diff --git a/SOURCES/0001-cleanup-and-fix-libxml2-backend.patch b/SOURCES/0001-cleanup-and-fix-libxml2-backend.patch new file mode 100644 index 0000000..ec1ce31 --- /dev/null +++ b/SOURCES/0001-cleanup-and-fix-libxml2-backend.patch @@ -0,0 +1,317 @@ +From 22c63b6ca838d257ce6b044fd893f3374d038e3f Mon Sep 17 00:00:00 2001 +From: Igor Gnatenko +Date: Sun, 18 Dec 2016 11:49:03 +0100 +Subject: [PATCH] cleanup and fix libxml2 backend + +Signed-off-by: Igor Gnatenko +--- + src/xmlrpc_libxml2.c | 138 +++++++++++++++++++++++++++------------------------ + 1 file changed, 73 insertions(+), 65 deletions(-) + +diff --git a/src/xmlrpc_libxml2.c b/src/xmlrpc_libxml2.c +index 207036ff..bf3d6914 100644 +--- a/src/xmlrpc_libxml2.c ++++ b/src/xmlrpc_libxml2.c +@@ -43,14 +43,15 @@ + #include "xmlrpc-c/base.h" + #include "xmlrpc-c/base_int.h" + #include "xmlrpc-c/string_int.h" ++#include "xmlrpc-c/util.h" + + #include "xmlparser.h" + + struct _xml_element { + xml_element * parentP; + const char * name; +- xmlrpc_mem_block cdata; /* char */ +- xmlrpc_mem_block children; /* xml_element* */ ++ xmlrpc_mem_block * cdataP; /* char */ ++ xmlrpc_mem_block * childrenP; /* xml_element* */ + }; + + #define XMLRPC_ASSERT_ELEM_OK(elem) \ +@@ -102,7 +103,7 @@ xmlElementNew(xmlrpc_env * const envP, + bool childrenAreValid; + + XMLRPC_ASSERT_ENV_OK(envP); +- assert(name != NULL); ++ XMLRPC_ASSERT(name != NULL); + + /* Set up our error-handling preconditions. */ + retval = NULL; +@@ -112,21 +113,20 @@ xmlElementNew(xmlrpc_env * const envP, + XMLRPC_FAIL_IF_NULL(retval, envP, XMLRPC_INTERNAL_ERROR, + "Couldn't allocate memory for XML element"); + ++ /* Set our parent field to NULL. */ + retval->parentP = NULL; +- ++ + /* Copy over the element name. */ +- retval->name = strdup(name); ++ retval->name = xmlrpc_strdupnull(name); + XMLRPC_FAIL_IF_NULL(retval->name, envP, XMLRPC_INTERNAL_ERROR, + "Couldn't allocate memory for XML element"); + nameIsValid = true; + +- /* Initialize a block to hold our CDATA. */ +- XMLRPC_TYPED_MEM_BLOCK_INIT(char, envP, &retval->cdata, 0); ++ retval->cdataP = XMLRPC_MEMBLOCK_NEW(char, envP, 0); + XMLRPC_FAIL_IF_FAULT(envP); + cdataIsValid = true; + +- /* Initialize a block to hold our child elements. */ +- XMLRPC_TYPED_MEM_BLOCK_INIT(xml_element *, envP, &retval->children, 0); ++ retval->childrenP = XMLRPC_MEMBLOCK_NEW(xml_element *, envP, 0); + XMLRPC_FAIL_IF_FAULT(envP); + childrenAreValid = true; + +@@ -136,48 +136,50 @@ cleanup: + if (nameIsValid) + xmlrpc_strfree(retval->name); + if (cdataIsValid) +- xmlrpc_mem_block_clean(&retval->cdata); ++ XMLRPC_MEMBLOCK_FREE(char, retval->cdataP); + if (childrenAreValid) +- xmlrpc_mem_block_clean(&retval->children); ++ XMLRPC_MEMBLOCK_FREE(xml_element *, retval->childrenP); + free(retval); + } +- retval = NULL; ++ return NULL; ++ } else { ++ return retval; + } +- return retval; + } + + +- ++/*========================================================================= ++** xml_element_free ++**========================================================================= ++** Blow away an existing element & all of its child elements. ++*/ + void + xml_element_free(xml_element * const elemP) { +-/*---------------------------------------------------------------------------- +- Blow away an existing element & all of its child elements. +------------------------------------------------------------------------------*/ +- xmlrpc_mem_block * children; +- unsigned int size; +- unsigned int i; ++ ++ xmlrpc_mem_block * childrenP; ++ size_t size, i; + xml_element ** contents; + + XMLRPC_ASSERT_ELEM_OK(elemP); + + xmlrpc_strfree(elemP->name); + elemP->name = XMLRPC_BAD_POINTER; +- xmlrpc_mem_block_clean(&elemP->cdata); ++ ++ XMLRPC_MEMBLOCK_FREE(char, elemP->cdataP); + + /* Deallocate all of our children recursively. */ +- children = &elemP->children; +- contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element *, children); +- size = XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element *, children); ++ childrenP = elemP->childrenP; ++ contents = XMLRPC_MEMBLOCK_CONTENTS(xml_element *, childrenP); ++ size = XMLRPC_MEMBLOCK_SIZE(xml_element *, childrenP); + for (i = 0; i < size; ++i) + xml_element_free(contents[i]); + +- xmlrpc_mem_block_clean(&elemP->children); ++ XMLRPC_MEMBLOCK_FREE(xml_element *, elemP->childrenP); + + free(elemP); + } + + +- + /*========================================================================= + ** Miscellaneous Accessors + **========================================================================= +@@ -185,36 +187,47 @@ xml_element_free(xml_element * const elemP) { + ** documentation on each function works. + */ + ++ ++ + const char * + xml_element_name(const xml_element * const elemP) { + + XMLRPC_ASSERT_ELEM_OK(elemP); ++ + return elemP->name; + } + ++ ++ + size_t +-xml_element_cdata_size(const xml_element * const elemP) { +- /* The result of this function is NOT VALID until the end_element handler +- has been called! +- */ ++xml_element_cdata_size (const xml_element * const elemP) { ++/*---------------------------------------------------------------------------- ++ The result of this function is NOT VALID until the end_element handler ++ has been called! ++-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT_ELEM_OK(elemP); +- return XMLRPC_TYPED_MEM_BLOCK_SIZE(char, &elemP->cdata) - 1; ++ ++ return XMLRPC_MEMBLOCK_SIZE(char, elemP->cdataP) - 1; + } + + + + const char * + xml_element_cdata(const xml_element * const elemP) { ++ + XMLRPC_ASSERT_ELEM_OK(elemP); +- return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &elemP->cdata); ++ ++ return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(const char, elemP->cdataP); + } + + + + unsigned int + xml_element_children_size(const xml_element * const elemP) { ++ + XMLRPC_ASSERT_ELEM_OK(elemP); +- return XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element *, &elemP->children); ++ ++ return XMLRPC_MEMBLOCK_SIZE(xml_element *, elemP->childrenP); + } + + +@@ -222,47 +235,42 @@ xml_element_children_size(const xml_element * const elemP) { + xml_element ** + xml_element_children(const xml_element * const elemP) { + XMLRPC_ASSERT_ELEM_OK(elemP); +- return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element *, &elemP->children); ++ return XMLRPC_MEMBLOCK_CONTENTS(xml_element *, elemP->childrenP); + } + + + +-/*========================================================================= +-** Internal xml_element Utility Functions +-**========================================================================= +-*/ ++/*============================================================================= ++ Internal xml_element Utility Functions ++=============================================================================*/ + + static void +-xmlElementAppendCdata(xmlrpc_env * const envP, +- xml_element * const elemP, +- const char * const cdata, +- size_t const size) { ++xml_element_append_cdata(xmlrpc_env * const envP, ++ xml_element * const elemP, ++ const char * const cdata, ++ size_t const size) { + + XMLRPC_ASSERT_ENV_OK(envP); +- XMLRPC_ASSERT_ELEM_OK(elemP); ++ XMLRPC_ASSERT_ELEM_OK(elemP); + +- XMLRPC_TYPED_MEM_BLOCK_APPEND(char, envP, &elemP->cdata, cdata, size); ++ XMLRPC_MEMBLOCK_APPEND(char, envP, elemP->cdataP, cdata, size); + } + + + + static void +-xmlElementAppendChild(xmlrpc_env * const envP, +- xml_element * const elemP, +- xml_element * const childP) { +- +- /* Whether or not this function succeeds, it takes ownership of the 'child' +- argument. +- WARNING - This is the exact opposite of the usual memory ownership +- rules for xmlrpc_value! So please pay attention. +- */ ++xml_element_append_child(xmlrpc_env * const envP, ++ xml_element * const elemP, ++ xml_element * const childP) { ++/*---------------------------------------------------------------------------- ++ Whether or not this function succeeds, it takes ownership of *childP. ++-----------------------------------------------------------------------------*/ + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_ELEM_OK(elemP); + XMLRPC_ASSERT_ELEM_OK(childP); +- assert(childP->parentP == NULL); ++ XMLRPC_ASSERT(childP->parentP == NULL); + +- XMLRPC_TYPED_MEM_BLOCK_APPEND(xml_element *, envP, &elemP->children, +- &childP, 1); ++ XMLRPC_MEMBLOCK_APPEND(xml_element *, envP, elemP->childrenP, &childP, 1); + if (!envP->fault_occurred) + childP->parentP = elemP; + else +@@ -317,7 +325,7 @@ startElement_(void * const userData, + /* (We need to watch our error handling invariants very carefully + ** here. Read the docs for xml_elementAppendChild. */ + newCurrentP = elemP; +- xmlElementAppendChild(&contextP->env, contextP->currentP, elemP); ++ xml_element_append_child(&contextP->env, contextP->currentP, elemP); + elemP = NULL; + XMLRPC_FAIL_IF_FAULT(&contextP->env); + contextP->currentP = newCurrentP; +@@ -348,7 +356,7 @@ endElement_(void * const userData, + contextP->currentP == contextP->rootP); + + /* Add a trailing '\0' to our cdata. */ +- xmlElementAppendCdata(&contextP->env, contextP->currentP, "\0", 1); ++ xml_element_append_cdata(&contextP->env, contextP->currentP, "\0", 1); + if (!contextP->env.fault_occurred) { + /* Pop our "stack" of elements. */ + contextP->currentP = contextP->currentP->parentP; +@@ -370,9 +378,9 @@ characterData(void * const userData, + /* Get our context and see if an error has already occured. */ + contextP = (ParseContext*)userData; + if (!contextP->env.fault_occurred) { +- assert(contextP->currentP != NULL); ++ XMLRPC_ASSERT(contextP->currentP != NULL); + +- xmlElementAppendCdata(&contextP->env, ++ xml_element_append_cdata(&contextP->env, + contextP->currentP, + (char *)s, + len); +@@ -428,7 +436,7 @@ static xmlSAXHandler const saxHandler = { + + + static void +-removeDocSizeLimit(xmlParserCtx * const parserP ATTR_UNUSED) { ++removeDocSizeLimit(xmlParserCtxt * const parserP ATTR_UNUSED) { + /*---------------------------------------------------------------------------- + Set up *parserP to accept a document of any size. + +@@ -451,13 +459,13 @@ removeDocSizeLimit(xmlParserCtx * const parserP ATTR_UNUSED) { + + + static void +-createParser(xmlrpc_env * const envP, +- ParseContext * const contextP, +- xmlParserCtx ** const parserPP) { ++createParser(xmlrpc_env * const envP, ++ ParseContext * const contextP, ++ xmlParserCtxt ** const parserPP) { + /*---------------------------------------------------------------------------- + Create an appropriate Libxml2 parser for our purpose. + -----------------------------------------------------------------------------*/ +- xmlParserCtx * parserP; ++ xmlParserCtxt * parserP; + + parserP = xmlCreatePushParserCtxt((xmlSAXHandler *)&saxHandler, contextP, + NULL, 0, NULL); +-- +2.11.0 + diff --git a/SPECS/xmlrpc-c.spec b/SPECS/xmlrpc-c.spec index 90c2890..0982abe 100644 --- a/SPECS/xmlrpc-c.spec +++ b/SPECS/xmlrpc-c.spec @@ -2,11 +2,11 @@ # Upstream libxml2 backend is completely broken since 2015 # https://sourceforge.net/p/xmlrpc-c/patches/49/ -%bcond_with libxml2 +%bcond_without libxml2 Name: xmlrpc-c Version: 1.51.0 -Release: 15%{?dist} +Release: 16%{?dist} Summary: Lightweight RPC library based on XML and HTTP # See doc/COPYING for details. # The Python 1.5.2 license used by a few files is just BSD. @@ -24,6 +24,7 @@ Patch102: 0002-Use-proper-datatypes-for-long-long.patch Patch103: 0003-allow-30x-redirections.patch #Patch104: xmlrpc-c-printf-size_t.patch #Patch105: xmlrpc-c-check-vasprintf-return-value.patch +Patch106: 0001-cleanup-and-fix-libxml2-backend.patch # Backported patches # https://sourceforge.net/p/xmlrpc-c/code/2981/ @@ -127,6 +128,11 @@ This package contains some handy XML-RPC demo applications. %prep %autosetup -Sgit +%if %{with libxml2} +# We want to build xmlrpc-c against libxml2, so we remove the bundled expat sources -- just to be sure +rm -Rf lib/expat +%endif + %build %meson %{?with_libxml2:-Dlibxml2-backend=true} %meson_build @@ -191,6 +197,11 @@ This package contains some handy XML-RPC demo applications. %{_bindir}/xmlrpc_dumpserver %changelog +* Thu Mar 17 2022 Michal Srb - 1.51.0-16 +- Drop bundled expat and build against libxml2 +- Resolves: CVE-2022-25235 +- Resolves: CVE-2022-25236 + * Tue Aug 10 2021 Mohan Boddu - 1.51.0-15 - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags Related: rhbz#1991688