From 1183b5668486030468b98e11c4abe0d054829223 Mon Sep 17 00:00:00 2001 From: Remi Pointel Date: Sun, 1 Apr 2012 18:52:02 +0000 Subject: update libexpat to 2.1.0. use arc4random instead of rand/srand in generate_hash_secret_salt, spotted by nicm@ and deraadt@. ok nicm@ deraadt@. --- lib/libexpat/Changes | 36 ++++++ lib/libexpat/README | 14 ++- lib/libexpat/doc/reference.html | 46 ++++++++ lib/libexpat/lib/expat.h | 39 ++++++- lib/libexpat/lib/xmlparse.c | 244 ++++++++++++++++++++++++++++------------ lib/libexpat/lib/xmltok_impl.c | 2 +- lib/libexpat/shlib_version | 2 +- 7 files changed, 302 insertions(+), 81 deletions(-) diff --git a/lib/libexpat/Changes b/lib/libexpat/Changes index fbda5279ce4..2f0f97ba3ce 100644 --- a/lib/libexpat/Changes +++ b/lib/libexpat/Changes @@ -1,3 +1,39 @@ +Release 2.1.0 Sat March 24 2012 + - Bug Fixes: + #1742315: Harmful XML_ParserCreateNS suggestion. + #2895533: CVE-2012-1147 - Resource leak in readfilemap.c. + #1785430: Expat build fails on linux-amd64 with gcc version>=4.1 -O3. + #1983953, 2517952, 2517962, 2649838: + Build modifications using autoreconf instead of buildconf.sh. + #2815947, #2884086: OBJEXT and EXEEXT support while building. + #1990430: CVE-2009-3720 - Parser crash with special UTF-8 sequences. + #2517938: xmlwf should return non-zero exit status if not well-formed. + #2517946: Wrong statement about XMLDecl in xmlwf.1 and xmlwf.sgml. + #2855609: Dangling positionPtr after error. + #2894085: CVE-2009-3560 - Buffer over-read and crash in big2_toUtf8(). + #2958794: CVE-2012-1148 - Memory leak in poolGrow. + #2990652: CMake support. + #3010819: UNEXPECTED_STATE with a trailing "%" in entity value. + #3206497: Unitialized memory returned from XML_Parse. + #3287849: make check fails on mingw-w64. + #3496608: CVE-2012-0876 - Hash DOS attack. + - Patches: + #1749198: pkg-config support. + #3010222: Fix for bug #3010819. + #3312568: CMake support. + #3446384: Report byte offsets for attr names and values. + - New Features / API changes: + Added new API member XML_SetHashSalt() that allows setting an intial + value (salt) for hash calculations. This is part of the fix for + bug #3496608 to randomize hash parameters. + When compiled with XML_ATTR_INFO defined, adds new API member + XML_GetAttributeInfo() that allows retrieving the byte + offsets for attribute names and values (patch #3446384). + Added CMake build system. + See bug #2990652 and patch #3312568. + Added run-benchmark target to Makefile.in - relies on testdata module + present in the same relative location as in the repository. + Release 2.0.1 Tue June 5 2007 - Fixed bugs #1515266, #1515600: The character data handler's calling of XML_StopParser() was not handled properly; if the parser was diff --git a/lib/libexpat/README b/lib/libexpat/README index fda282a8f54..1f88467d1b0 100644 --- a/lib/libexpat/README +++ b/lib/libexpat/README @@ -1,5 +1,5 @@ - Expat, Release 2.0.1 + Expat, Release 2.1.0 This is Expat, a C library for parsing XML, written by James Clark. Expat is a stream-oriented XML parser. This means that you register @@ -25,8 +25,7 @@ intended to be production grade software. If you are building Expat from a check-out from the CVS repository, you need to run a script that generates the configure script using the GNU autoconf and libtool tools. To do this, you need to have -autoconf 2.52 or newer and libtool 1.4 or newer (1.5 or newer preferred). -Run the script like this: +autoconf 2.58 or newer. Run the script like this: ./buildconf.sh @@ -65,8 +64,8 @@ location. Have a look at the "Makefile" to learn about additional the directories into which things will be installed. If you are interested in building Expat to provide document -information in UTF-16 rather than the default UTF-8, follow these -instructions (after having run "make distclean"): +information in UTF-16 encoding rather than the default UTF-8, follow +these instructions (after having run "make distclean"): 1. For UTF-16 output as unsigned short (and version/error strings as char), run: @@ -106,7 +105,10 @@ use DESTDIR=$(INSTALL_ROOT), even if DESTDIR eventually is defined in the environment, because variable-setting priority is 1) commandline 2) in-makefile -3) environment +3) environment + +Note: This only applies to the Expat library itself, building UTF-16 versions +of xmlwf and the tests is currently not supported. Note for Solaris users: The "ar" command is usually located in "/usr/ccs/bin", which is not in the default PATH. You will need to diff --git a/lib/libexpat/doc/reference.html b/lib/libexpat/doc/reference.html index c5f6c2c9432..8811a3397c7 100644 --- a/lib/libexpat/doc/reference.html +++ b/lib/libexpat/doc/reference.html @@ -129,8 +129,10 @@ interface.

  • XML_GetBase
  • XML_GetSpecifiedAttributeCount
  • XML_GetIdAttributeIndex
  • +
  • XML_GetAttributeInfo
  • XML_SetEncoding
  • XML_SetParamEntityParsing
  • +
  • XML_SetHashSalt
  • XML_UseForeignDTD
  • XML_SetReturnNSTriplet
  • XML_DefaultCurrent
  • @@ -369,6 +371,11 @@ footprint and can be faster. statically with the code that calls it; this is required to get all the right MSVC magic annotations correct. This is ignored on other platforms. + +
    XML_ATTR_INFO
    +
    If defined, makes the the additional function XML_GetAttributeInfo available +for reporting attribute byte offsets.

    @@ -2077,6 +2084,27 @@ attribute. If called inside a start handler, then that means the current call. +
    +const XML_AttrInfo * XMLCALL
    +XML_GetAttributeInfo(XML_Parser parser);
    +
    +
    +typedef struct {
    +  XML_Index  nameStart;  /* Offset to beginning of the attribute name. */
    +  XML_Index  nameEnd;    /* Offset after the attribute name's last byte. */
    +  XML_Index  valueStart; /* Offset to beginning of the attribute value. */
    +  XML_Index  valueEnd;   /* Offset after the attribute value's last byte. */
    +} XML_AttrInfo;
    +
    +
    +Returns an array of XML_AttrInfo structures for the +attribute/value pairs passed in the last call to the +XML_StartElementHandler that were specified +in the start-tag rather than defaulted. Each attribute/value pair counts +as 1; thus the number of entries in the array is +XML_GetSpecifiedAttributeCount(parser) / 2. +
    +
     enum XML_Status XMLCALL
     XML_SetEncoding(XML_Parser p,
    @@ -2107,6 +2135,24 @@ The choices for code are:
     
  • XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE
  • XML_PARAM_ENTITY_PARSING_ALWAYS
  • +Note: If XML_SetParamEntityParsing is called after +XML_Parse or XML_ParseBuffer, then it has +no effect and will always return 0. + + +
    +int XMLCALL
    +XML_SetHashSalt(XML_Parser p,
    +                unsigned long hash_salt);
    +
    +
    +Sets the hash salt to use for internal hash calculations. +Helps in preventing DoS attacks based on predicting hash +function behavior. In order to have an effect this must be called +before parsing has started. Returns 1 if successful, 0 when called +after XML_Parse or XML_ParseBuffer. +

    Note: This call is optional, as the parser will auto-generate a new +random salt value if no value has been set at the start of parsing.

    diff --git a/lib/libexpat/lib/expat.h b/lib/libexpat/lib/expat.h
    index 20a8278f78d..9a21680be46 100644
    --- a/lib/libexpat/lib/expat.h
    +++ b/lib/libexpat/lib/expat.h
    @@ -742,6 +742,29 @@ XML_GetSpecifiedAttributeCount(XML_Parser parser);
     XMLPARSEAPI(int)
     XML_GetIdAttributeIndex(XML_Parser parser);
     
    +#ifdef XML_ATTR_INFO
    +/* Source file byte offsets for the start and end of attribute names and values.
    +   The value indices are exclusive of surrounding quotes; thus in a UTF-8 source
    +   file an attribute value of "blah" will yield:
    +   info->valueEnd - info->valueStart = 4 bytes.
    +*/
    +typedef struct {
    +  XML_Index  nameStart;  /* Offset to beginning of the attribute name. */
    +  XML_Index  nameEnd;    /* Offset after the attribute name's last byte. */
    +  XML_Index  valueStart; /* Offset to beginning of the attribute value. */
    +  XML_Index  valueEnd;   /* Offset after the attribute value's last byte. */
    +} XML_AttrInfo;
    +
    +/* Returns an array of XML_AttrInfo structures for the attribute/value pairs
    +   passed in last call to the XML_StartElementHandler that were specified
    +   in the start-tag rather than defaulted. Each attribute/value pair counts
    +   as 1; thus the number of entries in the array is
    +   XML_GetSpecifiedAttributeCount(parser) / 2.
    +*/
    +XMLPARSEAPI(const XML_AttrInfo *)
    +XML_GetAttributeInfo(XML_Parser parser);
    +#endif
    +
     /* Parses some input. Returns XML_STATUS_ERROR if a fatal error is
        detected.  The last call to XML_Parse must have isFinal true; len
        may be zero for this call (or any other).
    @@ -883,6 +906,15 @@ XMLPARSEAPI(int)
     XML_SetParamEntityParsing(XML_Parser parser,
                               enum XML_ParamEntityParsing parsing);
     
    +/* Sets the hash salt to use for internal hash calculations.
    +   Helps in preventing DoS attacks based on predicting hash
    +   function behavior. This must be called before parsing is started.
    +   Returns 1 if successful, 0 when called after parsing has started.
    +*/
    +XMLPARSEAPI(int)
    +XML_SetHashSalt(XML_Parser parser,
    +                unsigned long hash_salt);
    +
     /* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then
        XML_GetErrorCode returns information about the error.
     */
    @@ -984,7 +1016,8 @@ enum XML_FeatureEnum {
       XML_FEATURE_SIZEOF_XML_CHAR,
       XML_FEATURE_SIZEOF_XML_LCHAR,
       XML_FEATURE_NS,
    -  XML_FEATURE_LARGE_SIZE
    +  XML_FEATURE_LARGE_SIZE,
    +  XML_FEATURE_ATTR_INFO
       /* Additional features must be added to the end of this enum. */
     };
     
    @@ -1004,8 +1037,8 @@ XML_GetFeatureList(void);
        change to major or minor version.
     */
     #define XML_MAJOR_VERSION 2
    -#define XML_MINOR_VERSION 0
    -#define XML_MICRO_VERSION 1
    +#define XML_MINOR_VERSION 1
    +#define XML_MICRO_VERSION 0
     
     #ifdef __cplusplus
     }
    diff --git a/lib/libexpat/lib/xmlparse.c b/lib/libexpat/lib/xmlparse.c
    index 15aa645ffcb..98cffbeb685 100644
    --- a/lib/libexpat/lib/xmlparse.c
    +++ b/lib/libexpat/lib/xmlparse.c
    @@ -5,6 +5,8 @@
     #include 
     #include                      /* memset(), memcpy() */
     #include 
    +#include                      /* UINT_MAX */
    +#include                        /* time() */
     
     #define XML_BUILDING_EXPAT 1
     
    @@ -391,12 +393,13 @@ static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
     static void
     dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
     static int
    -dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
    +dtdCopy(XML_Parser oldParser,
    +        DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
     static int
    -copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
    -
    +copyEntityTable(XML_Parser oldParser,
    +                HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
     static NAMED *
    -lookup(HASH_TABLE *table, KEY name, size_t createSize);
    +lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize);
     static void FASTCALL
     hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
     static void FASTCALL hashTableClear(HASH_TABLE *);
    @@ -429,11 +432,15 @@ static ELEMENT_TYPE *
     getElementType(XML_Parser parser, const ENCODING *enc,
                    const char *ptr, const char *end);
     
    +static unsigned long generate_hash_secret_salt(void);
    +static XML_Bool startParsing(XML_Parser parser);
    +
     static XML_Parser
     parserCreate(const XML_Char *encodingName,
                  const XML_Memory_Handling_Suite *memsuite,
                  const XML_Char *nameSep,
                  DTD *dtd);
    +
     static void
     parserInit(XML_Parser parser, const XML_Char *encodingName);
     
    @@ -533,6 +540,9 @@ struct XML_ParserStruct {
       NS_ATT *m_nsAtts;
       unsigned long m_nsAttsVersion;
       unsigned char m_nsAttsPower;
    +#ifdef XML_ATTR_INFO
    +  XML_AttrInfo *m_attInfo;
    +#endif
       POSITION m_position;
       STRING_POOL m_tempPool;
       STRING_POOL m_temp2Pool;
    @@ -546,6 +556,7 @@ struct XML_ParserStruct {
       XML_Bool m_useForeignDTD;
       enum XML_ParamEntityParsing m_paramEntityParsing;
     #endif
    +  unsigned long m_hash_secret_salt;
     };
     
     #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
    @@ -640,6 +651,7 @@ struct XML_ParserStruct {
     #define nsAtts (parser->m_nsAtts)
     #define nsAttsVersion (parser->m_nsAttsVersion)
     #define nsAttsPower (parser->m_nsAttsPower)
    +#define attInfo (parser->m_attInfo)
     #define tempPool (parser->m_tempPool)
     #define temp2Pool (parser->m_temp2Pool)
     #define groupConnector (parser->m_groupConnector)
    @@ -653,8 +665,7 @@ struct XML_ParserStruct {
     #define useForeignDTD (parser->m_useForeignDTD)
     #define paramEntityParsing (parser->m_paramEntityParsing)
     #endif /* XML_DTD */
    -
    -#define MAXLEN 0x7fffffff
    +#define hash_secret_salt (parser->m_hash_secret_salt)
     
     XML_Parser XMLCALL
     XML_ParserCreate(const XML_Char *encodingName)
    @@ -679,22 +690,33 @@ static const XML_Char implicitContext[] = {
       ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
     };
     
    +static unsigned long
    +generate_hash_secret_salt(void)
    +{
    +  return arc4random();
    +}
    +
    +static XML_Bool  /* only valid for root parser */
    +startParsing(XML_Parser parser)
    +{
    +    /* hash functions must be initialized before setContext() is called */
    +    if (hash_secret_salt == 0)
    +      hash_secret_salt = generate_hash_secret_salt();
    +    if (ns) {
    +      /* implicit context only set for root parser, since child
    +         parsers (i.e. external entity parsers) will inherit it
    +      */
    +      return setContext(parser, implicitContext);
    +    }
    +    return XML_TRUE;
    +}
    +
     XML_Parser XMLCALL
     XML_ParserCreate_MM(const XML_Char *encodingName,
                         const XML_Memory_Handling_Suite *memsuite,
                         const XML_Char *nameSep)
     {
    -  XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL);
    -  if (parser != NULL && ns) {
    -    /* implicit context only set for root parser, since child
    -       parsers (i.e. external entity parsers) will inherit it
    -    */
    -    if (!setContext(parser, implicitContext)) {
    -      XML_ParserFree(parser);
    -      return NULL;
    -    }
    -  }
    -  return parser;
    +  return parserCreate(encodingName, memsuite, nameSep, NULL);
     }
     
     static XML_Parser
    @@ -739,9 +761,20 @@ parserCreate(const XML_Char *encodingName,
         FREE(parser);
         return NULL;
       }
    +#ifdef XML_ATTR_INFO
    +  attInfo = (XML_AttrInfo*)MALLOC(attsSize * sizeof(XML_AttrInfo));
    +  if (attInfo == NULL) {
    +    FREE(atts);
    +    FREE(parser);
    +    return NULL;
    +  }
    +#endif
       dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
       if (dataBuf == NULL) {
         FREE(atts);
    +#ifdef XML_ATTR_INFO
    +    FREE(attInfo);
    +#endif
         FREE(parser);
         return NULL;
       }
    @@ -754,6 +787,9 @@ parserCreate(const XML_Char *encodingName,
         if (_dtd == NULL) {
           FREE(dataBuf);
           FREE(atts);
    +#ifdef XML_ATTR_INFO
    +      FREE(attInfo);
    +#endif
           FREE(parser);
           return NULL;
         }
    @@ -868,6 +904,7 @@ parserInit(XML_Parser parser, const XML_Char *encodingName)
       useForeignDTD = XML_FALSE;
       paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
     #endif
    +  hash_secret_salt = 0;
     }
     
     /* moves list of bindings to freeBindingList */
    @@ -915,7 +952,7 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
       poolClear(&temp2Pool);
       parserInit(parser, encodingName);
       dtdReset(_dtd, &parser->m_mem);
    -  return setContext(parser, implicitContext);
    +  return XML_TRUE;
     }
     
     enum XML_Status XMLCALL
    @@ -984,6 +1021,12 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser,
       int oldInEntityValue = prologState.inEntityValue;
     #endif
       XML_Bool oldns_triplets = ns_triplets;
    +  /* Note that the new parser shares the same hash secret as the old
    +     parser, so that dtdCopy and copyEntityTable can lookup values
    +     from hash tables associated with either parser without us having
    +     to worry which hash secrets each table has.
    +  */
    +  unsigned long oldhash_secret_salt = hash_secret_salt;
     
     #ifdef XML_DTD
       if (!context)
    @@ -1037,13 +1080,14 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser,
         externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
       defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
       ns_triplets = oldns_triplets;
    +  hash_secret_salt = oldhash_secret_salt;
       parentParser = oldParser;
     #ifdef XML_DTD
       paramEntityParsing = oldParamEntityParsing;
       prologState.inEntityValue = oldInEntityValue;
       if (context) {
     #endif /* XML_DTD */
    -    if (!dtdCopy(_dtd, oldDtd, &parser->m_mem)
    +    if (!dtdCopy(oldParser, _dtd, oldDtd, &parser->m_mem)
           || !setContext(parser, context)) {
           XML_ParserFree(parser);
           return NULL;
    @@ -1132,6 +1176,9 @@ XML_ParserFree(XML_Parser parser)
     #endif /* XML_DTD */
         dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
       FREE((void *)atts);
    +#ifdef XML_ATTR_INFO
    +  FREE((void *)attInfo);
    +#endif
       FREE(groupConnector);
       FREE(buffer);
       FREE(dataBuf);
    @@ -1212,6 +1259,14 @@ XML_GetIdAttributeIndex(XML_Parser parser)
       return idAttIndex;
     }
     
    +#ifdef XML_ATTR_INFO
    +const XML_AttrInfo * XMLCALL
    +XML_GetAttributeInfo(XML_Parser parser)
    +{
    +  return attInfo;
    +}
    +#endif
    +
     void XMLCALL
     XML_SetElementHandler(XML_Parser parser,
                           XML_StartElementHandler start,
    @@ -1428,12 +1483,20 @@ XML_SetParamEntityParsing(XML_Parser parser,
     #endif
     }
     
    +int XMLCALL
    +XML_SetHashSalt(XML_Parser parser,
    +                unsigned long hash_salt)
    +{
    +  /* block after XML_Parse()/XML_ParseBuffer() has been called */
    +  if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
    +    return 0;
    +  hash_secret_salt = hash_salt;
    +  return 1;
    +}
    +
     enum XML_Status XMLCALL
     XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
     {
    -  /* Avoid integer overflow */
    -  if (len > MAXLEN / 2)
    -    return XML_STATUS_ERROR;
       switch (ps_parsing) {
       case XML_SUSPENDED:
         errorCode = XML_ERROR_SUSPENDED;
    @@ -1441,6 +1504,11 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
       case XML_FINISHED:
         errorCode = XML_ERROR_FINISHED;
         return XML_STATUS_ERROR;
    +  case XML_INITIALIZED:
    +    if (parentParser == NULL && !startParsing(parser)) {
    +      errorCode = XML_ERROR_NO_MEMORY;
    +      return XML_STATUS_ERROR;
    +    }
       default:
         ps_parsing = XML_PARSING;
       }
    @@ -1499,11 +1567,13 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
             break;
           case XML_INITIALIZED:
           case XML_PARSING:
    -        result = XML_STATUS_OK;
             if (isFinal) {
               ps_parsing = XML_FINISHED;
    -          return result;
    +          return XML_STATUS_OK;
             }
    +      /* fall through */
    +      default:
    +        result = XML_STATUS_OK;
           }
         }
     
    @@ -1511,6 +1581,7 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
         nLeftOver = s + len - end;
         if (nLeftOver) {
           if (buffer == NULL || nLeftOver > bufferLim - buffer) {
    +        /* FIXME avoid integer overflow */
             char *temp;
             temp = (buffer == NULL
                     ? (char *)MALLOC(len * 2)
    @@ -1559,6 +1630,11 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
       case XML_FINISHED:
         errorCode = XML_ERROR_FINISHED;
         return XML_STATUS_ERROR;
    +  case XML_INITIALIZED:
    +    if (parentParser == NULL && !startParsing(parser)) {
    +      errorCode = XML_ERROR_NO_MEMORY;
    +      return XML_STATUS_ERROR;
    +    }
       default:
         ps_parsing = XML_PARSING;
       }
    @@ -1600,9 +1676,6 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
     void * XMLCALL
     XML_GetBuffer(XML_Parser parser, int len)
     {
    -  /* Avoid integer overflow */
    -  if (len > MAXLEN - (bufferEnd - bufferPtr))
    -    return NULL;
       switch (ps_parsing) {
       case XML_SUSPENDED:
         errorCode = XML_ERROR_SUSPENDED;
    @@ -1614,6 +1687,7 @@ XML_GetBuffer(XML_Parser parser, int len)
       }
     
       if (len > bufferLim - bufferEnd) {
    +    /* FIXME avoid integer overflow */
         int neededSize = len + (int)(bufferEnd - bufferPtr);
     #ifdef XML_CONTEXT_BYTES
         int keep = (int)(bufferPtr - buffer);
    @@ -1960,6 +2034,9 @@ XML_GetFeatureList(void)
     #endif
     #ifdef XML_LARGE_SIZE
         {XML_FEATURE_LARGE_SIZE,       XML_L("XML_LARGE_SIZE"), 0},
    +#endif
    +#ifdef XML_ATTR_INFO
    +    {XML_FEATURE_ATTR_INFO,        XML_L("XML_ATTR_INFO"), 0},
     #endif
         {XML_FEATURE_END,              NULL, 0}
       };
    @@ -2244,7 +2321,7 @@ doContent(XML_Parser parser,
                                     next - enc->minBytesPerChar);
             if (!name)
               return XML_ERROR_NO_MEMORY;
    -        entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
    +        entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
             poolDiscard(&dtd->pool);
             /* First, determine if a check for an existing declaration is needed;
                if yes, check that the entity exists, and that it is internal,
    @@ -2634,12 +2711,12 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
       const XML_Char *localPart;
     
       /* lookup the element type name */
    -  elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0);
    +  elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0);
       if (!elementType) {
         const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
         if (!name)
           return XML_ERROR_NO_MEMORY;
    -    elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name,
    +    elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
                                              sizeof(ELEMENT_TYPE));
         if (!elementType)
           return XML_ERROR_NO_MEMORY;
    @@ -2653,23 +2730,44 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
       if (n + nDefaultAtts > attsSize) {
         int oldAttsSize = attsSize;
         ATTRIBUTE *temp;
    +#ifdef XML_ATTR_INFO
    +    XML_AttrInfo *temp2;
    +#endif
         attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
         temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
         if (temp == NULL)
           return XML_ERROR_NO_MEMORY;
         atts = temp;
    +#ifdef XML_ATTR_INFO
    +    temp2 = (XML_AttrInfo *)REALLOC((void *)attInfo, attsSize * sizeof(XML_AttrInfo));
    +    if (temp2 == NULL)
    +      return XML_ERROR_NO_MEMORY;
    +    attInfo = temp2;
    +#endif
         if (n > oldAttsSize)
           XmlGetAttributes(enc, attStr, n, atts);
       }
     
       appAtts = (const XML_Char **)atts;
       for (i = 0; i < n; i++) {
    +    ATTRIBUTE *currAtt = &atts[i];
    +#ifdef XML_ATTR_INFO
    +    XML_AttrInfo *currAttInfo = &attInfo[i];
    +#endif
         /* add the name and value to the attribute list */
    -    ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
    -                                         atts[i].name
    -                                         + XmlNameLength(enc, atts[i].name));
    +    ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name,
    +                                         currAtt->name
    +                                         + XmlNameLength(enc, currAtt->name));
         if (!attId)
           return XML_ERROR_NO_MEMORY;
    +#ifdef XML_ATTR_INFO
    +    currAttInfo->nameStart = parseEndByteIndex - (parseEndPtr - currAtt->name);
    +    currAttInfo->nameEnd = currAttInfo->nameStart +
    +                           XmlNameLength(enc, currAtt->name);
    +    currAttInfo->valueStart = parseEndByteIndex -
    +                            (parseEndPtr - currAtt->valuePtr);
    +    currAttInfo->valueEnd = parseEndByteIndex - (parseEndPtr - currAtt->valueEnd);
    +#endif
         /* Detect duplicate attributes by their QNames. This does not work when
            namespace processing is turned on and different prefixes for the same
            namespace are used. For this case we have a check further down.
    @@ -2808,9 +2906,9 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
           if (s[-1] == 2) {  /* prefixed */
             ATTRIBUTE_ID *id;
             const BINDING *b;
    -        unsigned long uriHash = 0;
    +        unsigned long uriHash = hash_secret_salt;
             ((XML_Char *)s)[-1] = 0;  /* clear flag */
    -        id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0);
    +        id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
             b = id->prefix->binding;
             if (!b)
               return XML_ERROR_UNBOUND_PREFIX;
    @@ -2832,7 +2930,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
             } while (*s++);
     
             { /* Check hash table for duplicate of expanded name (uriName).
    -             Derived from code in lookup(HASH_TABLE *table, ...).
    +             Derived from code in lookup(parser, HASH_TABLE *table, ...).
               */
               unsigned char step = 0;
               unsigned long mask = nsAttsSize - 1;
    @@ -3781,7 +3879,8 @@ doProlog(XML_Parser parser,
         case XML_ROLE_DOCTYPE_PUBLIC_ID:
     #ifdef XML_DTD
           useForeignDTD = XML_FALSE;
    -      declEntity = (ENTITY *)lookup(&dtd->paramEntities,
    +      declEntity = (ENTITY *)lookup(parser,
    +                                    &dtd->paramEntities,
                                         externalSubsetName,
                                         sizeof(ENTITY));
           if (!declEntity)
    @@ -3838,7 +3937,8 @@ doProlog(XML_Parser parser,
             XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
             dtd->hasParamEntityRefs = XML_TRUE;
             if (paramEntityParsing && externalEntityRefHandler) {
    -          ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
    +          ENTITY *entity = (ENTITY *)lookup(parser,
    +                                            &dtd->paramEntities,
                                                 externalSubsetName,
                                                 sizeof(ENTITY));
               if (!entity)
    @@ -3882,7 +3982,7 @@ doProlog(XML_Parser parser,
             XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
             dtd->hasParamEntityRefs = XML_TRUE;
             if (paramEntityParsing && externalEntityRefHandler) {
    -          ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
    +          ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
                                                 externalSubsetName,
                                                 sizeof(ENTITY));
               if (!entity)
    @@ -4096,7 +4196,8 @@ doProlog(XML_Parser parser,
           break;
     #else /* XML_DTD */
           if (!declEntity) {
    -        declEntity = (ENTITY *)lookup(&dtd->paramEntities,
    +        declEntity = (ENTITY *)lookup(parser,
    +                                      &dtd->paramEntities,
                                           externalSubsetName,
                                           sizeof(ENTITY));
             if (!declEntity)
    @@ -4171,7 +4272,7 @@ doProlog(XML_Parser parser,
               const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
               if (!name)
                 return XML_ERROR_NO_MEMORY;
    -          declEntity = (ENTITY *)lookup(&dtd->generalEntities, name,
    +          declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,
                                             sizeof(ENTITY));
               if (!declEntity)
                 return XML_ERROR_NO_MEMORY;
    @@ -4203,7 +4304,7 @@ doProlog(XML_Parser parser,
             const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
             if (!name)
               return XML_ERROR_NO_MEMORY;
    -        declEntity = (ENTITY *)lookup(&dtd->paramEntities,
    +        declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
                                                name, sizeof(ENTITY));
             if (!declEntity)
               return XML_ERROR_NO_MEMORY;
    @@ -4385,7 +4486,7 @@ doProlog(XML_Parser parser,
                                     next - enc->minBytesPerChar);
             if (!name)
               return XML_ERROR_NO_MEMORY;
    -        entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
    +        entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
             poolDiscard(&dtd->pool);
             /* first, determine if a check for an existing declaration is needed;
                if yes, check that the entity exists, and that it is internal,
    @@ -4909,7 +5010,7 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
                                    next - enc->minBytesPerChar);
             if (!name)
               return XML_ERROR_NO_MEMORY;
    -        entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
    +        entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
             poolDiscard(&temp2Pool);
             /* First, determine if a check for an existing declaration is needed;
                if yes, check that the entity exists, and that it is internal.
    @@ -5018,7 +5119,7 @@ storeEntityValue(XML_Parser parser,
               result = XML_ERROR_NO_MEMORY;
               goto endEntityValue;
             }
    -        entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
    +        entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
             poolDiscard(&tempPool);
             if (!entity) {
               /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
    @@ -5308,7 +5409,7 @@ setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
           }
           if (!poolAppendChar(&dtd->pool, XML_T('\0')))
             return 0;
    -      prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
    +      prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
                                     sizeof(PREFIX));
           if (!prefix)
             return 0;
    @@ -5337,7 +5438,7 @@ getAttributeId(XML_Parser parser, const ENCODING *enc,
         return NULL;
       /* skip quotation mark - its storage will be re-used (like in name[-1]) */
       ++name;
    -  id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
    +  id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
       if (!id)
         return NULL;
       if (id->name != name)
    @@ -5355,7 +5456,7 @@ getAttributeId(XML_Parser parser, const ENCODING *enc,
           if (name[5] == XML_T('\0'))
             id->prefix = &dtd->defaultPrefix;
           else
    -        id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX));
    +        id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));
           id->xmlns = XML_TRUE;
         }
         else {
    @@ -5370,7 +5471,7 @@ getAttributeId(XML_Parser parser, const ENCODING *enc,
               }
               if (!poolAppendChar(&dtd->pool, XML_T('\0')))
                 return NULL;
    -          id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
    +          id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
                                             sizeof(PREFIX));
               if (id->prefix->name == poolStart(&dtd->pool))
                 poolFinish(&dtd->pool);
    @@ -5466,7 +5567,7 @@ setContext(XML_Parser parser, const XML_Char *context)
           ENTITY *e;
           if (!poolAppendChar(&tempPool, XML_T('\0')))
             return XML_FALSE;
    -      e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0);
    +      e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&tempPool), 0);
           if (e)
             e->open = XML_TRUE;
           if (*s != XML_T('\0'))
    @@ -5481,7 +5582,7 @@ setContext(XML_Parser parser, const XML_Char *context)
           else {
             if (!poolAppendChar(&tempPool, XML_T('\0')))
               return XML_FALSE;
    -        prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool),
    +        prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&tempPool),
                                       sizeof(PREFIX));
             if (!prefix)
               return XML_FALSE;
    @@ -5645,7 +5746,7 @@ dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
        The new DTD has already been initialized.
     */
     static int
    -dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
    +dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
     {
       HASH_TABLE_ITER iter;
     
    @@ -5660,7 +5761,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
         name = poolCopyString(&(newDtd->pool), oldP->name);
         if (!name)
           return 0;
    -    if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
    +    if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
           return 0;
       }
     
    @@ -5682,7 +5783,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
         if (!name)
           return 0;
         ++name;
    -    newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name,
    +    newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
                                       sizeof(ATTRIBUTE_ID));
         if (!newA)
           return 0;
    @@ -5692,7 +5793,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
           if (oldA->prefix == &oldDtd->defaultPrefix)
             newA->prefix = &newDtd->defaultPrefix;
           else
    -        newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
    +        newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
                                             oldA->prefix->name, 0);
         }
       }
    @@ -5711,7 +5812,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
         name = poolCopyString(&(newDtd->pool), oldE->name);
         if (!name)
           return 0;
    -    newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name,
    +    newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
                                       sizeof(ELEMENT_TYPE));
         if (!newE)
           return 0;
    @@ -5725,14 +5826,14 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
         }
         if (oldE->idAtt)
           newE->idAtt = (ATTRIBUTE_ID *)
    -          lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
    +          lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);
         newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
         if (oldE->prefix)
    -      newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
    +      newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
                                           oldE->prefix->name, 0);
         for (i = 0; i < newE->nDefaultAtts; i++) {
           newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
    -          lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
    +          lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
           newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
           if (oldE->defaultAtts[i].value) {
             newE->defaultAtts[i].value
    @@ -5746,13 +5847,15 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
       }
     
       /* Copy the entity tables. */
    -  if (!copyEntityTable(&(newDtd->generalEntities),
    +  if (!copyEntityTable(oldParser,
    +                       &(newDtd->generalEntities),
                            &(newDtd->pool),
                            &(oldDtd->generalEntities)))
           return 0;
     
     #ifdef XML_DTD
    -  if (!copyEntityTable(&(newDtd->paramEntities),
    +  if (!copyEntityTable(oldParser,
    +                       &(newDtd->paramEntities),
                            &(newDtd->pool),
                            &(oldDtd->paramEntities)))
           return 0;
    @@ -5775,7 +5878,8 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
     }  /* End dtdCopy */
     
     static int
    -copyEntityTable(HASH_TABLE *newTable,
    +copyEntityTable(XML_Parser oldParser,
    +                HASH_TABLE *newTable,
                     STRING_POOL *newPool,
                     const HASH_TABLE *oldTable)
     {
    @@ -5794,7 +5898,7 @@ copyEntityTable(HASH_TABLE *newTable,
         name = poolCopyString(newPool, oldE->name);
         if (!name)
           return 0;
    -    newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
    +    newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
         if (!newE)
           return 0;
         if (oldE->systemId) {
    @@ -5852,16 +5956,16 @@ keyeq(KEY s1, KEY s2)
     }
     
     static unsigned long FASTCALL
    -hash(KEY s)
    +hash(XML_Parser parser, KEY s)
     {
    -  unsigned long h = 0;
    +  unsigned long h = hash_secret_salt;
       while (*s)
         h = CHAR_HASH(h, *s++);
       return h;
     }
     
     static NAMED *
    -lookup(HASH_TABLE *table, KEY name, size_t createSize)
    +lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)
     {
       size_t i;
       if (table->size == 0) {
    @@ -5878,10 +5982,10 @@ lookup(HASH_TABLE *table, KEY name, size_t createSize)
           return NULL;
         }
         memset(table->v, 0, tsize);
    -    i = hash(name) & ((unsigned long)table->size - 1);
    +    i = hash(parser, name) & ((unsigned long)table->size - 1);
       }
       else {
    -    unsigned long h = hash(name);
    +    unsigned long h = hash(parser, name);
         unsigned long mask = (unsigned long)table->size - 1;
         unsigned char step = 0;
         i = h & mask;
    @@ -5907,7 +6011,7 @@ lookup(HASH_TABLE *table, KEY name, size_t createSize)
           memset(newV, 0, tsize);
           for (i = 0; i < table->size; i++)
             if (table->v[i]) {
    -          unsigned long newHash = hash(table->v[i]->name);
    +          unsigned long newHash = hash(parser, table->v[i]->name);
               size_t j = newHash & newMask;
               step = 0;
               while (newV[j]) {
    @@ -6283,7 +6387,7 @@ getElementType(XML_Parser parser,
     
       if (!name)
         return NULL;
    -  ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
    +  ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
       if (!ret)
         return NULL;
       if (ret->name != name)
    diff --git a/lib/libexpat/lib/xmltok_impl.c b/lib/libexpat/lib/xmltok_impl.c
    index 16dfb85f031..9c2895b8773 100644
    --- a/lib/libexpat/lib/xmltok_impl.c
    +++ b/lib/libexpat/lib/xmltok_impl.c
    @@ -885,7 +885,7 @@ PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
                         const char **nextTokPtr)
     {
       if (ptr == end)
    -    return -XML_TOK_PERCENT;
    +    return XML_TOK_PARTIAL;
       switch (BYTE_TYPE(enc, ptr)) {
       CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
       case BT_S: case BT_LF: case BT_CR: case BT_PERCNT:
    diff --git a/lib/libexpat/shlib_version b/lib/libexpat/shlib_version
    index 1c5d96eb2aa..c10074d52ae 100644
    --- a/lib/libexpat/shlib_version
    +++ b/lib/libexpat/shlib_version
    @@ -1,2 +1,2 @@
    -major=9
    +major=10
     minor=0
    -- 
    cgit v1.2.3