diff -u xmlrpc-c-1.16.33/debian/rules xmlrpc-c-1.16.33/debian/rules --- xmlrpc-c-1.16.33/debian/rules +++ xmlrpc-c-1.16.33/debian/rules @@ -53,6 +53,7 @@ dh_testdir $(MAKE) CADD=-fPIC ( cd tools && $(MAKE) CADD=-fPIC ) + $(MAKE) CADD=-fPIC check touch build-arch-stamp build-indep: build-indep-stamp diff -u xmlrpc-c-1.16.33/debian/control xmlrpc-c-1.16.33/debian/control --- xmlrpc-c-1.16.33/debian/control +++ xmlrpc-c-1.16.33/debian/control @@ -103,8 +103,9 @@ Replaces: xml-rpc-api2cpp, xml-rpc-api2txt Architecture: any Section: devel -Depends: libxmlrpc-core-c3 (= ${binary:Version}), libc6-dev, - libfrontier-rpc-perl, ${misc:Depends} +Depends: libxmlrpc-core-c3 (= ${binary:Version}), + libxmlrpc-c++4 (= ${binary:Version}), libc6-dev, libfrontier-rpc-perl, + ${misc:Depends} Description: Generate C++ wrapper classes for XML-RPC servers XML-RPC is a quick-and-easy way to make procedure calls over the Internet. It converts the procedure call into an XML document, sends it to a remote diff -u xmlrpc-c-1.16.33/debian/changelog xmlrpc-c-1.16.33/debian/changelog --- xmlrpc-c-1.16.33/debian/changelog +++ xmlrpc-c-1.16.33/debian/changelog @@ -1,3 +1,23 @@ +xmlrpc-c (1.16.33-3.1ubuntu6) quantal; urgency=low + + * 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 + * Fix dependencies of xmlrpc-api-utils + - debian/control: xml-rcp-api2cpp needs libxmlrpc_cpp.so.4, so depend on + libxmlrpc-c++4 + * SECURITY UPDATE: Denial of service via hash collisions (LP: #1048835) + - 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 (LP: #1048835) + - debian/patches/CVE-2012-1148.patch: Properly reallocate memory. + Based on upstream patch. + - CVE-2012-1148 + + -- Tyler Hicks Mon, 10 Sep 2012 14:57:29 -0700 + xmlrpc-c (1.16.33-3.1ubuntu5) precise; urgency=low * Bump the build-dep on libcurl3-openssl-dev as well, otherwise the diff -u xmlrpc-c-1.16.33/debian/patches/series xmlrpc-c-1.16.33/debian/patches/series --- xmlrpc-c-1.16.33/debian/patches/series +++ xmlrpc-c-1.16.33/debian/patches/series @@ -4,0 +5,3 @@ +FTBFS-tests.patch +CVE-2012-0876.patch +CVE-2012-1148.patch only in patch2: unchanged: --- xmlrpc-c-1.16.33.orig/debian/patches/CVE-2012-0876.patch +++ xmlrpc-c-1.16.33/debian/patches/CVE-2012-0876.patch @@ -0,0 +1,541 @@ +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.16.33/lib/expat/xmlparse/xmlparse.c +=================================================================== +--- xmlrpc-c-1.16.33.orig/lib/expat/xmlparse/xmlparse.c 2012-09-06 09:54:29.920445233 -0700 ++++ xmlrpc-c-1.16.33/lib/expat/xmlparse/xmlparse.c 2012-09-06 11:42:34.792312153 -0700 +@@ -17,6 +17,8 @@ + + #include + #include ++#include /* UINT_MAX */ ++#include /* time() */ + + #include "xmlrpc_config.h" + #include "c_util.h" +@@ -211,6 +213,8 @@ + enum XML_Error * const errorCodeP, + const char ** const errorP); + ++static ++int setContext(XML_Parser parser, const XML_Char *context); + + #define poolStart(pool) ((pool)->start) + #define poolEnd(pool) ((pool)->ptr) +@@ -314,6 +318,7 @@ + XML_Char m_namespaceSeparator; + enum XML_ParamEntityParsing m_paramEntityParsing; + XML_Parser m_parentParser; ++ unsigned long m_hash_secret_salt; + } Parser; + + #define userData (((Parser *)parser)->m_userData) +@@ -391,6 +396,7 @@ + #define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator) + #define parentParser (((Parser *)parser)->m_parentParser) + #define paramEntityParsing (((Parser *)parser)->m_paramEntityParsing) ++#define hash_secret_salt (((Parser *)parser)->m_hash_secret_salt) + + + +@@ -564,6 +570,39 @@ + return pool->start; + } + ++static unsigned long ++generate_hash_secret_salt(void) ++{ ++ unsigned int seed = time(NULL) % UINT_MAX; ++ srand(seed); ++ return rand(); ++} ++ ++static int /* only valid for root parser */ ++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') ++ }; ++ ++ /* 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 +@@ -576,16 +615,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) { +@@ -596,10 +635,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) { +@@ -617,7 +656,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) + ; +@@ -730,7 +769,8 @@ + poolDestroy(&(p->pool)); + } + +-static int copyEntityTable(HASH_TABLE *newTable, ++static int copyEntityTable(XML_Parser oldParser, ++ HASH_TABLE *newTable, + STRING_POOL *newPool, + const HASH_TABLE *oldTable) + { +@@ -749,7 +789,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) { +@@ -792,7 +832,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; + +@@ -807,7 +847,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; + } + +@@ -830,7 +870,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; +@@ -840,7 +880,7 @@ + newA->prefix = &newDtd->defaultPrefix; + else + newA->prefix = (PREFIX *) +- lookup(&(newDtd->prefixes), oldA->prefix->name, 0); ++ lookup(oldParser, &(newDtd->prefixes), oldA->prefix->name, 0); + } + } + +@@ -859,7 +899,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) { +@@ -870,14 +910,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 = +@@ -891,12 +932,12 @@ + } + + /* Copy the entity tables. */ +- if (!copyEntityTable(&(newDtd->generalEntities), ++ if (!copyEntityTable(oldParser, &(newDtd->generalEntities), + &(newDtd->pool), + &(oldDtd->generalEntities))) + return 0; + +- if (!copyEntityTable(&(newDtd->paramEntities), ++ if (!copyEntityTable(oldParser, &(newDtd->paramEntities), + &(newDtd->pool), + &(oldDtd->paramEntities))) + return 0; +@@ -1043,7 +1084,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')) +@@ -1059,7 +1101,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)) { +@@ -1370,7 +1412,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) +@@ -1388,7 +1431,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 { +@@ -1403,7 +1447,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 +@@ -1454,7 +1499,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)) +@@ -1556,7 +1601,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) { +@@ -1651,7 +1696,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 == parser->m_encoding) +@@ -1807,13 +1852,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(xmlParserP, elementType)) +@@ -1948,7 +1994,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; +@@ -2311,7 +2357,7 @@ + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } +- 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) +@@ -3289,7 +3335,7 @@ + } + break; + case XML_ROLE_DOCTYPE_PUBLIC_ID: +- declEntity = (ENTITY *)lookup(&dtd.paramEntities, ++ declEntity = (ENTITY *)lookup(parser, &dtd.paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!declEntity) { +@@ -3320,7 +3366,7 @@ + if (dtd.complete && hadExternalDoctype) { + dtd.complete = 0; + if (paramEntityParsing && externalEntityRefHandler) { +- ENTITY *entity = (ENTITY *)lookup(&dtd.paramEntities, ++ ENTITY *entity = (ENTITY *)lookup(parser, &dtd.paramEntities, + externalSubsetName, + 0); + if (!externalEntityRefHandler(externalEntityRefHandlerArg, +@@ -3356,7 +3402,7 @@ + return; + } + declElementType = (ELEMENT_TYPE *) +- lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE)); ++ lookup(parser, &dtd.elementTypes, name, sizeof(ELEMENT_TYPE)); + if (!declElementType) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; +@@ -3432,7 +3478,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, +@@ -3459,7 +3506,7 @@ + } + hadExternalDoctype = 1; + if (!declEntity) { +- declEntity = (ENTITY *)lookup(&dtd.paramEntities, ++ declEntity = (ENTITY *)lookup(parser, &dtd.paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!declEntity) { +@@ -3525,7 +3572,7 @@ + } + if (dtd.complete) { + declEntity = (ENTITY *) +- lookup(&dtd.generalEntities, name, sizeof(ENTITY)); ++ lookup(parser, &dtd.generalEntities, name, sizeof(ENTITY)); + if (!declEntity) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; +@@ -3551,7 +3598,7 @@ + return; + } + declEntity = (ENTITY *) +- lookup(&dtd.paramEntities, name, sizeof(ENTITY)); ++ lookup(parser, &dtd.paramEntities, name, sizeof(ENTITY)); + if (!declEntity) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; +@@ -3688,7 +3735,7 @@ + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } +- 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? */ +@@ -3922,6 +3969,7 @@ + namespaceSeparator = '!'; + parentParser = 0; + paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; ++ hash_secret_salt = 0; + ns = 0; + poolInit(&tempPool); + poolInit(&temp2Pool); +@@ -3946,42 +3994,17 @@ + xmlrpc_XML_ParserCreateNS(const XML_Char * const encodingName, + XML_Char const 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 const xmlParserP = xmlrpc_XML_ParserCreate(encodingName); + Parser * const parser = (Parser *)xmlParserP; +- XML_Parser retval; + + if (xmlParserP) { +- int succeeded; + xmlrpc_XmlInitEncodingNS(&initEncoding, &parser->m_encoding, 0); + ns = 1; + internalEncoding = XmlGetInternalEncodingNS(); + namespaceSeparator = nsSep; ++ } + +- succeeded = setContext(xmlParserP, implicitContext); +- if (succeeded) +- retval = xmlParserP; +- else { +- xmlrpc_XML_ParserFree(xmlParserP); +- retval = NULL; +- } +- } else +- retval = NULL; +- +- return retval; ++ return xmlParserP; + } + + +@@ -4030,6 +4053,12 @@ + int oldDefaultExpandInternalEntities = defaultExpandInternalEntities; + void *oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; + int oldParamEntityParsing = paramEntityParsing; ++ /* 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)); +@@ -4060,9 +4089,10 @@ + if (oldExternalEntityRefHandlerArg != oldParser) + externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; + defaultExpandInternalEntities = oldDefaultExpandInternalEntities; ++ hash_secret_salt = oldhash_secret_salt; + paramEntityParsing = oldParamEntityParsing; + if (context) { +- if (!dtdCopy(&dtd, oldDtd) || !setContext(parser, context)) { ++ if (!dtdCopy(oldParser, &dtd, oldDtd) || !setContext(parser, context)) { + xmlrpc_XML_ParserFree(parser); + return 0; + } +@@ -4423,6 +4453,13 @@ + } + + ++int ++XML_SetHashSalt(XML_Parser parser, ++ unsigned long hash_salt) ++{ ++ hash_secret_salt = hash_salt; ++ return 1; ++} + + int + xmlrpc_XML_Parse(XML_Parser const xmlParserP, +@@ -4439,6 +4476,11 @@ + errorString = NULL; + } + ++ if (parentParser == NULL && !startParsing(parser)) { ++ errorCode = XML_ERROR_NO_MEMORY; ++ return 0; ++ } ++ + if (len == 0) { + if (!isFinal) + retval = 1; +@@ -4469,6 +4511,11 @@ + errorString = NULL; + } + ++ if (parentParser == NULL && !startParsing(parser)) { ++ errorCode = XML_ERROR_NO_MEMORY; ++ return 0; ++ } ++ + positionPtr = start; + bufferEnd += len; + parseEndByteIndex += len; +Index: xmlrpc-c-1.16.33/lib/expat/xmlparse/xmlparse.h +=================================================================== +--- xmlrpc-c-1.16.33.orig/lib/expat/xmlparse/xmlparse.h 2012-09-06 09:54:29.920445233 -0700 ++++ xmlrpc-c-1.16.33/lib/expat/xmlparse/xmlparse.h 2012-09-06 11:43:02.888311576 -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.16.33.orig/debian/patches/FTBFS-tests.patch +++ xmlrpc-c-1.16.33/debian/patches/FTBFS-tests.patch @@ -0,0 +1,276 @@ +Description: Fix issues when running make check + Fixes FTBFS issues from missing #include's and the placement of -l options + when linking. Also fixes many "inlining failed" compiler warnings by + uninlining functions in test.h. +Origin: backport, http://xmlrpc-c.svn.sourceforge.net/viewvc/xmlrpc-c?revision=1630&view=revision +Origin: backport, http://xmlrpc-c.svn.sourceforge.net/viewvc/xmlrpc-c?revision=1631&view=revision +Origin: backport, http://xmlrpc-c.svn.sourceforge.net/viewvc/xmlrpc-c?revision=1943&view=revision +Origin: backport, http://xmlrpc-c.svn.sourceforge.net/viewvc/xmlrpc-c?revision=1945&view=revision +Index: xmlrpc-c-1.16.32/src/cpp/test/test.cpp +=================================================================== +--- xmlrpc-c-1.16.32.orig/src/cpp/test/test.cpp 2012-09-07 11:54:45.209317841 -0700 ++++ xmlrpc-c-1.16.32/src/cpp/test/test.cpp 2012-09-07 12:01:12.453309894 -0700 +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + #include + + #include "xmlrpc-c/girerr.hpp" +Index: xmlrpc-c-1.16.32/src/cpp/test/server_abyss.cpp +=================================================================== +--- xmlrpc-c-1.16.32.orig/src/cpp/test/server_abyss.cpp 2012-09-07 11:54:45.209317841 -0700 ++++ xmlrpc-c-1.16.32/src/cpp/test/server_abyss.cpp 2012-09-07 12:01:12.453309894 -0700 +@@ -10,6 +10,8 @@ + #include + #include + #include ++#include ++#include + #include + #ifdef WIN32 + #include +Index: xmlrpc-c-1.16.32/src/cpp/test/server_pstream.cpp +=================================================================== +--- xmlrpc-c-1.16.32.orig/src/cpp/test/server_pstream.cpp 2012-09-07 11:54:45.209317841 -0700 ++++ xmlrpc-c-1.16.32/src/cpp/test/server_pstream.cpp 2012-09-07 12:01:12.453309894 -0700 +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + + #include "xmlrpc-c/girerr.hpp" +Index: xmlrpc-c-1.16.32/src/test/Makefile +=================================================================== +--- xmlrpc-c-1.16.32.orig/src/test/Makefile 2012-09-07 11:54:45.209317841 -0700 ++++ xmlrpc-c-1.16.32/src/test/Makefile 2012-09-07 12:07:30.261302141 -0700 +@@ -28,6 +28,7 @@ + LDFLAGS = $(LADD) + + TEST_OBJS = \ ++ testtool.o \ + test.o \ + abyss.o \ + cgi.o \ +@@ -60,9 +61,11 @@ + $(CCLD) -o $@ $(LDFLAGS) \ + $(TEST_OBJS) $(LDADD_CLIENT) $(LDADD_ABYSS_SERVER) $(CASPRINTF) + +-cgitest1:%:%.o $(LIBXMLRPC_SERVER_A) $(LIBXMLRPC_SERVER_CGI_A) \ ++CGITEST1_OBJS = cgitest1.o testtool.o ++ ++cgitest1: $(CGITEST1_OBJS) $(LIBXMLRPC_SERVER_A) $(LIBXMLRPC_SERVER_CGI_A) \ + $(LIBXMLRPC_A) $(LIBXMLRPC_UTIL_A) $(LIBXMLRPC_XML) +- $(CCLD) -o $@ $< $(LDFLAGS) $(LDADD_CGI_SERVER) ++ $(CCLD) -o $@ $(CGITEST1_OBJS) $(LDFLAGS) $(LDADD_CGI_SERVER) + + CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD) + +Index: xmlrpc-c-1.16.32/src/test/test.h +=================================================================== +--- xmlrpc-c-1.16.32.orig/src/test/test.h 2012-09-07 11:54:45.209317841 -0700 ++++ xmlrpc-c-1.16.32/src/test/test.h 2012-09-07 12:07:30.261302141 -0700 +@@ -2,7 +2,6 @@ + #include + #include + +-#include "xmlrpc_config.h" + #include "xmlrpc-c/util.h" + #include "xmlrpc-c/util_int.h" + +@@ -10,19 +9,22 @@ + extern int total_failures; + + +-/* This is a good place to set a breakpoint. */ +-static __inline__ void ++void + test_failure(const char * const file, + unsigned int const line, + const char * const label, +- const char * const statement) { +- +- ++total_failures; +- printf("\n%s:%u: test failure: %s (%s)\n", file, line, label, statement); +- abort(); +-} ++ const char * const statement); + ++void ++test_fault(xmlrpc_env * const envP, ++ int const expectedCode, ++ const char * const fileName, ++ unsigned int const lineNumber); + ++void ++test_null_string(const char * const string, ++ const char * const fileName, ++ unsigned int const lineNumber); + + #define TEST(statement) \ + do { \ +@@ -54,47 +56,11 @@ + #define TESTFLOATEQUAL(comparand, comparator) \ + TEST(FLOATEQUAL(comparand, comparator)) + +-static __inline__ void +-test_fault(xmlrpc_env * const envP, +- int const expectedCode, +- const char * const fileName, +- unsigned int const lineNumber) { +- +- ++total_tests; +- +- if (!envP->fault_occurred) +- test_failure(fileName, lineNumber, "no fault occurred", ""); +- else if (envP->fault_code != expectedCode) +- test_failure(fileName, lineNumber, "wrong fault occurred", +- envP->fault_string); +- else +- printf("."); +- +- xmlrpc_env_clean(envP); +- xmlrpc_env_init(envP); +-} +- +- + #define TEST_FAULT(envP, code) \ + do { test_fault(envP, code, __FILE__, __LINE__); } while(0) + + ; + +- +-static __inline__ void +-test_null_string(const char * const string, +- const char * const fileName, +- unsigned int const lineNumber) { +- +- ++total_tests; +- +- if (string != NULL) +- test_failure(fileName, lineNumber, "string not null", string); +- else +- printf("."); +-} +- +- + #define TEST_NULL_STRING(string) \ + do { test_null_string(string, __FILE__, __LINE__); } while(0) + +Index: xmlrpc-c-1.16.32/src/test/testtool.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ xmlrpc-c-1.16.32/src/test/testtool.c 2012-09-07 12:06:54.261302880 -0700 +@@ -0,0 +1,65 @@ ++#include ++#include ++ ++#include "xmlrpc_config.h" ++#include "xmlrpc-c/util.h" ++#include "xmlrpc-c/util_int.h" ++ ++#include "test.h" ++ /* Defines global variable, 'total_tests', 'total_failures' */ ++ ++ ++/* This is a good place to set a breakpoint. */ ++void ++test_failure(const char * const file, ++ unsigned int const line, ++ const char * const label, ++ const char * const statement) { ++ ++ ++total_failures; ++ printf("\n%s:%u: test failure: %s (%s)\n", file, line, label, statement); ++ ++ /* We abort rather than exit so one can tell from a dump or debug session ++ who called us. ++ */ ++ abort(); ++} ++ ++ ++ ++void ++test_fault(xmlrpc_env * const envP, ++ int const expectedCode, ++ const char * const fileName, ++ unsigned int const lineNumber) { ++ ++ ++total_tests; ++ ++ if (!envP->fault_occurred) ++ test_failure(fileName, lineNumber, "no fault occurred", ""); ++ else if (envP->fault_code != expectedCode) ++ test_failure(fileName, lineNumber, "wrong fault occurred", ++ envP->fault_string); ++ else ++ printf("."); ++ ++ xmlrpc_env_clean(envP); ++ xmlrpc_env_init(envP); ++} ++ ++ ++ ++void ++test_null_string(const char * const string, ++ const char * const fileName, ++ unsigned int const lineNumber) { ++ ++ ++total_tests; ++ ++ if (string != NULL) ++ test_failure(fileName, lineNumber, "string not null", string); ++ else ++ printf("."); ++} ++ ++ +Index: xmlrpc-c-1.16.32/src/cpp/test/Makefile +=================================================================== +--- xmlrpc-c-1.16.32.orig/src/cpp/test/Makefile 2012-09-07 11:54:45.209317841 -0700 ++++ xmlrpc-c-1.16.32/src/cpp/test/Makefile 2012-09-07 12:01:12.457309894 -0700 +@@ -19,18 +19,16 @@ + + CXXFLAGS = $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD) + +-LDFLAGS += $(shell $(XMLRPC_C_CONFIG) client --ldadd) ++LIBS := $(shell $(XMLRPC_C_CONFIG) client --ldadd) + + ifeq ($(MUST_BUILD_CURL_CLIENT),yes) +- LDFLAGS += $(shell curl-config --libs) ++ LIBS += $(shell curl-config --libs) + endif + ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes) +- LDFLAGS += $(shell libwww-config --libs) ++ LIBS += $(shell libwww-config --libs) + endif + +-LDFLAGS += "-lpthread" +- +-LDFLAGS += $(LADD) ++LIBS += -lpthread + + INCLUDES = -Isrcdir/include -I$(BLDDIR) -Isrcdir -Isrcdir/lib/util/include + +@@ -69,13 +67,13 @@ + ifneq ($(ENABLE_LIBXML2_BACKEND),yes) + # We're using the internal Expat XML parser + TEST_LIBS += $(LIBXMLRPC_XMLPARSE_A) $(LIBXMLRPC_XMLTOK_A) +- LDADD_XML = ++ LIB_XML = + else +- LDADD_XML = $(shell xml2-config --libs) ++ LIB_XML = $(shell xml2-config --libs) + endif + + test: $(TEST_OBJS) $(TEST_LIBS) +- $(CXXLD) -o $@ $(LDFLAGS) $(LDADD_XML) $^ ++ $(CXXLD) -o $@ $(LDFLAGS) $(LADD) $^ $(LIB_XML) $(LIBS) + + %.o:%.cpp + $(CXX) -c $(INCLUDES) $(CXXFLAGS) $< only in patch2: unchanged: --- xmlrpc-c-1.16.33.orig/debian/patches/CVE-2012-1148.patch +++ xmlrpc-c-1.16.33/debian/patches/CVE-2012-1148.patch @@ -0,0 +1,134 @@ +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.16.33/lib/expat/xmlparse/xmlparse.c +=================================================================== +--- xmlrpc-c-1.16.33.orig/lib/expat/xmlparse/xmlparse.c 2012-08-28 17:15:21.103200078 -0700 ++++ xmlrpc-c-1.16.33/lib/expat/xmlparse/xmlparse.c 2012-08-28 17:15:21.135200079 -0700 +@@ -480,10 +480,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; +@@ -965,9 +966,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; +@@ -1804,15 +1806,18 @@ + type->allocDefaultAtts = 8; + type->defaultAtts = + malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE)); ++ if (!type->defaultAtts) ++ return 0; + } + 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; + } + att = type->defaultAtts + type->nDefaultAtts; + att->id = attId; +@@ -1871,10 +1876,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); + } +@@ -2473,13 +2480,15 @@ + 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) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } ++ tag->buf = temp; + tag->bufEnd = tag->buf + bufSize; + } + memcpy(tag->buf, tag->rawName, tag->rawNameLength); +@@ -2506,11 +2515,12 @@ + break; + else { + int const bufSize = (tag->bufEnd - tag->buf) << 1; +- tag->buf = realloc(tag->buf, bufSize); +- if (!tag->buf) { ++ char *temp = realloc(tag->buf, bufSize); ++ if (!temp) { + *errorCodeP = XML_ERROR_NO_MEMORY; + return; + } ++ tag->buf = temp; + tag->bufEnd = tag->buf + bufSize; + if (nextPtr) + tag->rawName = tag->buf; +@@ -3697,13 +3707,19 @@ + break; + 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) { ++ *errorCodeP = XML_ERROR_NO_MEMORY; ++ return; ++ } ++ groupConnector = temp; ++ } else { + groupConnector = malloc(groupSize = 32); +- if (!groupConnector) { +- *errorCodeP = XML_ERROR_NO_MEMORY; +- return; ++ if (!groupConnector) { ++ *errorCodeP = XML_ERROR_NO_MEMORY; ++ return; ++ } + } + } + groupConnector[prologState.level] = 0;