Package: xmlrpc-c
Version: 1.06.27-1
Followup-For: Bug #687672
User: ubuntu-de...@lists.ubuntu.com
Usertags: origin-ubuntu quantal ubuntu-patch

I've also backported the same changes to 1.06.27-1 for our Lucid
xmlrpc-c package. It looks to apply cleanly to the Squeeze package.
Here's the changelog:

  * Run the tests as part of the build process
    - debian/patches/FTBFS-tests.patch: Fix issues when running make check.
      Based on upstream patches.
    - debian/rules: Run make check after building
  * SECURITY UPDATE: Denial of service via hash collisions
    - debian/patches/CVE-2012-0876.patch: Add random salt value to
      hash inputs. Based on upstream patch.
    - CVE-2012-0876
  * SECURITY UPDATE: Denial of service via memory leak
    - debian/patches/CVE-2012-1148.patch: Properly reallocate memory.
      Based on upstream patch.
    - CVE-2012-1148


I hope it is of some help.


-- System Information:
Debian Release: wheezy/sid
  APT prefers quantal-updates
  APT policy: (500, 'quantal-updates'), (500, 'quantal-security'), (500, 
'quantal')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.5.0-14-generic (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
diff -u xmlrpc-c-1.06.27/debian/changelog xmlrpc-c-1.06.27/debian/changelog
diff -u xmlrpc-c-1.06.27/debian/rules xmlrpc-c-1.06.27/debian/rules
--- xmlrpc-c-1.06.27/debian/rules
+++ xmlrpc-c-1.06.27/debian/rules
@@ -55,6 +55,7 @@
 build-arch-stamp: config.status
 	dh_testdir
 	$(MAKE) CADD=-fPIC
+	$(MAKE) CADD=-fPIC check
 	touch build-arch-stamp
 
 build-indep: build-indep-stamp
diff -u xmlrpc-c-1.06.27/debian/patches/series xmlrpc-c-1.06.27/debian/patches/series
--- xmlrpc-c-1.06.27/debian/patches/series
+++ xmlrpc-c-1.06.27/debian/patches/series
@@ -5,0 +6,3 @@
+FTBFS-tests.patch
+CVE-2012-0876.patch
+CVE-2012-1148.patch
only in patch2:
unchanged:
--- xmlrpc-c-1.06.27.orig/debian/patches/CVE-2012-0876.patch
+++ xmlrpc-c-1.06.27/debian/patches/CVE-2012-0876.patch
@@ -0,0 +1,556 @@
+Description: Prevent predictable hash collisions by using a random salt value
+ Backported from the upstream Expat sources to the embedded copy of Expat in
+ xmlrpc-c.
+Origin: backport, http://xmlrpc-c.svn.sourceforge.net/viewvc/xmlrpc-c?view=revision&revision=2391
+Index: xmlrpc-c-1.06.27/lib/expat/xmlparse/xmlparse.c
+===================================================================
+--- xmlrpc-c-1.06.27.orig/lib/expat/xmlparse/xmlparse.c	2012-09-06 14:54:24.144075962 -0700
++++ xmlrpc-c-1.06.27/lib/expat/xmlparse/xmlparse.c	2012-09-06 14:54:26.416075915 -0700
+@@ -16,6 +16,8 @@
+ */
+ 
+ #include <stddef.h>
++#include <limits.h>                     /* UINT_MAX */
++#include <time.h>                       /* time() */
+ 
+ #include "xmlrpc_config.h"
+ #include "c_util.h"
+@@ -40,6 +42,8 @@
+ typedef char ICHAR;
+ #endif
+ 
++static
++int setContext(XML_Parser parser, const XML_Char *context);
+ 
+ #ifndef XML_NS
+ 
+@@ -256,12 +260,15 @@
+ static void normalizePublicId(XML_Char *s);
+ static int dtdInit(DTD *);
+ static void dtdDestroy(DTD *);
+-static int dtdCopy(DTD *newDtd, const DTD *oldDtd);
+-static int copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
++static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd);
++static int copyEntityTable(XML_Parser, HASH_TABLE *, STRING_POOL *,
++                           const HASH_TABLE *);
+ #ifdef XML_DTD
+ static void dtdSwap(DTD *, DTD *);
+ #endif /* XML_DTD */
+-static NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize);
++static NAMED *lookup(XML_Parser parser, HASH_TABLE *table, KEY name,
++                     size_t createSize);
++static int startParsing(XML_Parser parser);
+ static void hashTableInit(HASH_TABLE *);
+ static void hashTableDestroy(HASH_TABLE *);
+ static void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
+@@ -370,6 +377,7 @@
+   enum XML_ParamEntityParsing m_paramEntityParsing;
+   XML_Parser m_parentParser;
+ #endif
++  unsigned long m_hash_secret_salt;
+ } Parser;
+ 
+ #define userData (((Parser *)parser)->m_userData)
+@@ -449,6 +457,7 @@
+ #define parentParser (((Parser *)parser)->m_parentParser)
+ #define paramEntityParsing (((Parser *)parser)->m_paramEntityParsing)
+ #endif /* XML_DTD */
++#define hash_secret_salt (((Parser *)parser)->m_hash_secret_salt)
+ 
+ #ifdef _MSC_VER
+ #ifdef _DEBUG
+@@ -527,6 +536,7 @@
+   parentParser = 0;
+   paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+ #endif
++  hash_secret_salt = 0;
+   ns = 0;
+   poolInit(&tempPool);
+   poolInit(&temp2Pool);
+@@ -546,20 +556,6 @@
+ XML_Parser
+ xmlrpc_XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
+ {
+-  static
+-  const XML_Char implicitContext[] = {
+-    XML_T('x'), XML_T('m'), XML_T('l'), XML_T('='),
+-    XML_T('h'), XML_T('t'), XML_T('t'), XML_T('p'), XML_T(':'),
+-    XML_T('/'), XML_T('/'), XML_T('w'), XML_T('w'), XML_T('w'),
+-    XML_T('.'), XML_T('w'), XML_T('3'),
+-    XML_T('.'), XML_T('o'), XML_T('r'), XML_T('g'),
+-    XML_T('/'), XML_T('X'), XML_T('M'), XML_T('L'),
+-    XML_T('/'), XML_T('1'), XML_T('9'), XML_T('9'), XML_T('8'),
+-    XML_T('/'), XML_T('n'), XML_T('a'), XML_T('m'), XML_T('e'),
+-    XML_T('s'), XML_T('p'), XML_T('a'), XML_T('c'), XML_T('e'),
+-    XML_T('\0')
+-  };
+-
+   XML_Parser parser = xmlrpc_XML_ParserCreate(encodingName);
+   if (parser) {
+     XmlInitEncodingNS(&initEncoding, &encoding, 0);
+@@ -567,10 +563,6 @@
+     internalEncoding = XmlGetInternalEncodingNS();
+     namespaceSeparator = nsSep;
+   }
+-  if (!setContext(parser, implicitContext)) {
+-    xmlrpc_XML_ParserFree(parser);
+-    return 0;
+-  }
+   return parser;
+ }
+ 
+@@ -618,6 +610,12 @@
+ #ifdef XML_DTD
+   int oldParamEntityParsing = paramEntityParsing;
+ #endif
++  /* 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;
+   parser = (ns
+             ? xmlrpc_XML_ParserCreateNS(encodingName, namespaceSeparator)
+             : xmlrpc_XML_ParserCreate(encodingName));
+@@ -648,11 +646,12 @@
+   if (oldExternalEntityRefHandlerArg != oldParser)
+     externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
+   defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
++  hash_secret_salt = oldhash_secret_salt;
+ #ifdef XML_DTD
+   paramEntityParsing = oldParamEntityParsing;
+   if (context) {
+ #endif /* XML_DTD */
+-    if (!dtdCopy(&dtd, oldDtd) || !setContext(parser, context)) {
++    if (!dtdCopy(parser, &dtd, oldDtd) || !setContext(parser, context)) {
+       xmlrpc_XML_ParserFree(parser);
+       return 0;
+     }
+@@ -929,6 +928,11 @@
+ int
+ xmlrpc_XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
+ {
++  if (!startParsing(parser)) {
++    errorCode = XML_ERROR_NO_MEMORY;
++    return 0;
++  }
++
+   if (len == 0) {
+     if (!isFinal)
+       return 1;
+@@ -990,6 +994,12 @@
+ xmlrpc_XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
+ {
+   const char *start = bufferPtr;
++
++  if (!startParsing(parser)) {
++    errorCode = XML_ERROR_NO_MEMORY;
++    return 0;
++  }
++
+   positionPtr = start;
+   bufferEnd += len;
+   parseEndByteIndex += len;
+@@ -1323,7 +1333,7 @@
+                                 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);
+         if (!entity) {
+           if (dtd.complete || dtd.standalone)
+@@ -1692,13 +1702,14 @@
+   /* lookup the element type name */
+   if (tagNamePtr) {
+     elementType = (ELEMENT_TYPE *)
+-        lookup(&dtd.elementTypes, tagNamePtr->str, 0);
++        lookup(parser, &dtd.elementTypes, tagNamePtr->str, 0);
+     if (!elementType) {
+       tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str);
+       if (!tagNamePtr->str)
+         return XML_ERROR_NO_MEMORY;
+       elementType = (ELEMENT_TYPE *)
+-          lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE));
++          lookup(parser, &dtd.elementTypes, tagNamePtr->str,
++                 sizeof(ELEMENT_TYPE));
+       if (!elementType)
+         return XML_ERROR_NO_MEMORY;
+       if (ns && !setElementTypePrefix(parser, elementType))
+@@ -1833,7 +1844,7 @@
+       if (appAtts[i][-1] == 2) {
+         ATTRIBUTE_ID *id;
+         ((XML_Char *)(appAtts[i]))[-1] = 0;
+-        id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0);
++        id = (ATTRIBUTE_ID *)lookup(parser, &dtd.attributeIds, appAtts[i], 0);
+         if (id->prefix->binding) {
+           int j;
+           const BINDING *b = id->prefix->binding;
+@@ -2383,7 +2394,7 @@
+ #endif /* XML_DTD */
+     case XML_ROLE_DOCTYPE_PUBLIC_ID:
+ #ifdef XML_DTD
+-      declEntity = (ENTITY *)lookup(&dtd.paramEntities,
++      declEntity = (ENTITY *)lookup(parser, &dtd.paramEntities,
+                                     externalSubsetName,
+                                     sizeof(ENTITY));
+       if (!declEntity)
+@@ -2410,7 +2421,7 @@
+         dtd.complete = 0;
+ #ifdef XML_DTD
+         if (paramEntityParsing && externalEntityRefHandler) {
+-          ENTITY *entity = (ENTITY *)lookup(&dtd.paramEntities,
++          ENTITY *entity = (ENTITY *)lookup(parser, &dtd.paramEntities,
+                                             externalSubsetName,
+                                             0);
+           if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+@@ -2439,7 +2450,7 @@
+         if (!name)
+           return XML_ERROR_NO_MEMORY;
+         declElementType = (ELEMENT_TYPE *)
+-            lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE));
++            lookup(parser, &dtd.elementTypes, name, sizeof(ELEMENT_TYPE));
+         if (!declElementType)
+           return XML_ERROR_NO_MEMORY;
+         if (declElementType->name != name)
+@@ -2503,7 +2514,8 @@
+           poolFinish(&dtd.pool);
+           if (internalParsedEntityDeclHandler
+               /* Check it's not a parameter entity */
+-              && ((ENTITY *)lookup(&dtd.generalEntities, declEntity->name, 0)
++              && ((ENTITY *)lookup(parser, &dtd.generalEntities,
++                                   declEntity->name, 0)
+                   == declEntity)) {
+             *eventEndPP = s;
+             internalParsedEntityDeclHandler(handlerArg,
+@@ -2531,7 +2543,7 @@
+       break;
+ #else /* XML_DTD */
+       if (!declEntity) {
+-        declEntity = (ENTITY *)lookup(&dtd.paramEntities,
++        declEntity = (ENTITY *)lookup(parser, &dtd.paramEntities,
+                                       externalSubsetName,
+                                       sizeof(ENTITY));
+         if (!declEntity)
+@@ -2590,7 +2602,7 @@
+           return XML_ERROR_NO_MEMORY;
+         if (dtd.complete) {
+             declEntity = (ENTITY *)
+-                lookup(&dtd.generalEntities, name, sizeof(ENTITY));
++                lookup(parser, &dtd.generalEntities, name, sizeof(ENTITY));
+           if (!declEntity)
+             return XML_ERROR_NO_MEMORY;
+           if (declEntity->name != name) {
+@@ -2613,7 +2625,7 @@
+         if (!name)
+           return XML_ERROR_NO_MEMORY;
+         declEntity = (ENTITY *)
+-            lookup(&dtd.paramEntities, name, sizeof(ENTITY));
++            lookup(parser, &dtd.paramEntities, name, sizeof(ENTITY));
+         if (!declEntity)
+           return XML_ERROR_NO_MEMORY;
+         if (declEntity->name != name) {
+@@ -2736,7 +2748,7 @@
+                                 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);
+         if (!entity) {
+           /* FIXME what to do if !dtd.complete? */
+@@ -3004,7 +3016,7 @@
+                                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);
+         if (!entity) {
+           if (dtd.complete) {
+@@ -3071,7 +3083,7 @@
+                                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(&tempPool);
+         if (!entity) {
+           if (enc == encoding)
+@@ -3320,7 +3332,7 @@
+       if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+         return 0;
+       prefix = (PREFIX *)
+-          lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
++          lookup(parser, &dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
+       if (!prefix)
+         return 0;
+       if (prefix->name == poolStart(&dtd.pool))
+@@ -3348,7 +3360,8 @@
+   if (!name)
+     return 0;
+   ++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 0;
+   if (id->name != name)
+@@ -3366,7 +3379,8 @@
+       if (name[5] == '\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 = 1;
+     }
+     else {
+@@ -3381,7 +3395,8 @@
+           if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+             return 0;
+           id->prefix = (PREFIX *)
+-              lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
++              lookup(parser, &dtd.prefixes, poolStart(&dtd.pool),
++                     sizeof(PREFIX));
+           if (id->prefix->name == poolStart(&dtd.pool))
+             poolFinish(&dtd.pool);
+           else
+@@ -3474,7 +3489,8 @@
+       ENTITY *e;
+       if (!poolAppendChar(&tempPool, XML_T('\0')))
+         return 0;
+-      e = (ENTITY *)lookup(&dtd.generalEntities, poolStart(&tempPool), 0);
++      e = (ENTITY *)lookup(parser, &dtd.generalEntities, poolStart(&tempPool),
++                           0);
+       if (e)
+         e->open = 1;
+       if (*s != XML_T('\0'))
+@@ -3490,7 +3506,7 @@
+         if (!poolAppendChar(&tempPool, XML_T('\0')))
+           return 0;
+         prefix = (PREFIX *)
+-            lookup(&dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX));
++            lookup(parser, &dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX));
+         if (!prefix)
+           return 0;
+         if (prefix->name == poolStart(&tempPool)) {
+@@ -3600,7 +3616,7 @@
+ /* Do a deep copy of the DTD.  Return 0 for out of memory; non-zero otherwise.
+ The new DTD has already been initialized. */
+ 
+-static int dtdCopy(DTD *newDtd, const DTD *oldDtd)
++static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd)
+ {
+   HASH_TABLE_ITER iter;
+ 
+@@ -3615,7 +3631,7 @@
+     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;
+   }
+ 
+@@ -3638,7 +3654,7 @@
+       return 0;
+     ++name;
+     newA = (ATTRIBUTE_ID *)
+-        lookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID));
++        lookup(oldParser, &(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID));
+     if (!newA)
+       return 0;
+     newA->maybeTokenized = oldA->maybeTokenized;
+@@ -3648,7 +3664,7 @@
+         newA->prefix = &newDtd->defaultPrefix;
+       else
+         newA->prefix = (PREFIX *)
+-            lookup(&(newDtd->prefixes), oldA->prefix->name, 0);
++            lookup(oldParser, &(newDtd->prefixes), oldA->prefix->name, 0);
+     }
+   }
+ 
+@@ -3667,7 +3683,7 @@
+     if (!name)
+       return 0;
+     newE = (ELEMENT_TYPE *)
+-        lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE));
++        lookup(oldParser, &(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE));
+     if (!newE)
+       return 0;
+     if (oldE->nDefaultAtts) {
+@@ -3678,14 +3694,15 @@
+     }
+     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), oldE->prefix->name, 0);
++          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 =
+@@ -3699,13 +3716,13 @@
+   }
+ 
+   /* 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;
+@@ -3716,7 +3733,8 @@
+   return 1;
+ }
+ 
+-static int copyEntityTable(HASH_TABLE *newTable,
++static int copyEntityTable(XML_Parser oldParser,
++                           HASH_TABLE *newTable,
+                            STRING_POOL *newPool,
+                            const HASH_TABLE *oldTable)
+ {
+@@ -3735,7 +3753,7 @@
+     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) {
+@@ -3773,6 +3791,44 @@
+   return 1;
+ }
+ 
++static unsigned long
++generate_hash_secret_salt(void)
++{
++  unsigned int seed = time(NULL) % UINT_MAX;
++  srand(seed);
++  return rand();
++}
++
++static int
++startParsing(XML_Parser parser)
++{
++    static
++        const XML_Char implicitContext[] = {
++            XML_T('x'), XML_T('m'), XML_T('l'), XML_T('='),
++            XML_T('h'), XML_T('t'), XML_T('t'), XML_T('p'), XML_T(':'),
++            XML_T('/'), XML_T('/'), XML_T('w'), XML_T('w'), XML_T('w'),
++            XML_T('.'), XML_T('w'), XML_T('3'),
++            XML_T('.'), XML_T('o'), XML_T('r'), XML_T('g'),
++            XML_T('/'), XML_T('X'), XML_T('M'), XML_T('L'),
++            XML_T('/'), XML_T('1'), XML_T('9'), XML_T('9'), XML_T('8'),
++            XML_T('/'), XML_T('n'), XML_T('a'), XML_T('m'), XML_T('e'),
++            XML_T('s'), XML_T('p'), XML_T('a'), XML_T('c'), XML_T('e'),
++            XML_T('\0')
++        };
++
++#ifdef XML_DTD
++    if (parentParser != NULL)
++      return 1;
++#endif
++
++    /* hash functions must be initialized before setContext() is called */
++    if (hash_secret_salt == 0)
++      hash_secret_salt = generate_hash_secret_salt();
++    if (parser)
++      return setContext(parser, implicitContext);
++    return 0;
++}
++
+ #define INIT_SIZE 64
+ 
+ static
+@@ -3785,16 +3841,16 @@
+ }
+ 
+ static
+-unsigned long hash(KEY s)
++unsigned long hash(XML_Parser parser, KEY s)
+ {
+-  unsigned long h = 0;
++  unsigned long h = hash_secret_salt;
+   while (*s)
+     h = (h << 5) + h + (unsigned char)*s++;
+   return h;
+ }
+ 
+ static
+-NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize)
++NAMED *lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)
+ {
+   size_t i;
+   if (table->size == 0) {
+@@ -3805,10 +3861,10 @@
+       return 0;
+     table->size = INIT_SIZE;
+     table->usedLim = INIT_SIZE / 2;
+-    i = hash(name) & (table->size - 1);
++    i = hash(parser, name) & (table->size - 1);
+   }
+   else {
+-    unsigned long h = hash(name);
++    unsigned long h = hash(parser, name);
+     for (i = h & (table->size - 1);
+          table->v[i];
+          i == 0 ? i = table->size - 1 : --i) {
+@@ -3826,7 +3882,7 @@
+       for (i = 0; i < table->size; i++)
+         if (table->v[i]) {
+           size_t j;
+-          for (j = hash(table->v[i]->name) & (newSize - 1);
++          for (j = hash(parser, table->v[i]->name) & (newSize - 1);
+                newV[j];
+                j == 0 ? j = newSize - 1 : --j)
+             ;
+@@ -3890,6 +3946,13 @@
+   return 0;
+ }
+ 
++int
++XML_SetHashSalt(XML_Parser parser,
++                unsigned long hash_salt)
++{
++  hash_secret_salt = hash_salt;
++  return 1;
++}
+ 
+ static
+ void poolInit(STRING_POOL *pool)
+Index: xmlrpc-c-1.06.27/lib/expat/xmlparse/xmlparse.h
+===================================================================
+--- xmlrpc-c-1.06.27.orig/lib/expat/xmlparse/xmlparse.h	2012-08-29 11:55:00.777227617 -0700
++++ xmlrpc-c-1.06.27/lib/expat/xmlparse/xmlparse.h	2012-09-06 14:54:35.064075737 -0700
+@@ -477,6 +477,14 @@
+ xmlrpc_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.
++*/
++int
++XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt);
++
+ enum XML_Error {
+   XML_ERROR_NONE,
+   XML_ERROR_NO_MEMORY,
only in patch2:
unchanged:
--- xmlrpc-c-1.06.27.orig/debian/patches/FTBFS-tests.patch
+++ xmlrpc-c-1.06.27/debian/patches/FTBFS-tests.patch
@@ -0,0 +1,76 @@
+Description: Fix issues when running make check
+ Fixes FTBFS issues from missing #include's. Also fixes bad test cases so that
+ make check can be used successfully.
+Origin: backport, http://xmlrpc-c.svn.sourceforge.net/viewvc/xmlrpc-c?revision=1630&view=revision
+Origin: upstream, http://xmlrpc-c.svn.sourceforge.net/viewvc/xmlrpc-c?revision=1564&view=revision
+Origin: upstream, http://xmlrpc-c.svn.sourceforge.net/viewvc/xmlrpc-c?revision=784&view=revision
+Index: xmlrpc-c-1.06.27/src/cpp/test/test.cpp
+===================================================================
+--- xmlrpc-c-1.06.27.orig/src/cpp/test/test.cpp	2012-09-06 16:12:40.139979593 -0700
++++ xmlrpc-c-1.06.27/src/cpp/test/test.cpp	2012-09-07 10:28:25.593424135 -0700
+@@ -4,6 +4,7 @@
+ #include <vector>
+ #include <sstream>
+ #include <memory>
++#include <cstring>
+ #include <time.h>
+ 
+ #include "xmlrpc-c/girerr.hpp"
+Index: xmlrpc-c-1.06.27/src/cpp/test/server_abyss.cpp
+===================================================================
+--- xmlrpc-c-1.06.27.orig/src/cpp/test/server_abyss.cpp	2012-09-06 16:12:40.139979593 -0700
++++ xmlrpc-c-1.06.27/src/cpp/test/server_abyss.cpp	2012-09-07 10:26:12.241426871 -0700
+@@ -13,6 +13,7 @@
+ #include <vector>
+ #include <sstream>
+ #include <memory>
++#include <cstring>
+ #include <time.h>
+ 
+ #include "xmlrpc-c/girerr.hpp"
+Index: xmlrpc-c-1.06.27/src/cpp/test/testclient.cpp
+===================================================================
+--- xmlrpc-c-1.06.27.orig/src/cpp/test/testclient.cpp	2012-09-06 16:12:40.139979593 -0700
++++ xmlrpc-c-1.06.27/src/cpp/test/testclient.cpp	2012-09-07 10:25:22.425427893 -0700
+@@ -33,7 +33,7 @@
+ class sampleAddMethod : public method {
+ public:
+     sampleAddMethod() {
+-        this->_signature = "ii";
++        this->_signature = "i:ii";
+         this->_help = "This method adds two integers together";
+     }
+     void
+@@ -438,12 +438,28 @@
+ 
+         rpcPtr rpc2P("blowme", paramList0);
+ 
+-        // This fails because the server doesn't exist
+-        EXPECT_ERROR(rpc2P->start(&client0, &carriageParmCurl););
++        // This RPC fails to execute because the server doesn't exist,
++        // But libcurl "starts" it just fine.
++        rpc2P->start(&client0, &carriageParmCurl);
++
++        transportc0.finishAsync(5000);
++
++        TEST(rpc2P->isFinished());
++
++        TEST(!rpc2P->isSuccessful());
++
++        // Because the RPC did not return an XML-RPC failure (because the
++        // server doesn't exist), this throws:
++        EXPECT_ERROR(rpc2P->getFault(););
+ 
+         rpcPtr rpc3P("blowme", paramList0);
+-        // This fails because the server doesn't exist
+-        EXPECT_ERROR(rpc3P->start(connection0););
++        // This RPC fails to execute because the server doesn't exist
++        rpc3P->start(connection0);
++
++        transportc0.finishAsync(5000);
++        TEST(rpc2P->isFinished());
++        TEST(!rpc2P->isSuccessful());
++
+ #else
+         // This fails because there is no Curl transport in the library.
+         EXPECT_ERROR(clientXmlTransport_curl transportc0;);
only in patch2:
unchanged:
--- xmlrpc-c-1.06.27.orig/debian/patches/CVE-2012-1148.patch
+++ xmlrpc-c-1.06.27/debian/patches/CVE-2012-1148.patch
@@ -0,0 +1,147 @@
+Description: Don't leak memory when realloc() returns NULL
+ Backported from the upstream Expat sources to the embedded copy of Expat in
+ xmlrpc-c.
+Origin: backport, http://xmlrpc-c.svn.sourceforge.net/viewvc/xmlrpc-c?view=revision&revision=2393
+Index: xmlrpc-c-1.06.27/lib/expat/xmlparse/xmlparse.c
+===================================================================
+--- xmlrpc-c-1.06.27.orig/lib/expat/xmlparse/xmlparse.c	2012-08-29 01:07:09.907092848 -0700
++++ xmlrpc-c-1.06.27/lib/expat/xmlparse/xmlparse.c	2012-08-29 01:07:14.851092966 -0700
+@@ -967,15 +967,16 @@
+     nLeftOver = s + len - end;
+     if (nLeftOver) {
+       if (buffer == 0 || nLeftOver > bufferLim - buffer) {
++        char *temp;
+         /* FIXME avoid integer overflow */
+-        buffer = buffer == 0 ? malloc(len * 2) : realloc(buffer, len * 2);
+-        /* FIXME storage leak if realloc fails */
+-        if (!buffer) {
++        temp = buffer == 0 ? malloc(len * 2) : realloc(buffer, len * 2);
++        if (!temp) {
+           errorCode = XML_ERROR_NO_MEMORY;
+           eventPtr = eventEndPtr = 0;
+           processor = errorProcessor;
+           return 0;
+         }
++	buffer = temp;
+         bufferLim = buffer + len * 2;
+       }
+       memcpy(buffer, end, nLeftOver);
+@@ -1424,11 +1425,13 @@
+           /* Need to guarantee that:
+              tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= tag->bufEnd - sizeof(XML_Char) */
+           if (tag->rawNameLength + (int)(sizeof(XML_Char) - 1) + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) {
++            char *temp;
+             int bufSize = tag->rawNameLength * 4;
+             bufSize = ROUND_UP(bufSize, sizeof(XML_Char));
+-            tag->buf = realloc(tag->buf, bufSize);
+-            if (!tag->buf)
++            temp = realloc(tag->buf, bufSize);
++            if (!temp)
+               return XML_ERROR_NO_MEMORY;
++            tag->buf = temp;
+             tag->bufEnd = tag->buf + bufSize;
+           }
+           memcpy(tag->buf, tag->rawName, tag->rawNameLength);
+@@ -1441,6 +1444,7 @@
+           for (;;) {
+             const char *rawNameEnd = tag->rawName + tag->rawNameLength;
+             const char *fromPtr = tag->rawName;
++            char *temp;
+             int bufSize;
+             if (nextPtr)
+               toPtr = (XML_Char *)(tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)));
+@@ -1453,9 +1457,10 @@
+             if (fromPtr == rawNameEnd)
+               break;
+             bufSize = (tag->bufEnd - tag->buf) << 1;
+-            tag->buf = realloc(tag->buf, bufSize);
+-            if (!tag->buf)
++            temp = realloc(tag->buf, bufSize);
++            if (!temp)
+               return XML_ERROR_NO_MEMORY;
++            tag->buf = temp;
+             tag->bufEnd = tag->buf + bufSize;
+             if (nextPtr)
+               tag->rawName = tag->buf;
+@@ -1721,10 +1726,12 @@
+   n = XmlGetAttributes(enc, attStr, attsSize, atts);
+   if (n + nDefaultAtts > attsSize) {
+     int oldAttsSize = attsSize;
++    ATTRIBUTE *temp;
+     attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
+-    atts = realloc((void *)atts, attsSize * sizeof(ATTRIBUTE));
+-    if (!atts)
++    temp = realloc((void *)atts, attsSize * sizeof(ATTRIBUTE));
++    if (!temp)
+       return XML_ERROR_NO_MEMORY;
++    atts = temp;
+     if (n > oldAttsSize)
+       XmlGetAttributes(enc, attStr, n, atts);
+   }
+@@ -1930,9 +1937,10 @@
+   if (freeBindingList) {
+     b = freeBindingList;
+     if (len > b->uriAlloc) {
+-      b->uri = realloc(b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
+-      if (!b->uri)
++      XML_Char *temp = realloc(b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
++      if (!temp)
+         return 0;
++      b->uri = temp;
+       b->uriAlloc = len + EXPAND_SPARE;
+     }
+     freeBindingList = b->nextTagBinding;
+@@ -2717,12 +2725,16 @@
+ #endif /* XML_DTD */
+     case XML_ROLE_GROUP_OPEN:
+       if (prologState.level >= groupSize) {
+-        if (groupSize)
+-          groupConnector = realloc(groupConnector, groupSize *= 2);
+-        else
++        if (groupSize) {
++          char *temp = realloc(groupConnector, groupSize *= 2);
++          if (!temp)
++            return XML_ERROR_NO_MEMORY;
++          groupConnector = temp;
++	} else {
+           groupConnector = malloc(groupSize = 32);
+-        if (!groupConnector)
+-          return XML_ERROR_NO_MEMORY;
++          if (!groupConnector)
++            return XML_ERROR_NO_MEMORY;
++        }
+       }
+       groupConnector[prologState.level] = 0;
+       break;
+@@ -3300,10 +3312,13 @@
+           malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
+     }
+     else {
++      DEFAULT_ATTRIBUTE *temp;
+       type->allocDefaultAtts *= 2;
+-      type->defaultAtts =
+-          realloc(type->defaultAtts,
+-                  type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
++      temp = realloc(type->defaultAtts,
++                     type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
++      if (!temp)
++        return 0;
++      type->defaultAtts = temp;
+     }
+     if (!type->defaultAtts)
+       return 0;
+@@ -4090,10 +4105,11 @@
+   }
+   if (pool->blocks && pool->start == pool->blocks->s) {
+     int blockSize = (pool->end - pool->start)*2;
+-    pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) +
+-                           blockSize * sizeof(XML_Char));
+-    if (!pool->blocks)
++    BLOCK *temp = realloc(pool->blocks, offsetof(BLOCK, s) +
++                          blockSize * sizeof(XML_Char));
++    if (!temp)
+       return 0;
++    pool->blocks = temp;
+     pool->blocks->size = blockSize;
+     pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+     pool->start = pool->blocks->s;

Reply via email to