--- Begin Message ---
Package: xmlrpc-c
Version: 1.16.33-3.1
Severity: grave
Tags: patch security
Justification: user security hole
User: ubuntu-de...@lists.ubuntu.com
Usertags: origin-ubuntu quantal ubuntu-patch
Dear Maintainer,
In Ubuntu, the attached patch was applied to achieve the following:
* 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 (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
Because I had to backport the patch from upstream Expat to the forked
Expat in xmlrpc-c, I enabled the tests that are ran with 'make check' to
help ensure that I didn't introduce any regressions.
The fixes for the two CVEs have since been merged in upstream xmlrpc-c
(see the patch tags for links). Thanks for considering the patch.
-- 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.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/changelog xmlrpc-c-1.16.33/debian/changelog
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 <stddef.h>
+ #include <assert.h>
++#include <limits.h> /* UINT_MAX */
++#include <time.h> /* 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 <vector>
+ #include <sstream>
+ #include <memory>
++#include <cstring>
+ #include <time.h>
+
+ #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 <vector>
+ #include <sstream>
+ #include <memory>
++#include <cstring>
++#include <cstdlib>
+ #include <time.h>
+ #ifdef WIN32
+ #include <winsock.h>
+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 <arpa/inet.h>
+ #include <errno.h>
+ #include <string>
++#include <cstring>
+ #include <fcntl.h>
+
+ #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 <stdio.h>
+ #include <math.h>
+
+-#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 <stdlib.h>
++#include <stdio.h>
++
++#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;
--- End Message ---