1--- libxml2-2.7.8/dict.c 2010-10-12 08:25:31.000000000 +0200 2+++ libxml2-2.7.8.patched/dict.c 2012-09-28 12:08:37.432414664 +0200 3@@ -2,7 +2,7 @@ 4 * dict.c: dictionary of reusable strings, just used to avoid allocation 5 * and freeing operations. 6 * 7- * Copyright (C) 2003 Daniel Veillard. 8+ * Copyright (C) 2003-2012 Daniel Veillard. 9 * 10 * Permission to use, copy, modify, and distribute this software for any 11 * purpose with or without fee is hereby granted, provided that the above 12@@ -19,6 +19,28 @@ 13 #define IN_LIBXML 14 #include "libxml.h" 15 16+#ifdef HAVE_STDLIB_H 17+#include <stdlib.h> 18+#endif 19+#ifdef HAVE_TIME_H 20+#include <time.h> 21+#endif 22+ 23+/* 24+ * Following http://www.ocert.org/advisories/ocert-2011-003.html 25+ * it seems that having hash randomization might be a good idea 26+ * when using XML with untrusted data 27+ * Note1: that it works correctly only if compiled with WITH_BIG_KEY 28+ * which is the default. 29+ * Note2: the fast function used for a small dict won't protect very 30+ * well but since the attack is based on growing a very big hash 31+ * list we will use the BigKey algo as soon as the hash size grows 32+ * over MIN_DICT_SIZE so this actually works 33+ */ 34+#if defined(HAVE_RAND) && defined(HAVE_SRAND) && defined(HAVE_TIME) 35+#define DICT_RANDOMIZATION 36+#endif 37+ 38 #include <string.h> 39 #ifdef HAVE_STDINT_H 40 #include <stdint.h> 41@@ -44,23 +66,23 @@ 42 #define WITH_BIG_KEY 43 44 #ifdef WITH_BIG_KEY 45-#define xmlDictComputeKey(dict, name, len) \ 46- (((dict)->size == MIN_DICT_SIZE) ? \ 47- xmlDictComputeFastKey(name, len) : \ 48- xmlDictComputeBigKey(name, len)) 49- 50-#define xmlDictComputeQKey(dict, prefix, plen, name, len) \ 51- (((prefix) == NULL) ? \ 52- (xmlDictComputeKey(dict, name, len)) : \ 53- (((dict)->size == MIN_DICT_SIZE) ? \ 54- xmlDictComputeFastQKey(prefix, plen, name, len) : \ 55- xmlDictComputeBigQKey(prefix, plen, name, len))) 56+#define xmlDictComputeKey(dict, name, len) \ 57+ (((dict)->size == MIN_DICT_SIZE) ? \ 58+ xmlDictComputeFastKey(name, len, (dict)->seed) : \ 59+ xmlDictComputeBigKey(name, len, (dict)->seed)) 60+ 61+#define xmlDictComputeQKey(dict, prefix, plen, name, len) \ 62+ (((prefix) == NULL) ? \ 63+ (xmlDictComputeKey(dict, name, len)) : \ 64+ (((dict)->size == MIN_DICT_SIZE) ? \ 65+ xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed) : \ 66+ xmlDictComputeBigQKey(prefix, plen, name, len, (dict)->seed))) 67 68 #else /* !WITH_BIG_KEY */ 69-#define xmlDictComputeKey(dict, name, len) \ 70- xmlDictComputeFastKey(name, len) 71-#define xmlDictComputeQKey(dict, prefix, plen, name, len) \ 72- xmlDictComputeFastQKey(prefix, plen, name, len) 73+#define xmlDictComputeKey(dict, name, len) \ 74+ xmlDictComputeFastKey(name, len, (dict)->seed) 75+#define xmlDictComputeQKey(dict, prefix, plen, name, len) \ 76+ xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed) 77 #endif /* WITH_BIG_KEY */ 78 79 /* 80@@ -98,6 +120,8 @@ 81 xmlDictStringsPtr strings; 82 83 struct _xmlDict *subdict; 84+ /* used for randomization */ 85+ int seed; 86 }; 87 88 /* 89@@ -125,6 +149,9 @@ 90 if ((xmlDictMutex = xmlNewRMutex()) == NULL) 91 return(0); 92 93+#ifdef DICT_RANDOMIZATION 94+ srand(time(NULL)); 95+#endif 96 xmlDictInitialized = 1; 97 return(1); 98 } 99@@ -277,13 +304,13 @@ 100 */ 101 102 static uint32_t 103-xmlDictComputeBigKey(const xmlChar* data, int namelen) { 104+xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) { 105 uint32_t hash; 106 int i; 107 108 if (namelen <= 0 || data == NULL) return(0); 109 110- hash = 0; 111+ hash = seed; 112 113 for (i = 0;i < namelen; i++) { 114 hash += data[i]; 115@@ -310,12 +337,12 @@ 116 */ 117 static unsigned long 118 xmlDictComputeBigQKey(const xmlChar *prefix, int plen, 119- const xmlChar *name, int len) 120+ const xmlChar *name, int len, int seed) 121 { 122 uint32_t hash; 123 int i; 124 125- hash = 0; 126+ hash = seed; 127 128 for (i = 0;i < plen; i++) { 129 hash += prefix[i]; 130@@ -346,8 +373,8 @@ 131 * for low hash table fill. 132 */ 133 static unsigned long 134-xmlDictComputeFastKey(const xmlChar *name, int namelen) { 135- unsigned long value = 0L; 136+xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) { 137+ unsigned long value = seed; 138 139 if (name == NULL) return(0); 140 value = *name; 141@@ -381,9 +408,9 @@ 142 */ 143 static unsigned long 144 xmlDictComputeFastQKey(const xmlChar *prefix, int plen, 145- const xmlChar *name, int len) 146+ const xmlChar *name, int len, int seed) 147 { 148- unsigned long value = 0L; 149+ unsigned long value = (unsigned long) seed; 150 151 if (plen == 0) 152 value += 30 * (unsigned long) ':'; 153@@ -460,6 +487,11 @@ 154 dict->subdict = NULL; 155 if (dict->dict) { 156 memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry)); 157+#ifdef DICT_RANDOMIZATION 158+ dict->seed = rand(); 159+#else 160+ dict->seed = 0; 161+#endif 162 return(dict); 163 } 164 xmlFree(dict); 165@@ -486,6 +518,7 @@ 166 #ifdef DICT_DEBUG_PATTERNS 167 fprintf(stderr, "R"); 168 #endif 169+ dict->seed = sub->seed; 170 dict->subdict = sub; 171 xmlDictReference(dict->subdict); 172 } 173--- libxml2-2.7.8/encoding.c 2010-11-04 17:40:06.000000000 +0100 174+++ libxml2-2.7.8.patched/encoding.c 2012-09-28 12:08:37.440414665 +0200 175@@ -1928,7 +1928,7 @@ 176 if (in == NULL) return(-1); 177 178 /* calculate space available */ 179- written = out->size - out->use; 180+ written = out->size - out->use - 1; /* count '\0' */ 181 toconv = in->use; 182 /* 183 * echo '<?xml version="1.0" encoding="UCS4"?>' | wc -c => 38 184@@ -2059,7 +2059,7 @@ 185 toconv = in->use; 186 if (toconv == 0) 187 return (0); 188- written = out->size - out->use; 189+ written = out->size - out->use - 1; /* count '\0' */ 190 if (toconv * 2 >= written) { 191 xmlBufferGrow(out, out->size + toconv * 2); 192 written = out->size - out->use - 1; 193--- libxml2-2.7.8/entities.c 2010-10-12 08:25:32.000000000 +0200 194+++ libxml2-2.7.8.patched/entities.c 2012-09-28 12:08:37.432414664 +0200 195@@ -528,13 +528,13 @@ 196 * Macro used to grow the current buffer. 197 */ 198 #define growBufferReentrant() { \ 199- buffer_size *= 2; \ 200- buffer = (xmlChar *) \ 201- xmlRealloc(buffer, buffer_size * sizeof(xmlChar)); \ 202- if (buffer == NULL) { \ 203- xmlEntitiesErrMemory("xmlEncodeEntitiesReentrant: realloc failed");\ 204- return(NULL); \ 205- } \ 206+ xmlChar *tmp; \ 207+ size_t new_size = buffer_size * 2; \ 208+ if (new_size < buffer_size) goto mem_error; \ 209+ tmp = (xmlChar *) xmlRealloc(buffer, new_size); \ 210+ if (tmp == NULL) goto mem_error; \ 211+ buffer = tmp; \ 212+ buffer_size = new_size; \ 213 } 214 215 216@@ -555,7 +555,7 @@ 217 const xmlChar *cur = input; 218 xmlChar *buffer = NULL; 219 xmlChar *out = NULL; 220- int buffer_size = 0; 221+ size_t buffer_size = 0; 222 int html = 0; 223 224 if (input == NULL) return(NULL); 225@@ -574,8 +574,8 @@ 226 out = buffer; 227 228 while (*cur != '\0') { 229- if (out - buffer > buffer_size - 100) { 230- int indx = out - buffer; 231+ size_t indx = out - buffer; 232+ if (indx + 100 > buffer_size) { 233 234 growBufferReentrant(); 235 out = &buffer[indx]; 236@@ -692,6 +692,11 @@ 237 } 238 *out = 0; 239 return(buffer); 240+ 241+mem_error: 242+ xmlEntitiesErrMemory("xmlEncodeEntitiesReentrant: realloc failed"); 243+ xmlFree(buffer); 244+ return(NULL); 245 } 246 247 /** 248@@ -709,7 +714,7 @@ 249 const xmlChar *cur = input; 250 xmlChar *buffer = NULL; 251 xmlChar *out = NULL; 252- int buffer_size = 0; 253+ size_t buffer_size = 0; 254 if (input == NULL) return(NULL); 255 256 /* 257@@ -724,8 +729,8 @@ 258 out = buffer; 259 260 while (*cur != '\0') { 261- if (out - buffer > buffer_size - 10) { 262- int indx = out - buffer; 263+ size_t indx = out - buffer; 264+ if (indx + 10 > buffer_size) { 265 266 growBufferReentrant(); 267 out = &buffer[indx]; 268@@ -774,6 +779,11 @@ 269 } 270 *out = 0; 271 return(buffer); 272+ 273+mem_error: 274+ xmlEntitiesErrMemory("xmlEncodeSpecialChars: realloc failed"); 275+ xmlFree(buffer); 276+ return(NULL); 277 } 278 279 /** 280--- libxml2-2.7.8/hash.c 2010-10-12 08:25:32.000000000 +0200 281+++ libxml2-2.7.8.patched/hash.c 2012-09-28 12:08:37.392414663 +0200 282@@ -3,7 +3,7 @@ 283 * 284 * Reference: Your favorite introductory book on algorithms 285 * 286- * Copyright (C) 2000 Bjorn Reese and Daniel Veillard. 287+ * Copyright (C) 2000,2012 Bjorn Reese and Daniel Veillard. 288 * 289 * Permission to use, copy, modify, and distribute this software for any 290 * purpose with or without fee is hereby granted, provided that the above 291@@ -21,6 +21,22 @@ 292 #include "libxml.h" 293 294 #include <string.h> 295+#ifdef HAVE_STDLIB_H 296+#include <stdlib.h> 297+#endif 298+#ifdef HAVE_TIME_H 299+#include <time.h> 300+#endif 301+ 302+/* 303+ * Following http://www.ocert.org/advisories/ocert-2011-003.html 304+ * it seems that having hash randomization might be a good idea 305+ * when using XML with untrusted data 306+ */ 307+#if defined(HAVE_RAND) && defined(HAVE_SRAND) && defined(HAVE_TIME) 308+#define HASH_RANDOMIZATION 309+#endif 310+ 311 #include <libxml/parser.h> 312 #include <libxml/hash.h> 313 #include <libxml/xmlmemory.h> 314@@ -31,6 +47,10 @@ 315 316 /* #define DEBUG_GROW */ 317 318+#ifdef HASH_RANDOMIZATION 319+static int hash_initialized = 0; 320+#endif 321+ 322 /* 323 * A single entry in the hash table 324 */ 325@@ -53,6 +73,9 @@ 326 int size; 327 int nbElems; 328 xmlDictPtr dict; 329+#ifdef HASH_RANDOMIZATION 330+ int random_seed; 331+#endif 332 }; 333 334 /* 335@@ -65,6 +88,9 @@ 336 unsigned long value = 0L; 337 char ch; 338 339+#ifdef HASH_RANDOMIZATION 340+ value = table->random_seed; 341+#endif 342 if (name != NULL) { 343 value += 30 * (*name); 344 while ((ch = *name++) != 0) { 345@@ -92,6 +118,9 @@ 346 unsigned long value = 0L; 347 char ch; 348 349+#ifdef HASH_RANDOMIZATION 350+ value = table->random_seed; 351+#endif 352 if (prefix != NULL) 353 value += 30 * (*prefix); 354 else 355@@ -156,6 +185,13 @@ 356 table->table = xmlMalloc(size * sizeof(xmlHashEntry)); 357 if (table->table) { 358 memset(table->table, 0, size * sizeof(xmlHashEntry)); 359+#ifdef HASH_RANDOMIZATION 360+ if (!hash_initialized) { 361+ srand(time(NULL)); 362+ hash_initialized = 1; 363+ } 364+ table->random_seed = rand(); 365+#endif 366 return(table); 367 } 368 xmlFree(table); 369--- libxml2-2.7.8/parser.c 2010-11-04 16:55:45.000000000 +0100 370+++ libxml2-2.7.8.patched/parser.c 2012-09-28 12:08:37.440414665 +0200 371@@ -40,6 +40,7 @@ 372 #endif 373 374 #include <stdlib.h> 375+#include <limits.h> 376 #include <string.h> 377 #include <stdarg.h> 378 #include <libxml/xmlmemory.h> 379@@ -114,10 +115,10 @@ 380 * parser option. 381 */ 382 static int 383-xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long size, 384+xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size, 385 xmlEntityPtr ent) 386 { 387- unsigned long consumed = 0; 388+ size_t consumed = 0; 389 390 if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE)) 391 return (0); 392@@ -2580,15 +2581,17 @@ 393 394 /* 395 * Macro used to grow the current buffer. 396+ * buffer##_size is expected to be a size_t 397+ * mem_error: is expected to handle memory allocation failures 398 */ 399 #define growBuffer(buffer, n) { \ 400 xmlChar *tmp; \ 401- buffer##_size *= 2; \ 402- buffer##_size += n; \ 403- tmp = (xmlChar *) \ 404- xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \ 405+ size_t new_size = buffer##_size * 2 + n; \ 406+ if (new_size < buffer##_size) goto mem_error; \ 407+ tmp = (xmlChar *) xmlRealloc(buffer, new_size); \ 408 if (tmp == NULL) goto mem_error; \ 409 buffer = tmp; \ 410+ buffer##_size = new_size; \ 411 } 412 413 /** 414@@ -2614,14 +2617,14 @@ 415 xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, 416 int what, xmlChar end, xmlChar end2, xmlChar end3) { 417 xmlChar *buffer = NULL; 418- int buffer_size = 0; 419+ size_t buffer_size = 0; 420+ size_t nbchars = 0; 421 422 xmlChar *current = NULL; 423 xmlChar *rep = NULL; 424 const xmlChar *last; 425 xmlEntityPtr ent; 426 int c,l; 427- int nbchars = 0; 428 429 if ((ctxt == NULL) || (str == NULL) || (len < 0)) 430 return(NULL); 431@@ -2638,7 +2641,7 @@ 432 * allocate a translation buffer. 433 */ 434 buffer_size = XML_PARSER_BIG_BUFFER_SIZE; 435- buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar)); 436+ buffer = (xmlChar *) xmlMallocAtomic(buffer_size); 437 if (buffer == NULL) goto mem_error; 438 439 /* 440@@ -2658,7 +2661,7 @@ 441 if (val != 0) { 442 COPY_BUF(0,buffer,nbchars,val); 443 } 444- if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { 445+ if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { 446 growBuffer(buffer, XML_PARSER_BUFFER_SIZE); 447 } 448 } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) { 449@@ -2676,7 +2679,7 @@ 450 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { 451 if (ent->content != NULL) { 452 COPY_BUF(0,buffer,nbchars,ent->content[0]); 453- if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { 454+ if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { 455 growBuffer(buffer, XML_PARSER_BUFFER_SIZE); 456 } 457 } else { 458@@ -2693,8 +2696,7 @@ 459 current = rep; 460 while (*current != 0) { /* non input consuming loop */ 461 buffer[nbchars++] = *current++; 462- if (nbchars > 463- buffer_size - XML_PARSER_BUFFER_SIZE) { 464+ if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { 465 if (xmlParserEntityCheck(ctxt, nbchars, ent)) 466 goto int_error; 467 growBuffer(buffer, XML_PARSER_BUFFER_SIZE); 468@@ -2708,8 +2710,8 @@ 469 const xmlChar *cur = ent->name; 470 471 buffer[nbchars++] = '&'; 472- if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) { 473- growBuffer(buffer, XML_PARSER_BUFFER_SIZE); 474+ if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) { 475+ growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE); 476 } 477 for (;i > 0;i--) 478 buffer[nbchars++] = *cur++; 479@@ -2736,8 +2738,7 @@ 480 current = rep; 481 while (*current != 0) { /* non input consuming loop */ 482 buffer[nbchars++] = *current++; 483- if (nbchars > 484- buffer_size - XML_PARSER_BUFFER_SIZE) { 485+ if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { 486 if (xmlParserEntityCheck(ctxt, nbchars, ent)) 487 goto int_error; 488 growBuffer(buffer, XML_PARSER_BUFFER_SIZE); 489@@ -2750,8 +2751,8 @@ 490 } else { 491 COPY_BUF(l,buffer,nbchars,c); 492 str += l; 493- if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { 494- growBuffer(buffer, XML_PARSER_BUFFER_SIZE); 495+ if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { 496+ growBuffer(buffer, XML_PARSER_BUFFER_SIZE); 497 } 498 } 499 if (str < last) 500@@ -3755,8 +3756,8 @@ 501 xmlChar limit = 0; 502 xmlChar *buf = NULL; 503 xmlChar *rep = NULL; 504- int len = 0; 505- int buf_size = 0; 506+ size_t len = 0; 507+ size_t buf_size = 0; 508 int c, l, in_space = 0; 509 xmlChar *current = NULL; 510 xmlEntityPtr ent; 511@@ -3778,7 +3779,7 @@ 512 * allocate a translation buffer. 513 */ 514 buf_size = XML_PARSER_BUFFER_SIZE; 515- buf = (xmlChar *) xmlMallocAtomic(buf_size * sizeof(xmlChar)); 516+ buf = (xmlChar *) xmlMallocAtomic(buf_size); 517 if (buf == NULL) goto mem_error; 518 519 /* 520@@ -3795,7 +3796,7 @@ 521 522 if (val == '&') { 523 if (ctxt->replaceEntities) { 524- if (len > buf_size - 10) { 525+ if (len + 10 > buf_size) { 526 growBuffer(buf, 10); 527 } 528 buf[len++] = '&'; 529@@ -3804,7 +3805,7 @@ 530 * The reparsing will be done in xmlStringGetNodeList() 531 * called by the attribute() function in SAX.c 532 */ 533- if (len > buf_size - 10) { 534+ if (len + 10 > buf_size) { 535 growBuffer(buf, 10); 536 } 537 buf[len++] = '&'; 538@@ -3814,7 +3815,7 @@ 539 buf[len++] = ';'; 540 } 541 } else if (val != 0) { 542- if (len > buf_size - 10) { 543+ if (len + 10 > buf_size) { 544 growBuffer(buf, 10); 545 } 546 len += xmlCopyChar(0, &buf[len], val); 547@@ -3826,7 +3827,7 @@ 548 ctxt->nbentities += ent->owner; 549 if ((ent != NULL) && 550 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { 551- if (len > buf_size - 10) { 552+ if (len + 10 > buf_size) { 553 growBuffer(buf, 10); 554 } 555 if ((ctxt->replaceEntities == 0) && 556@@ -3854,7 +3855,7 @@ 557 current++; 558 } else 559 buf[len++] = *current++; 560- if (len > buf_size - 10) { 561+ if (len + 10 > buf_size) { 562 growBuffer(buf, 10); 563 } 564 } 565@@ -3862,7 +3863,7 @@ 566 rep = NULL; 567 } 568 } else { 569- if (len > buf_size - 10) { 570+ if (len + 10 > buf_size) { 571 growBuffer(buf, 10); 572 } 573 if (ent->content != NULL) 574@@ -3890,7 +3891,7 @@ 575 * Just output the reference 576 */ 577 buf[len++] = '&'; 578- while (len > buf_size - i - 10) { 579+ while (len + i + 10 > buf_size) { 580 growBuffer(buf, i + 10); 581 } 582 for (;i > 0;i--) 583@@ -3903,7 +3904,7 @@ 584 if ((len != 0) || (!normalize)) { 585 if ((!normalize) || (!in_space)) { 586 COPY_BUF(l,buf,len,0x20); 587- while (len > buf_size - 10) { 588+ while (len + 10 > buf_size) { 589 growBuffer(buf, 10); 590 } 591 } 592@@ -3912,7 +3913,7 @@ 593 } else { 594 in_space = 0; 595 COPY_BUF(l,buf,len,c); 596- if (len > buf_size - 10) { 597+ if (len + 10 > buf_size) { 598 growBuffer(buf, 10); 599 } 600 } 601@@ -3937,7 +3938,18 @@ 602 } 603 } else 604 NEXT; 605- if (attlen != NULL) *attlen = len; 606+ 607+ /* 608+ * There we potentially risk an overflow, don't allow attribute value of 609+ * lenght more than INT_MAX it is a very reasonnable assumption ! 610+ */ 611+ if (len >= INT_MAX) { 612+ xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, 613+ "AttValue lenght too long\n"); 614+ goto mem_error; 615+ } 616+ 617+ if (attlen != NULL) *attlen = (int) len; 618 return(buf); 619 620 mem_error: 621@@ -4949,7 +4961,8 @@ 622 (ctxt->sax->processingInstruction != NULL)) 623 ctxt->sax->processingInstruction(ctxt->userData, 624 target, NULL); 625- ctxt->instate = state; 626+ if (ctxt->instate != XML_PARSER_EOF) 627+ ctxt->instate = state; 628 return; 629 } 630 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); 631@@ -5029,7 +5042,8 @@ 632 } else { 633 xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL); 634 } 635- ctxt->instate = state; 636+ if (ctxt->instate != XML_PARSER_EOF) 637+ ctxt->instate = state; 638 } 639 } 640 641@@ -9588,6 +9602,8 @@ 642 else 643 name = xmlParseStartTag(ctxt); 644 #endif /* LIBXML_SAX1_ENABLED */ 645+ if (ctxt->instate == XML_PARSER_EOF) 646+ return; 647 if (name == NULL) { 648 spacePop(ctxt); 649 return; 650@@ -10967,6 +10983,8 @@ 651 else 652 name = xmlParseStartTag(ctxt); 653 #endif /* LIBXML_SAX1_ENABLED */ 654+ if (ctxt->instate == XML_PARSER_EOF) 655+ goto done; 656 if (name == NULL) { 657 spacePop(ctxt); 658 ctxt->instate = XML_PARSER_EOF; 659@@ -11153,7 +11171,9 @@ 660 else 661 xmlParseEndTag1(ctxt, 0); 662 #endif /* LIBXML_SAX1_ENABLED */ 663- if (ctxt->nameNr == 0) { 664+ if (ctxt->instate == XML_PARSER_EOF) { 665+ /* Nothing */ 666+ } else if (ctxt->nameNr == 0) { 667 ctxt->instate = XML_PARSER_EPILOG; 668 } else { 669 ctxt->instate = XML_PARSER_CONTENT; 670--- libxml2-2.7.8/xmllint.c 2010-11-03 15:49:11.000000000 +0100 671+++ libxml2-2.7.8.patched/xmllint.c 2012-09-28 12:08:37.436414665 +0200 672@@ -2976,7 +2976,7 @@ 673 printf("\t--huge : remove any internal arbitrary parser limits\n"); 674 printf("\t--noent : substitute entity references by their value\n"); 675 printf("\t--noout : don't output the result tree\n"); 676- printf("\t--path 'paths': provide a set of paths for resources\n"); 677+ printf("\t--path 'paths' : provide a set of paths for resources\n"); 678 printf("\t--load-trace : print trace of all external entites loaded\n"); 679 printf("\t--nonet : refuse to fetch DTDs or entities over network\n"); 680 printf("\t--nocompact : do not generate compact text nodes\n"); 681@@ -3032,7 +3032,7 @@ 682 printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n"); 683 printf("\t otherwise XML Catalogs starting from \n"); 684 printf("\t %s are activated by default\n", XML_XML_DEFAULT_CATALOG); 685- printf("\t--nocatalogs: deactivate all catalogs\n"); 686+ printf("\t--nocatalogs : deactivate all catalogs\n"); 687 #endif 688 printf("\t--auto : generate a small doc on the fly\n"); 689 #ifdef LIBXML_XINCLUDE_ENABLED 690--- libxml2-2.7.8/xpath.c 2010-11-03 20:18:27.000000000 +0100 691+++ libxml2-2.7.8.patched/xpath.c 2012-09-28 12:08:37.444414664 +0200 692@@ -252,6 +252,7 @@ 693 "Encoding error\n", 694 "Char out of XML range\n", 695 "Invalid or incomplete context\n", 696+ "Stack usage errror\n", 697 "?? Unknown error ??\n" /* Must be last in the list! */ 698 }; 699 #define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \ 700@@ -2398,6 +2399,42 @@ 701 ************************************************************************/ 702 703 /** 704+ * xmlXPathSetFrame: 705+ * @ctxt: an XPath parser context 706+ * 707+ * Set the callee evaluation frame 708+ * 709+ * Returns the previous frame value to be restored once done 710+ */ 711+static int 712+xmlXPathSetFrame(xmlXPathParserContextPtr ctxt) { 713+ int ret; 714+ 715+ if (ctxt == NULL) 716+ return(0); 717+ ret = ctxt->valueFrame; 718+ ctxt->valueFrame = ctxt->valueNr; 719+ return(ret); 720+} 721+ 722+/** 723+ * xmlXPathPopFrame: 724+ * @ctxt: an XPath parser context 725+ * @frame: the previous frame value 726+ * 727+ * Remove the callee evaluation frame 728+ */ 729+static void 730+xmlXPathPopFrame(xmlXPathParserContextPtr ctxt, int frame) { 731+ if (ctxt == NULL) 732+ return; 733+ if (ctxt->valueNr < ctxt->valueFrame) { 734+ xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR); 735+ } 736+ ctxt->valueFrame = frame; 737+} 738+ 739+/** 740 * valuePop: 741 * @ctxt: an XPath evaluation context 742 * 743@@ -2412,6 +2449,12 @@ 744 745 if ((ctxt == NULL) || (ctxt->valueNr <= 0)) 746 return (NULL); 747+ 748+ if (ctxt->valueNr <= ctxt->valueFrame) { 749+ xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR); 750+ return (NULL); 751+ } 752+ 753 ctxt->valueNr--; 754 if (ctxt->valueNr > 0) 755 ctxt->value = ctxt->valueTab[ctxt->valueNr - 1]; 756@@ -3522,13 +3565,13 @@ 757 } else if (cur->nodeNr == cur->nodeMax) { 758 xmlNodePtr *temp; 759 760- cur->nodeMax *= 2; 761- temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 762+ temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 * 763 sizeof(xmlNodePtr)); 764 if (temp == NULL) { 765 xmlXPathErrMemory(NULL, "growing nodeset\n"); 766 return; 767 } 768+ cur->nodeMax *= 2; 769 cur->nodeTab = temp; 770 } 771 cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns); 772@@ -3627,14 +3670,14 @@ 773 } else if (cur->nodeNr == cur->nodeMax) { 774 xmlNodePtr *temp; 775 776- cur->nodeMax *= 2; 777- temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 778+ temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 * 779 sizeof(xmlNodePtr)); 780 if (temp == NULL) { 781 xmlXPathErrMemory(NULL, "growing nodeset\n"); 782 return; 783 } 784 cur->nodeTab = temp; 785+ cur->nodeMax *= 2; 786 } 787 if (val->type == XML_NAMESPACE_DECL) { 788 xmlNsPtr ns = (xmlNsPtr) val; 789@@ -3738,14 +3781,14 @@ 790 } else if (val1->nodeNr == val1->nodeMax) { 791 xmlNodePtr *temp; 792 793- val1->nodeMax *= 2; 794- temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 795+ temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 2 * 796 sizeof(xmlNodePtr)); 797 if (temp == NULL) { 798 xmlXPathErrMemory(NULL, "merging nodeset\n"); 799 return(NULL); 800 } 801 val1->nodeTab = temp; 802+ val1->nodeMax *= 2; 803 } 804 if (n2->type == XML_NAMESPACE_DECL) { 805 xmlNsPtr ns = (xmlNsPtr) n2; 806@@ -3907,14 +3950,14 @@ 807 } else if (set1->nodeNr >= set1->nodeMax) { 808 xmlNodePtr *temp; 809 810- set1->nodeMax *= 2; 811 temp = (xmlNodePtr *) xmlRealloc( 812- set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr)); 813+ set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr)); 814 if (temp == NULL) { 815 xmlXPathErrMemory(NULL, "merging nodeset\n"); 816 return(NULL); 817 } 818 set1->nodeTab = temp; 819+ set1->nodeMax *= 2; 820 } 821 if (n2->type == XML_NAMESPACE_DECL) { 822 xmlNsPtr ns = (xmlNsPtr) n2; 823@@ -3991,14 +4034,14 @@ 824 } else if (set1->nodeNr >= set1->nodeMax) { 825 xmlNodePtr *temp; 826 827- set1->nodeMax *= 2; 828 temp = (xmlNodePtr *) xmlRealloc( 829- set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr)); 830+ set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr)); 831 if (temp == NULL) { 832 xmlXPathErrMemory(NULL, "merging nodeset\n"); 833 return(NULL); 834 } 835 set1->nodeTab = temp; 836+ set1->nodeMax *= 2; 837 } 838 set1->nodeTab[set1->nodeNr++] = n2; 839 } 840@@ -6154,6 +6197,7 @@ 841 ret->valueNr = 0; 842 ret->valueMax = 10; 843 ret->value = NULL; 844+ ret->valueFrame = 0; 845 846 ret->context = ctxt; 847 ret->comp = comp; 848@@ -11712,6 +11756,7 @@ 849 xmlXPathObjectPtr contextObj = NULL, exprRes = NULL; 850 xmlNodePtr oldContextNode, contextNode = NULL; 851 xmlXPathContextPtr xpctxt = ctxt->context; 852+ int frame; 853 854 #ifdef LIBXML_XPTR_ENABLED 855 /* 856@@ -11731,6 +11776,8 @@ 857 */ 858 exprOp = &ctxt->comp->steps[op->ch2]; 859 for (i = 0; i < set->nodeNr; i++) { 860+ xmlXPathObjectPtr tmp; 861+ 862 if (set->nodeTab[i] == NULL) 863 continue; 864 865@@ -11758,18 +11805,25 @@ 866 xmlXPathNodeSetAddUnique(contextObj->nodesetval, 867 contextNode); 868 869+ frame = xmlXPathSetFrame(ctxt); 870 valuePush(ctxt, contextObj); 871 res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1); 872+ tmp = valuePop(ctxt); 873+ xmlXPathPopFrame(ctxt, frame); 874 875 if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) { 876- xmlXPathObjectPtr tmp; 877- /* pop the result */ 878- tmp = valuePop(ctxt); 879- xmlXPathReleaseObject(xpctxt, tmp); 880- /* then pop off contextObj, which will be freed later */ 881- valuePop(ctxt); 882+ while (tmp != contextObj) { 883+ /* 884+ * Free up the result 885+ * then pop off contextObj, which will be freed later 886+ */ 887+ xmlXPathReleaseObject(xpctxt, tmp); 888+ tmp = valuePop(ctxt); 889+ } 890 goto evaluation_error; 891 } 892+ /* push the result back onto the stack */ 893+ valuePush(ctxt, tmp); 894 895 if (res) 896 pos++; 897@@ -13357,6 +13411,7 @@ 898 xmlGenericError(xmlGenericErrorContext, 899 "xmlXPathCompOpEval: variable %s bound to undefined prefix %s\n", 900 (char *) op->value4, (char *)op->value5); 901+ ctxt->error = XPATH_UNDEF_PREFIX_ERROR; 902 return (total); 903 } 904 val = xmlXPathVariableLookupNS(ctxt->context, 905@@ -13373,7 +13428,9 @@ 906 xmlXPathFunction func; 907 const xmlChar *oldFunc, *oldFuncURI; 908 int i; 909+ int frame; 910 911+ frame = xmlXPathSetFrame(ctxt); 912 if (op->ch1 != -1) 913 total += 914 xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); 915@@ -13381,15 +13438,18 @@ 916 xmlGenericError(xmlGenericErrorContext, 917 "xmlXPathCompOpEval: parameter error\n"); 918 ctxt->error = XPATH_INVALID_OPERAND; 919+ xmlXPathPopFrame(ctxt, frame); 920 return (total); 921 } 922- for (i = 0; i < op->value; i++) 923+ for (i = 0; i < op->value; i++) { 924 if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) { 925 xmlGenericError(xmlGenericErrorContext, 926 "xmlXPathCompOpEval: parameter error\n"); 927 ctxt->error = XPATH_INVALID_OPERAND; 928+ xmlXPathPopFrame(ctxt, frame); 929 return (total); 930 } 931+ } 932 if (op->cache != NULL) 933 XML_CAST_FPTR(func) = op->cache; 934 else { 935@@ -13405,6 +13465,8 @@ 936 xmlGenericError(xmlGenericErrorContext, 937 "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n", 938 (char *)op->value4, (char *)op->value5); 939+ ctxt->error = XPATH_UNDEF_PREFIX_ERROR; 940+ xmlXPathPopFrame(ctxt, frame); 941 return (total); 942 } 943 func = xmlXPathFunctionLookupNS(ctxt->context, 944@@ -13426,6 +13488,7 @@ 945 func(ctxt, op->value); 946 ctxt->context->function = oldFunc; 947 ctxt->context->functionURI = oldFuncURI; 948+ xmlXPathPopFrame(ctxt, frame); 949 return (total); 950 } 951 case XPATH_OP_ARG: 952@@ -14329,6 +14392,7 @@ 953 ctxt->valueNr = 0; 954 ctxt->valueMax = 10; 955 ctxt->value = NULL; 956+ ctxt->valueFrame = 0; 957 } 958 #ifdef XPATH_STREAMING 959 if (ctxt->comp->stream) { 960--- libxml2-2.7.8/xpointer.c 2010-10-12 08:25:33.000000000 +0200 961+++ libxml2-2.7.8.patched/xpointer.c 2012-09-28 12:08:37.428414664 +0200 962@@ -1007,21 +1007,14 @@ 963 NEXT; 964 break; 965 } 966- *cur++ = CUR; 967 } else if (CUR == '(') { 968 level++; 969- *cur++ = CUR; 970 } else if (CUR == '^') { 971- NEXT; 972- if ((CUR == ')') || (CUR == '(') || (CUR == '^')) { 973- *cur++ = CUR; 974- } else { 975- *cur++ = '^'; 976- *cur++ = CUR; 977- } 978- } else { 979- *cur++ = CUR; 980+ if ((NXT(1) == ')') || (NXT(1) == '(') || (NXT(1) == '^')) { 981+ NEXT; 982+ } 983 } 984+ *cur++ = CUR; 985 NEXT; 986 } 987 *cur = 0; 988@@ -1269,6 +1262,7 @@ 989 ctxt->valueNr = 0; 990 ctxt->valueMax = 10; 991 ctxt->value = NULL; 992+ ctxt->valueFrame = 0; 993 } 994 SKIP_BLANKS; 995 if (CUR == '/') { 996--- libxml2-2.7.8/libxml.h 2010-10-12 08:25:32.000000000 +0200 997+++ libxml2-2.7.8.patched/libxml.h 2012-09-28 12:08:37.432414664 +0200 998@@ -13,6 +13,9 @@ 999 #ifndef _LARGEFILE_SOURCE 1000 #define _LARGEFILE_SOURCE 1001 #endif 1002+#ifndef _LARGEFILE64_SOURCE 1003+#define _LARGEFILE64_SOURCE 1004+#endif 1005 #ifndef _FILE_OFFSET_BITS 1006 #define _FILE_OFFSET_BITS 64 1007 #endif 1008--- libxml2-2.7.8/include/libxml/xpath.h 2010-10-12 08:25:32.000000000 +0200 1009+++ libxml2-2.7.8.patched/include/libxml/xpath.h 2012-09-28 12:08:37.456414665 +0200 1010@@ -68,7 +68,8 @@ 1011 XPATH_UNDEF_PREFIX_ERROR, 1012 XPATH_ENCODING_ERROR, 1013 XPATH_INVALID_CHAR_ERROR, 1014- XPATH_INVALID_CTXT 1015+ XPATH_INVALID_CTXT, 1016+ XPATH_STACK_ERROR 1017 } xmlXPathError; 1018 1019 /* 1020@@ -380,6 +381,8 @@ 1021 xmlXPathCompExprPtr comp; /* the precompiled expression */ 1022 int xptr; /* it this an XPointer expression */ 1023 xmlNodePtr ancestor; /* used for walking preceding axis */ 1024+ 1025+ int valueFrame; /* used to limit Pop on the stack */ 1026 }; 1027 1028 /************************************************************************ 1029