Restrict XML Entity Expansion Depth in libexpat CVE-2024-8176
The embedded libexpat library is vulnerable to a stack overflow due to uncontrolled recursion when processing deeply nested XML entities. This can cause the application to crash, resulting in a denial of service (DoS) or potentially leading to memory corruption, depending on the user's environment and how the library is used. The issue is triggered by supplying a specially crafted XML document designed to create a long chain of recursive entities. libexpat addressed this upstream in https://github.com/libexpat/libexpat/pull/973 but the embedded copy within xmlrpc-c is so old there is no chance of applying this without rebasing it. Instead a recursion counter is added to the parser to limit the depth. Resolves: RHEL-57536
This commit is contained in:
		
							parent
							
								
									288e29745d
								
							
						
					
					
						commit
						a8bddf83d5
					
				
							
								
								
									
										473
									
								
								0009-Restrict-XML-Entity-Expansion-Depth-in-libexpat-CVE-.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										473
									
								
								0009-Restrict-XML-Entity-Expansion-Depth-in-libexpat-CVE-.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,473 @@ | |||||||
|  | From 6d8259c43c7d675987d96bf990b6b57402d27f28 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: root <root@vm-10-0-185-207.hosted.upshift.rdu2.redhat.com> | ||||||
|  | Date: Wed, 19 Mar 2025 12:52:04 -0400 | ||||||
|  | Subject: [PATCH 09/10] Restrict XML Entity Expansion Depth in libexpat | ||||||
|  |  CVE-2024-8176 | ||||||
|  | 
 | ||||||
|  | The embedded libexpat library is vulnerable to a stack overflow | ||||||
|  | due to uncontrolled recursion when processing deeply nested XML | ||||||
|  | entities. This can cause the application to crash, resulting in | ||||||
|  | a denial of service (DoS) or potentially leading to memory | ||||||
|  | corruption, depending on the user's environment and how the | ||||||
|  | library is used. The issue is triggered by supplying a specially | ||||||
|  | crafted XML document designed to create a long chain of recursive | ||||||
|  | entities. | ||||||
|  | 
 | ||||||
|  | libexpat addressed this upstream in | ||||||
|  | https://github.com/libexpat/libexpat/pull/973 | ||||||
|  | but the embedded copy within xmlrpc-c is so old there is no chance | ||||||
|  | of applying this without rebasing it. Instead a recursion counter | ||||||
|  | is added to the parser to limit the depth. | ||||||
|  | 
 | ||||||
|  | Resolves: RHEL-57536 | ||||||
|  | ---
 | ||||||
|  |  lib/expat/xmlparse/xmlparse.c | 40 +++++++++++++--- | ||||||
|  |  test/Makefile                 | 30 ++++++++++-- | ||||||
|  |  test/overflow_attr_test.c     | 88 +++++++++++++++++++++++++++++++++++ | ||||||
|  |  test/overflow_entity_test.c   | 86 ++++++++++++++++++++++++++++++++++ | ||||||
|  |  4 files changed, 234 insertions(+), 10 deletions(-) | ||||||
|  |  create mode 100644 test/overflow_attr_test.c | ||||||
|  |  create mode 100644 test/overflow_entity_test.c | ||||||
|  | 
 | ||||||
|  | diff --git a/lib/expat/xmlparse/xmlparse.c b/lib/expat/xmlparse/xmlparse.c
 | ||||||
|  | index c440ac7..467910a 100644
 | ||||||
|  | --- a/lib/expat/xmlparse/xmlparse.c
 | ||||||
|  | +++ b/lib/expat/xmlparse/xmlparse.c
 | ||||||
|  | @@ -29,6 +29,8 @@ See the file copying.txt for copying permission.
 | ||||||
|  |  #include "xmldef.h" | ||||||
|  |  #include "xmlparse.h" | ||||||
|  |   | ||||||
|  | +#define MAX_RECURSE 28
 | ||||||
|  | +
 | ||||||
|  |  static const char * | ||||||
|  |  extractXmlSample(const char * const start, | ||||||
|  |                   const char * const end, | ||||||
|  | @@ -312,6 +314,7 @@ typedef struct {
 | ||||||
|  |    enum XML_ParamEntityParsing m_paramEntityParsing; | ||||||
|  |    XML_Parser m_parentParser; | ||||||
|  |    unsigned long m_hash_secret_salt; | ||||||
|  | +  int m_recurse_lock;
 | ||||||
|  |  } Parser; | ||||||
|  |   | ||||||
|  |  #define userData (((Parser *)parser)->m_userData) | ||||||
|  | @@ -388,6 +391,7 @@ typedef struct {
 | ||||||
|  |  #define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator) | ||||||
|  |  #define parentParser (((Parser *)parser)->m_parentParser) | ||||||
|  |  #define hash_secret_salt (((Parser *)parser)->m_hash_secret_salt) | ||||||
|  | +#define recurse_lock (((Parser *)parser)->m_recurse_lock)
 | ||||||
|  |   | ||||||
|  |   | ||||||
|  |   | ||||||
|  | @@ -515,7 +519,7 @@ poolGrow(STRING_POOL * const poolP,
 | ||||||
|  |              size_t const newSize = | ||||||
|  |                  offsetof(BLOCK, s) + blockSize * sizeof(XML_Char); | ||||||
|  |   | ||||||
|  | -                BLOCK * const newBlocksP = malloc(newSize);
 | ||||||
|  | +            BLOCK * const newBlocksP = calloc(offsetof(BLOCK, s) + blockSize, sizeof(XML_Char));
 | ||||||
|  |   | ||||||
|  |              if (newBlocksP) { | ||||||
|  |                  newBlocksP->size = blockSize; | ||||||
|  | @@ -1143,6 +1147,7 @@ const XML_Char *getContext(XML_Parser parser)
 | ||||||
|  |  { | ||||||
|  |    HASH_TABLE_ITER iter; | ||||||
|  |    int needSep = 0; | ||||||
|  | +  Parser * const parserP = (Parser *) parser;
 | ||||||
|  |   | ||||||
|  |    if (dtd.defaultPrefix.binding) { | ||||||
|  |      int i; | ||||||
|  | @@ -1191,7 +1196,7 @@ const XML_Char *getContext(XML_Parser parser)
 | ||||||
|  |      ENTITY *e = (ENTITY *)hashTableIterNext(&iter); | ||||||
|  |      if (!e) | ||||||
|  |        break; | ||||||
|  | -    if (!e->open)
 | ||||||
|  | +    if (!e->open || parserP->m_recurse_lock > MAX_RECURSE)
 | ||||||
|  |        continue; | ||||||
|  |      if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) | ||||||
|  |        return 0; | ||||||
|  | @@ -1210,6 +1215,7 @@ static
 | ||||||
|  |  int setContext(XML_Parser parser, const XML_Char *context) | ||||||
|  |  { | ||||||
|  |    const XML_Char *s = context; | ||||||
|  | +  Parser * const parserP = (Parser *) parser;
 | ||||||
|  |   | ||||||
|  |    while (*context != XML_T('\0')) { | ||||||
|  |      if (*s == CONTEXT_SEP || *s == XML_T('\0')) { | ||||||
|  | @@ -1218,8 +1224,9 @@ int setContext(XML_Parser parser, const XML_Char *context)
 | ||||||
|  |          return 0; | ||||||
|  |        e = (ENTITY *)lookup(parser, &dtd.generalEntities, poolStart(&tempPool), | ||||||
|  |                             0); | ||||||
|  | -      if (e)
 | ||||||
|  | +      if (e) {
 | ||||||
|  |          e->open = 1; | ||||||
|  | + 	}
 | ||||||
|  |        if (*s != XML_T('\0')) | ||||||
|  |          s++; | ||||||
|  |        context = s; | ||||||
|  | @@ -1860,7 +1867,7 @@ appendAttributeValue(XML_Parser       const xmlParserP,
 | ||||||
|  |              return XML_ERROR_UNDEFINED_ENTITY; | ||||||
|  |            } | ||||||
|  |          } | ||||||
|  | -        else if (entity->open) {
 | ||||||
|  | +        else if (entity->open || parser->m_recurse_lock > MAX_RECURSE) {
 | ||||||
|  |            if (enc == parser->m_encoding) | ||||||
|  |              eventPtr = ptr; | ||||||
|  |            return XML_ERROR_RECURSIVE_ENTITY_REF; | ||||||
|  | @@ -1879,10 +1886,12 @@ appendAttributeValue(XML_Parser       const xmlParserP,
 | ||||||
|  |            enum XML_Error result; | ||||||
|  |            const XML_Char *textEnd = entity->textPtr + entity->textLen; | ||||||
|  |            entity->open = 1; | ||||||
|  | +	  parser->m_recurse_lock++;
 | ||||||
|  |            result = appendAttributeValue(xmlParserP, internalEncoding, | ||||||
|  |                                          isCdata, (char *)entity->textPtr, | ||||||
|  |                                          (char *)textEnd, pool); | ||||||
|  |            entity->open = 0; | ||||||
|  | +	  parser->m_recurse_lock--;
 | ||||||
|  |            if (result) | ||||||
|  |              return result; | ||||||
|  |          } | ||||||
|  | @@ -1952,7 +1961,7 @@ storeEntityValue(XML_Parser       const xmlParserP,
 | ||||||
|  |              eventPtr = entityTextPtr; | ||||||
|  |            return XML_ERROR_UNDEFINED_ENTITY; | ||||||
|  |          } | ||||||
|  | -        if (entity->open) {
 | ||||||
|  | +        if (entity->open || parser->m_recurse_lock > MAX_RECURSE) {
 | ||||||
|  |            if (enc == parser->m_encoding) | ||||||
|  |              eventPtr = entityTextPtr; | ||||||
|  |            return XML_ERROR_RECURSIVE_ENTITY_REF; | ||||||
|  | @@ -2641,8 +2650,13 @@ doInternalEntityRef(XML_Parser       const xmlParserP,
 | ||||||
|  |          *errorP = NULL; | ||||||
|  |      } else { | ||||||
|  |          OPEN_INTERNAL_ENTITY openEntity; | ||||||
|  | +        if (entityP->open || parserP->m_recurse_lock > MAX_RECURSE) {
 | ||||||
|  | +            *errorCodeP = XML_ERROR_RECURSIVE_ENTITY_REF;
 | ||||||
|  | +            return;
 | ||||||
|  | +        }
 | ||||||
|  |   | ||||||
|  |          entityP->open = 1;  /* recursion control */ | ||||||
|  | +	parserP->m_recurse_lock++;
 | ||||||
|  |   | ||||||
|  |          openEntity.next = parserP->m_openInternalEntities; | ||||||
|  |   | ||||||
|  | @@ -2659,6 +2673,7 @@ doInternalEntityRef(XML_Parser       const xmlParserP,
 | ||||||
|  |                    0, errorCodeP, errorP); | ||||||
|  |   | ||||||
|  |          entityP->open = 0;  /* recursion control */ | ||||||
|  | +	parserP->m_recurse_lock--;
 | ||||||
|  |          parserP->m_openInternalEntities = openEntity.next; | ||||||
|  |      } | ||||||
|  |  } | ||||||
|  | @@ -2681,8 +2696,14 @@ doExternalEntityRef(XML_Parser       const xmlParserP,
 | ||||||
|  |      if (parserP->m_externalEntityRefHandler) { | ||||||
|  |          const XML_Char * contextP; | ||||||
|  |   | ||||||
|  | +    	if (entityP->open || parserP->m_recurse_lock > MAX_RECURSE) {
 | ||||||
|  | +            *errorCodeP = XML_ERROR_RECURSIVE_ENTITY_REF;
 | ||||||
|  | +	    return;
 | ||||||
|  | +	}
 | ||||||
|  |          entityP->open = 1; | ||||||
|  | +	parserP->m_recurse_lock++;
 | ||||||
|  |          contextP = getContext(xmlParserP); | ||||||
|  | +	parserP->m_recurse_lock--;
 | ||||||
|  |          entityP->open = 0; | ||||||
|  |   | ||||||
|  |          if (!contextP) | ||||||
|  | @@ -2753,7 +2774,7 @@ doEntityRef(XML_Parser       const xmlParserP,
 | ||||||
|  |                      *errorCodeP = XML_ERROR_NONE; | ||||||
|  |                  } | ||||||
|  |              } else { | ||||||
|  | -                if (entityP->open)
 | ||||||
|  | +                if (entityP->open || parserP->m_recurse_lock > MAX_RECURSE)
 | ||||||
|  |                      *errorCodeP = XML_ERROR_RECURSIVE_ENTITY_REF; | ||||||
|  |                  else if (entityP->notation) | ||||||
|  |                      *errorCodeP = XML_ERROR_BINARY_ENTITY_REF; | ||||||
|  | @@ -4059,7 +4080,7 @@ doProlog(XML_Parser       const xmlParserP,
 | ||||||
|  |            *errorCodeP = XML_ERROR_UNDEFINED_ENTITY; | ||||||
|  |            return; | ||||||
|  |          } | ||||||
|  | -        if (entity->open) {
 | ||||||
|  | +        if (entity->open || parser->m_recurse_lock > MAX_RECURSE) {
 | ||||||
|  |            *errorCodeP = XML_ERROR_RECURSIVE_ENTITY_REF; | ||||||
|  |            return; | ||||||
|  |          } | ||||||
|  | @@ -4076,16 +4097,19 @@ doProlog(XML_Parser       const xmlParserP,
 | ||||||
|  |          if (externalEntityRefHandler) { | ||||||
|  |            dtd.complete = 0; | ||||||
|  |            entity->open = 1; | ||||||
|  | +          parser->m_recurse_lock++;
 | ||||||
|  |            if (!externalEntityRefHandler(externalEntityRefHandlerArg, | ||||||
|  |                                          0, | ||||||
|  |                                          entity->base, | ||||||
|  |                                          entity->systemId, | ||||||
|  |                                          entity->publicId)) { | ||||||
|  |              entity->open = 0; | ||||||
|  | +            parser->m_recurse_lock--;
 | ||||||
|  |              *errorCodeP = XML_ERROR_EXTERNAL_ENTITY_HANDLING; | ||||||
|  |              return; | ||||||
|  |            } | ||||||
|  |            entity->open = 0; | ||||||
|  | +          parser->m_recurse_lock--;
 | ||||||
|  |            if (dtd.complete) | ||||||
|  |              break; | ||||||
|  |          } | ||||||
|  | @@ -4199,6 +4223,7 @@ processInternalParamEntity(XML_Parser       const parser,
 | ||||||
|  |      const char *s, *end, *next; | ||||||
|  |      int tok; | ||||||
|  |      OPEN_INTERNAL_ENTITY openEntity; | ||||||
|  | +    Parser * const parserP = (Parser *) parser;
 | ||||||
|  |   | ||||||
|  |      entity->open = 1; | ||||||
|  |      openEntity.next = openInternalEntities; | ||||||
|  | @@ -4292,6 +4317,7 @@ xmlrpc_XML_ParserCreate(const XML_Char * const encodingName) {
 | ||||||
|  |          parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; | ||||||
|  |          parser->m_hash_secret_salt = 0; | ||||||
|  |          parser->m_ns = 0; | ||||||
|  | +        parser->m_recurse_lock = 0;
 | ||||||
|  |          poolInit(&parser->m_tempPool); | ||||||
|  |          poolInit(&parser->m_temp2Pool); | ||||||
|  |          parser->m_protocolEncodingName = | ||||||
|  | diff --git a/test/Makefile b/test/Makefile
 | ||||||
|  | index 1242910..59c698c 100644
 | ||||||
|  | --- a/test/Makefile
 | ||||||
|  | +++ b/test/Makefile
 | ||||||
|  | @@ -16,9 +16,9 @@ LDADD_CGI_SERVER = \
 | ||||||
|  |   | ||||||
|  |  default: all | ||||||
|  |   | ||||||
|  | -INCLUDES = -I$(BLDDIR) -Isrcdir/include -Isrcdir/lib/util/include \
 | ||||||
|  | +INCLUDES = -I$(BLDDIR) -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include \
 | ||||||
|  |   | ||||||
|  | -PROGS = test cgitest1
 | ||||||
|  | +PROGS = test cgitest1 overflow_attr_test overflow_entity_test
 | ||||||
|  |   | ||||||
|  |  all: $(PROGS) $(SUBDIRS:%=%/all) | ||||||
|  |   | ||||||
|  | @@ -86,6 +86,28 @@ OBJS = $(TEST_OBJS) cgitest1.o
 | ||||||
|  |  $(OBJS):%.o:%.c | ||||||
|  |  	$(CC) -c $(INCLUDES) $(CFLAGS_ALL) $< | ||||||
|  |   | ||||||
|  | +OVERFLOW_ATTR_OBJS = overflow_attr_test.o
 | ||||||
|  | +
 | ||||||
|  | +overflow_attr_test: $(OVERFLOW_ATTR_OBJS) $(LIBXMLRPC_SERVER_A) \
 | ||||||
|  | +  $(LIBXMLRPC_A) $(LIBXMLRPC_UTIL_A) $(LIBXMLRPC_XML)
 | ||||||
|  | +	$(CCLD) -o $@ $(LDFLAGS_ALL) \
 | ||||||
|  | +	    $(OVERFLOW_ATTR_OBJS) $(LDADD_CLIENT) $(LDADD_ABYSS_SERVER) $(CASPRINTF)
 | ||||||
|  | +OBJS = overflow_attr_test.o
 | ||||||
|  | +
 | ||||||
|  | +$(OBJS):%.o:%.c
 | ||||||
|  | +	$(CC) -c $(INCLUDES) -I$(SRCDIR)/lib/expat/xmlparse/ $(CFLAGS_ALL) $<
 | ||||||
|  | +
 | ||||||
|  | +OVERFLOW_ENTITY_OBJS = overflow_entity_test.o
 | ||||||
|  | +
 | ||||||
|  | +overflow_entity_test: $(OVERFLOW_ENTITY_OBJS) $(LIBXMLRPC_SERVER_A) \
 | ||||||
|  | +  $(LIBXMLRPC_A) $(LIBXMLRPC_UTIL_A) $(LIBXMLRPC_XML)
 | ||||||
|  | +	$(CCLD) -o $@ $(LDFLAGS_ALL) \
 | ||||||
|  | +	    $(OVERFLOW_ENTITY_OBJS) $(LDADD_CLIENT) $(LDADD_ABYSS_SERVER) $(CASPRINTF)
 | ||||||
|  | +OBJS = overflow_entity_test.o
 | ||||||
|  | +
 | ||||||
|  | +$(OBJS):%.o:%.c
 | ||||||
|  | +	$(CC) -c $(INCLUDES) -I$(SRCDIR)/lib/expat/xmlparse/ $(CFLAGS_ALL) $<
 | ||||||
|  | +
 | ||||||
|  |  # Note the difference between 'check' and 'runtests'.  'check' means to check | ||||||
|  |  # our own correctness.  'runtests' means to run the tests that check our | ||||||
|  |  # parent's correctness | ||||||
|  | @@ -94,8 +116,10 @@ $(OBJS):%.o:%.c
 | ||||||
|  |  check: | ||||||
|  |   | ||||||
|  |  .PHONY: runtests_local | ||||||
|  | -runtests_local: test cgitest1
 | ||||||
|  | +runtests_local: test cgitest1 overflow_attr_test overflow_entity_test
 | ||||||
|  |  	./test | ||||||
|  | +	./overflow_attr_test
 | ||||||
|  | +	./overflow_entity_test
 | ||||||
|  |   | ||||||
|  |  .PHONY: runtests | ||||||
|  |  runtests: runtests_local cpp/runtests benchmark/runtests | ||||||
|  | diff --git a/test/overflow_attr_test.c b/test/overflow_attr_test.c
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000..eb06556
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/test/overflow_attr_test.c
 | ||||||
|  | @@ -0,0 +1,88 @@
 | ||||||
|  | +/* gcc -g -std=c11 -D_POSIX_C_SOURCE=200809L -I lib/expat/xmlparse  -lxmlrpc_xmlparse -lxmlrpc_xmltok overflow_attr_test.c -o overflow_attr_test */
 | ||||||
|  | +
 | ||||||
|  | +#include <err.h>
 | ||||||
|  | +#include <stdio.h>
 | ||||||
|  | +#include <stdlib.h>
 | ||||||
|  | +#include <unistd.h>
 | ||||||
|  | +#include <sys/stat.h>
 | ||||||
|  | +#include "xmlparse.h"
 | ||||||
|  | +#include <string.h>
 | ||||||
|  | +
 | ||||||
|  | +#define XML_STATUS_OK       1
 | ||||||
|  | +#define XML_STATUS_ERROR    0
 | ||||||
|  | +
 | ||||||
|  | +typedef unsigned char XML_Bool;
 | ||||||
|  | +#define XML_TRUE ((XML_Bool)1)
 | ||||||
|  | +#define XML_FALSE ((XML_Bool)0)
 | ||||||
|  | +    
 | ||||||
|  | +#define SIZE_PER_LINE 50
 | ||||||
|  | +
 | ||||||
|  | +static int
 | ||||||
|  | +doParse(int N_LINES) {
 | ||||||
|  | +  XML_Parser parser;
 | ||||||
|  | +  char tmp[SIZE_PER_LINE];
 | ||||||
|  | +  int ret = 0;
 | ||||||
|  | +  int rval = 0;
 | ||||||
|  | +
 | ||||||
|  | +  if ((parser = xmlrpc_XML_ParserCreate(NULL)) == NULL)
 | ||||||
|  | +    errx(1, "XML_ParserCreate");
 | ||||||
|  | +
 | ||||||
|  | +  char *const text = (char *)malloc((N_LINES + 4) * SIZE_PER_LINE);
 | ||||||
|  | +  if (text == NULL) {
 | ||||||
|  | +    printf("malloc failed");
 | ||||||
|  | +    return 1;
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  // Create the XML
 | ||||||
|  | +  snprintf(text, SIZE_PER_LINE,
 | ||||||
|  | +                      "<!DOCTYPE foo [\n"
 | ||||||
|  | +                      "    <!ENTITY s0 'deepText'>\n");
 | ||||||
|  | +
 | ||||||
|  | +  for (size_t i = 1; i < N_LINES; ++i) {
 | ||||||
|  | +    snprintf(tmp, SIZE_PER_LINE, "  <!ENTITY s%lu '&s%lu;'>\n",
 | ||||||
|  | +                        (long unsigned)i, (long unsigned)(i - 1));
 | ||||||
|  | +    strncat(text, tmp, SIZE_PER_LINE);
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  snprintf(tmp, SIZE_PER_LINE, "]> <foo name='&s%lu;'>mainText</foo>\n",
 | ||||||
|  | +           (long unsigned)(N_LINES - 1));
 | ||||||
|  | +  strncat(text, tmp, SIZE_PER_LINE);
 | ||||||
|  | +
 | ||||||
|  | +  ret = xmlrpc_XML_Parse(parser, text, strlen(text), XML_TRUE);
 | ||||||
|  | +  if (ret == XML_STATUS_ERROR) {
 | ||||||
|  | +    int err = xmlrpc_XML_GetErrorCode(parser);
 | ||||||
|  | +    if (err == XML_ERROR_RECURSIVE_ENTITY_REF) {
 | ||||||
|  | +      if (N_LINES <= 28) {
 | ||||||
|  | +         printf("%d Unexpected FAIL (%s)\n", N_LINES, xmlrpc_XML_ErrorString(err));
 | ||||||
|  | +      } else {
 | ||||||
|  | +         printf("%d expected failure OK (%s)\n", N_LINES, xmlrpc_XML_ErrorString(err));
 | ||||||
|  | +      }
 | ||||||
|  | +    } else {
 | ||||||
|  | +      printf("%d Unexpected FAIL (%s)\n", N_LINES, xmlrpc_XML_ErrorString(err));
 | ||||||
|  | +      rval = 1;
 | ||||||
|  | +    }
 | ||||||
|  | +  } else {
 | ||||||
|  | +    printf("%d OK\n", N_LINES);
 | ||||||
|  | +  }
 | ||||||
|  | +  free(text);
 | ||||||
|  | +  xmlrpc_XML_ParserFree(parser);
 | ||||||
|  | +  return rval;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +int main(int argc, char *argv[]) {
 | ||||||
|  | +  int status = 0;
 | ||||||
|  | +
 | ||||||
|  | +  for (int i = 2; i <= 28; i++ )
 | ||||||
|  | +      status += doParse(i);
 | ||||||
|  | +
 | ||||||
|  | +  status += doParse(29);
 | ||||||
|  | +  status += doParse(30);
 | ||||||
|  | +  status += doParse(100);
 | ||||||
|  | +  status += doParse(1000);
 | ||||||
|  | +  status += doParse(10000);
 | ||||||
|  | +  status += doParse(60000);
 | ||||||
|  | +
 | ||||||
|  | +  if (status == 0)
 | ||||||
|  | +    printf("PASSED\n");
 | ||||||
|  | +  return (status != 0);
 | ||||||
|  | +}
 | ||||||
|  | diff --git a/test/overflow_entity_test.c b/test/overflow_entity_test.c
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000..d0d1290
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/test/overflow_entity_test.c
 | ||||||
|  | @@ -0,0 +1,86 @@
 | ||||||
|  | +/* gcc -g -std=c11 -D_POSIX_C_SOURCE=200809L -I lib/expat/xmlparse  -lxmlrpc_xmlparse -lxmlrpc_xmltok overflow_entity_test.c -o overflow_entity_test */
 | ||||||
|  | +
 | ||||||
|  | +#include <err.h>
 | ||||||
|  | +#include <stdio.h>
 | ||||||
|  | +#include <stdlib.h>
 | ||||||
|  | +#include <unistd.h>
 | ||||||
|  | +#include <sys/stat.h>
 | ||||||
|  | +#include "xmlparse.h"
 | ||||||
|  | +#include <string.h>
 | ||||||
|  | +
 | ||||||
|  | +#define XML_STATUS_OK       1
 | ||||||
|  | +#define XML_STATUS_ERROR    0
 | ||||||
|  | +
 | ||||||
|  | +typedef unsigned char XML_Bool;
 | ||||||
|  | +#define XML_TRUE ((XML_Bool)1)
 | ||||||
|  | +#define XML_FALSE ((XML_Bool)0)
 | ||||||
|  | +    
 | ||||||
|  | +#define SIZE_PER_LINE 50
 | ||||||
|  | +
 | ||||||
|  | +static int
 | ||||||
|  | +doParse(int N_LINES) {
 | ||||||
|  | +  XML_Parser parser;
 | ||||||
|  | +  char tmp[SIZE_PER_LINE];
 | ||||||
|  | +  int ret = 0;
 | ||||||
|  | +  int rval = 0;
 | ||||||
|  | +
 | ||||||
|  | +  if ((parser = xmlrpc_XML_ParserCreate(NULL)) == NULL)
 | ||||||
|  | +    errx(1, "XML_ParserCreate");
 | ||||||
|  | +
 | ||||||
|  | +  char *const text = (char *)malloc((N_LINES + 4) * SIZE_PER_LINE);
 | ||||||
|  | +  if (text == NULL) {
 | ||||||
|  | +    printf("malloc failed");
 | ||||||
|  | +    return 1;  
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  // Create the XML
 | ||||||
|  | +  snprintf(text, SIZE_PER_LINE,
 | ||||||
|  | +                      "<!DOCTYPE foo [\n"
 | ||||||
|  | +                      "    <!ENTITY s0 'deepText'>\n");
 | ||||||
|  | +
 | ||||||
|  | +  for (size_t i = 1; i < N_LINES; ++i) {
 | ||||||
|  | +    snprintf(tmp, SIZE_PER_LINE, "  <!ENTITY s%lu '&s%lu;'>\n",
 | ||||||
|  | +                        (long unsigned)i, (long unsigned)(i - 1));
 | ||||||
|  | +    strncat(text, tmp, SIZE_PER_LINE);
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  snprintf(tmp, SIZE_PER_LINE, "]> <foo>&s%lu;</foo>\n",
 | ||||||
|  | +           (long unsigned)(N_LINES - 1));
 | ||||||
|  | +  strncat(text, tmp, SIZE_PER_LINE);
 | ||||||
|  | +
 | ||||||
|  | +  ret = xmlrpc_XML_Parse(parser, text, strlen(text), XML_TRUE);
 | ||||||
|  | +  if (ret == XML_STATUS_ERROR){
 | ||||||
|  | +    int err = xmlrpc_XML_GetErrorCode(parser);
 | ||||||
|  | +    if (err == XML_ERROR_RECURSIVE_ENTITY_REF) {
 | ||||||
|  | +      if (N_LINES <= 28) {
 | ||||||
|  | +         printf("%d Unexpected FAIL (%s)\n", N_LINES, xmlrpc_XML_ErrorString(err));
 | ||||||
|  | +         rval = 1;
 | ||||||
|  | +      } else {
 | ||||||
|  | +         printf("%d expected failure OK (%s)\n", N_LINES, xmlrpc_XML_ErrorString(err));
 | ||||||
|  | +      }
 | ||||||
|  | +    }
 | ||||||
|  | +  } else {
 | ||||||
|  | +    printf("%d OK\n", N_LINES);
 | ||||||
|  | +  }
 | ||||||
|  | +  free(text);
 | ||||||
|  | +  xmlrpc_XML_ParserFree(parser);
 | ||||||
|  | +  return rval;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +int main(int argc, char *argv[]) {
 | ||||||
|  | +  int status = 0;
 | ||||||
|  | +
 | ||||||
|  | +  for (int i = 2; i <= 28; i++ )
 | ||||||
|  | +      status += doParse(i);
 | ||||||
|  | +
 | ||||||
|  | +  status += doParse(29);
 | ||||||
|  | +  status += doParse(30);
 | ||||||
|  | +  status += doParse(100);
 | ||||||
|  | +  status += doParse(1000);
 | ||||||
|  | +  status += doParse(10000);
 | ||||||
|  | +  status += doParse(60000);
 | ||||||
|  | +
 | ||||||
|  | +  if (status == 0)
 | ||||||
|  | +    printf("PASSED\n");
 | ||||||
|  | +  return (status != 0);
 | ||||||
|  | +}
 | ||||||
|  | -- 
 | ||||||
|  | 2.43.5 | ||||||
|  | 
 | ||||||
							
								
								
									
										286
									
								
								0010-Add-missing-files-for-the-benchmark-tests.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								0010-Add-missing-files-for-the-benchmark-tests.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,286 @@ | |||||||
|  | From 0f3661572b50df9878412181dc600e69eafbd868 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: root <root@vm-10-0-185-207.hosted.upshift.rdu2.redhat.com> | ||||||
|  | Date: Wed, 19 Mar 2025 13:54:48 -0400 | ||||||
|  | Subject: [PATCH] Add missing files for the benchmark tests | ||||||
|  | 
 | ||||||
|  | The SOURCES tarball needs to be manually unpacked. | ||||||
|  | ---
 | ||||||
|  |  test/benchmark/Makefile    |  82 ++++++++++++++++++++ | ||||||
|  |  test/benchmark/README.txt  |  16 ++++ | ||||||
|  |  test/benchmark/benchmark.c | 152 +++++++++++++++++++++++++++++++++++++ | ||||||
|  |  3 files changed, 250 insertions(+) | ||||||
|  |  create mode 100644 test/benchmark/Makefile | ||||||
|  |  create mode 100644 test/benchmark/README.txt | ||||||
|  |  create mode 100644 test/benchmark/benchmark.c | ||||||
|  | 
 | ||||||
|  | diff --git a/test/benchmark/Makefile b/test/benchmark/Makefile
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000..20e648c
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/test/benchmark/Makefile
 | ||||||
|  | @@ -0,0 +1,82 @@
 | ||||||
|  | +ifeq ($(SRCDIR),)
 | ||||||
|  | +  updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
 | ||||||
|  | +  testDIR := $(call updir,$(CURDIR))
 | ||||||
|  | +  SRCDIR := $(call updir,$(testDIR))
 | ||||||
|  | +  BLDDIR := $(SRCDIR)
 | ||||||
|  | +endif
 | ||||||
|  | +SUBDIR := test/benchmark
 | ||||||
|  | +
 | ||||||
|  | +include $(BLDDIR)/config.mk
 | ||||||
|  | +
 | ||||||
|  | +PROGS = benchmark
 | ||||||
|  | +
 | ||||||
|  | +default: all
 | ||||||
|  | +
 | ||||||
|  | +all: $(PROGS)
 | ||||||
|  | +
 | ||||||
|  | +XMLRPC_C_CONFIG = $(BLDDIR)/xmlrpc-c-config.test
 | ||||||
|  | +
 | ||||||
|  | +LIBS := 
 | ||||||
|  | +
 | ||||||
|  | +LIBS += $(SOCKETLIBOPT) $(THREAD_LIBS)
 | ||||||
|  | +
 | ||||||
|  | +INCLUDES = -Isrcdir/include -I$(BLDDIR) -Isrcdir -Isrcdir/lib/util/include -Isrcdir/lib/expat/xmlparse
 | ||||||
|  | +
 | ||||||
|  | +# This 'common.mk' dependency makes sure the symlinks get built before
 | ||||||
|  | +# this make file is used for anything.
 | ||||||
|  | +
 | ||||||
|  | +$(SRCDIR)/common.mk: srcdir blddir
 | ||||||
|  | +
 | ||||||
|  | +include $(SRCDIR)/common.mk
 | ||||||
|  | +
 | ||||||
|  | +CFLAGS += $(INCLUDES)
 | ||||||
|  | +
 | ||||||
|  | +TEST_OBJS = benchmark.o
 | ||||||
|  | +
 | ||||||
|  | +#-----------------------------------------------------------------------------
 | ||||||
|  | +#  TEST_LIBS
 | ||||||
|  | +#-----------------------------------------------------------------------------
 | ||||||
|  | +TEST_LIBS =
 | ||||||
|  | +TEST_LIBS += $(LIBXMLRPC_UTIL_A)
 | ||||||
|  | +TEST_LIBS += $(LIBXMLRPC_XMLPARSE_A)
 | ||||||
|  | +TEST_LIBS += $(LIBXMLRPC_XMLTOK_A)
 | ||||||
|  | +
 | ||||||
|  | +benchmark: $(TEST_OBJS) $(TEST_LIBS)
 | ||||||
|  | +	$(CXXLD) -o $@ $(INCLUDES) $(LDFLAGS_ALL) $^ $(LIB_XML) $(TEST_LIBS)
 | ||||||
|  | +
 | ||||||
|  | +%.o:%.cpp
 | ||||||
|  | +	$(CC) -c $(INCLUDES) $(CXXFLAGS_ALL) $(D_INTERNAL_EXPAT) $<
 | ||||||
|  | +
 | ||||||
|  | +# Note the difference between 'check' and 'runtests'.  'check' means to check
 | ||||||
|  | +# our own correctness.  'runtests' means to run the tests that check our
 | ||||||
|  | +# parent's correctness
 | ||||||
|  | +
 | ||||||
|  | +.PHONY: check
 | ||||||
|  | +check:
 | ||||||
|  | +
 | ||||||
|  | +.PHONY: runtests
 | ||||||
|  | +runtests: benchmark
 | ||||||
|  | +	./benchmark aaaaaa_attr.xml 4096 1
 | ||||||
|  | +	./benchmark aaaaaa_comment.xml 4096 1
 | ||||||
|  | +	./benchmark aaaaaa_tag.xml 4096 1
 | ||||||
|  | +	./benchmark aaaaaa_text.xml 4096 1
 | ||||||
|  | +	-./benchmark aaaaaa_cdata.xml 4096 1
 | ||||||
|  | +	echo "PASSED"
 | ||||||
|  | +
 | ||||||
|  | +.PHONY: install
 | ||||||
|  | +install:
 | ||||||
|  | +
 | ||||||
|  | +.PHONY: uninstall
 | ||||||
|  | +uninstall:
 | ||||||
|  | +
 | ||||||
|  | +.PHONY: clean clean-local distclean
 | ||||||
|  | +clean: clean-common clean-local
 | ||||||
|  | +clean-local:
 | ||||||
|  | +	rm -f $(PROGS)
 | ||||||
|  | +
 | ||||||
|  | +distclean: clean distclean-common
 | ||||||
|  | +
 | ||||||
|  | +.PHONY: dep
 | ||||||
|  | +dep: dep-common
 | ||||||
|  | +
 | ||||||
|  | +include depend.mk
 | ||||||
|  | diff --git a/test/benchmark/README.txt b/test/benchmark/README.txt
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000..86414d5
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/test/benchmark/README.txt
 | ||||||
|  | @@ -0,0 +1,16 @@
 | ||||||
|  | +Use this benchmark command line utility as follows:
 | ||||||
|  | +
 | ||||||
|  | +  benchmark [-n] <file name> <buffer size> <# iterations>
 | ||||||
|  | +
 | ||||||
|  | +The command line arguments are:
 | ||||||
|  | +
 | ||||||
|  | +  -n             ... optional; if supplied, namespace processing is turned on
 | ||||||
|  | +  <file name>    ... name/path of test xml file
 | ||||||
|  | +  <buffer size>  ... size of processing buffer;
 | ||||||
|  | +                     the file is parsed in chunks of this size
 | ||||||
|  | +  <# iterations> ... how often will the file be parsed
 | ||||||
|  | +
 | ||||||
|  | +Returns:
 | ||||||
|  | +
 | ||||||
|  | +  The time (in seconds) it takes to parse the test file,
 | ||||||
|  | +  averaged over the number of iterations.@
 | ||||||
|  | diff --git a/test/benchmark/benchmark.c b/test/benchmark/benchmark.c
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000..3864280
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/test/benchmark/benchmark.c
 | ||||||
|  | @@ -0,0 +1,152 @@
 | ||||||
|  | +/*
 | ||||||
|  | +                            __  __            _
 | ||||||
|  | +                         ___\ \/ /_ __   __ _| |_
 | ||||||
|  | +                        / _ \\  /| '_ \ / _` | __|
 | ||||||
|  | +                       |  __//  \| |_) | (_| | |_
 | ||||||
|  | +                        \___/_/\_\ .__/ \__,_|\__|
 | ||||||
|  | +                                 |_| XML parser
 | ||||||
|  | +
 | ||||||
|  | +   Copyright (c) 2003-2006 Karl Waclawek <karl@waclawek.net>
 | ||||||
|  | +   Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
 | ||||||
|  | +   Copyright (c) 2017      Sebastian Pipping <sebastian@pipping.org>
 | ||||||
|  | +   Copyright (c) 2017      Rhodri James <rhodri@wildebeest.org.uk>
 | ||||||
|  | +   Licensed under the MIT license:
 | ||||||
|  | +
 | ||||||
|  | +   Permission is  hereby granted,  free of charge,  to any  person obtaining
 | ||||||
|  | +   a  copy  of  this  software   and  associated  documentation  files  (the
 | ||||||
|  | +   "Software"),  to  deal in  the  Software  without restriction,  including
 | ||||||
|  | +   without  limitation the  rights  to use,  copy,  modify, merge,  publish,
 | ||||||
|  | +   distribute, sublicense, and/or sell copies of the Software, and to permit
 | ||||||
|  | +   persons  to whom  the Software  is  furnished to  do so,  subject to  the
 | ||||||
|  | +   following conditions:
 | ||||||
|  | +
 | ||||||
|  | +   The above copyright  notice and this permission notice  shall be included
 | ||||||
|  | +   in all copies or substantial portions of the Software.
 | ||||||
|  | +
 | ||||||
|  | +   THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
 | ||||||
|  | +   EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
 | ||||||
|  | +   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
 | ||||||
|  | +   NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 | ||||||
|  | +   DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
 | ||||||
|  | +   OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 | ||||||
|  | +   USE OR OTHER DEALINGS IN THE SOFTWARE.
 | ||||||
|  | +*/
 | ||||||
|  | +
 | ||||||
|  | +#include <sys/stat.h>
 | ||||||
|  | +#include <assert.h>
 | ||||||
|  | +#include <stddef.h> // ptrdiff_t
 | ||||||
|  | +#include <stdlib.h>
 | ||||||
|  | +#include <stdio.h>
 | ||||||
|  | +#include <time.h>
 | ||||||
|  | +#include "xmlparse.h"
 | ||||||
|  | +
 | ||||||
|  | +#ifdef XML_LARGE_SIZE
 | ||||||
|  | +#  define XML_FMT_INT_MOD "ll"
 | ||||||
|  | +#else
 | ||||||
|  | +#  define XML_FMT_INT_MOD "l"
 | ||||||
|  | +#endif
 | ||||||
|  | +
 | ||||||
|  | +#ifdef XML_UNICODE_WCHAR_T
 | ||||||
|  | +#  define XML_FMT_STR "ls"
 | ||||||
|  | +#else
 | ||||||
|  | +#  define XML_FMT_STR "s"
 | ||||||
|  | +#endif
 | ||||||
|  | +
 | ||||||
|  | +static void
 | ||||||
|  | +usage(const char *prog, int rc) {
 | ||||||
|  | +  fprintf(stderr, "usage: %s [-n] filename bufferSize nr_of_loops\n", prog);
 | ||||||
|  | +  exit(rc);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +int
 | ||||||
|  | +main(int argc, char *argv[]) {
 | ||||||
|  | +  XML_Parser parser;
 | ||||||
|  | +  char *XMLBuf, *XMLBufEnd, *XMLBufPtr;
 | ||||||
|  | +  FILE *fd;
 | ||||||
|  | +  struct stat fileAttr;
 | ||||||
|  | +  int nrOfLoops, bufferSize, i, isFinal;
 | ||||||
|  | +  size_t fileSize;
 | ||||||
|  | +  int j = 0, ns = 0;
 | ||||||
|  | +  clock_t tstart, tend;
 | ||||||
|  | +  double cpuTime = 0.0;
 | ||||||
|  | +
 | ||||||
|  | +  if (argc > 1) {
 | ||||||
|  | +    if (argv[1][0] == '-') {
 | ||||||
|  | +      if (argv[1][1] == 'n' && argv[1][2] == '\0') {
 | ||||||
|  | +        ns = 1;
 | ||||||
|  | +        j = 1;
 | ||||||
|  | +      } else
 | ||||||
|  | +        usage(argv[0], 1);
 | ||||||
|  | +    }
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  if (argc != j + 4)
 | ||||||
|  | +    usage(argv[0], 1);
 | ||||||
|  | +
 | ||||||
|  | +  if (stat(argv[j + 1], &fileAttr) != 0) {
 | ||||||
|  | +    fprintf(stderr, "could not access file '%s'\n", argv[j + 1]);
 | ||||||
|  | +    return 2;
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  fd = fopen(argv[j + 1], "r");
 | ||||||
|  | +  if (! fd) {
 | ||||||
|  | +    fprintf(stderr, "could not open file '%s'\n", argv[j + 1]);
 | ||||||
|  | +    exit(2);
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  bufferSize = atoi(argv[j + 2]);
 | ||||||
|  | +  nrOfLoops = atoi(argv[j + 3]);
 | ||||||
|  | +  if (bufferSize <= 0 || nrOfLoops <= 0) {
 | ||||||
|  | +    fprintf(stderr, "buffer size and nr of loops must be greater than zero.\n");
 | ||||||
|  | +    exit(3);
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  XMLBuf = malloc(fileAttr.st_size);
 | ||||||
|  | +  fileSize = fread(XMLBuf, sizeof(char), fileAttr.st_size, fd);
 | ||||||
|  | +  fclose(fd);
 | ||||||
|  | +
 | ||||||
|  | +  if (ns)
 | ||||||
|  | +    parser = xmlrpc_XML_ParserCreateNS(NULL, '!');
 | ||||||
|  | +  else
 | ||||||
|  | +    parser = xmlrpc_XML_ParserCreate(NULL);
 | ||||||
|  | +
 | ||||||
|  | +  i = 0;
 | ||||||
|  | +  XMLBufEnd = XMLBuf + fileSize;
 | ||||||
|  | +  while (i < nrOfLoops) {
 | ||||||
|  | +    XMLBufPtr = XMLBuf;
 | ||||||
|  | +    isFinal = 0;
 | ||||||
|  | +    tstart = clock();
 | ||||||
|  | +    do {
 | ||||||
|  | +      ptrdiff_t parseBufferSize = XMLBufEnd - XMLBufPtr;
 | ||||||
|  | +      if (parseBufferSize <= (ptrdiff_t)bufferSize)
 | ||||||
|  | +        isFinal = 1;
 | ||||||
|  | +      else
 | ||||||
|  | +        parseBufferSize = bufferSize;
 | ||||||
|  | +      assert(parseBufferSize <= (ptrdiff_t)bufferSize);
 | ||||||
|  | +      if (! xmlrpc_XML_Parse(parser, XMLBufPtr, (int)parseBufferSize, isFinal)) {
 | ||||||
|  | +        fprintf(stderr,
 | ||||||
|  | +                "error '%" XML_FMT_STR "' at line %" XML_FMT_INT_MOD
 | ||||||
|  | +                "u character %" XML_FMT_INT_MOD "u\n",
 | ||||||
|  | +                xmlrpc_XML_ErrorString(xmlrpc_XML_GetErrorCode(parser)),
 | ||||||
|  | +                xmlrpc_XML_GetCurrentLineNumber(parser),
 | ||||||
|  | +                xmlrpc_XML_GetCurrentColumnNumber(parser));
 | ||||||
|  | +        free(XMLBuf);
 | ||||||
|  | +        xmlrpc_XML_ParserFree(parser);
 | ||||||
|  | +        exit(4);
 | ||||||
|  | +      }
 | ||||||
|  | +      XMLBufPtr += bufferSize;
 | ||||||
|  | +    } while (! isFinal);
 | ||||||
|  | +    tend = clock();
 | ||||||
|  | +    cpuTime += ((double)(tend - tstart)) / CLOCKS_PER_SEC;
 | ||||||
|  | +    //xmlrpc-c lacks XML_ParserReset
 | ||||||
|  | +    //xmlrpc_XML_ParserReset(parser, NULL);
 | ||||||
|  | +    i++;
 | ||||||
|  | +  }
 | ||||||
|  | +
 | ||||||
|  | +  xmlrpc_XML_ParserFree(parser);
 | ||||||
|  | +  free(XMLBuf);
 | ||||||
|  | +
 | ||||||
|  | +  printf("%d loops, with buffer size %d. Average time per loop: %f\n",
 | ||||||
|  | +         nrOfLoops, bufferSize, cpuTime / (double)nrOfLoops);
 | ||||||
|  | +  return 0;
 | ||||||
|  | +}
 | ||||||
|  | -- 
 | ||||||
|  | 2.43.5 | ||||||
|  | 
 | ||||||
| @ -6,7 +6,7 @@ | |||||||
| 
 | 
 | ||||||
| Name:           xmlrpc-c | Name:           xmlrpc-c | ||||||
| Version:        1.51.0 | Version:        1.51.0 | ||||||
| Release:        10%{?dist} | Release:        11%{?dist} | ||||||
| Summary:        Lightweight RPC library based on XML and HTTP | Summary:        Lightweight RPC library based on XML and HTTP | ||||||
| # See doc/COPYING for details. | # See doc/COPYING for details. | ||||||
| # The Python 1.5.2 license used by a few files is just BSD. | # The Python 1.5.2 license used by a few files is just BSD. | ||||||
| @ -30,6 +30,8 @@ Patch105:       0005-lib-Prevent-more-integer-overflows-CVE-2022-22822-to.patch | |||||||
| Patch106:       0006-Prevent-integer-overflow-on-m_groupSize-in-doProlog-.patch | Patch106:       0006-Prevent-integer-overflow-on-m_groupSize-in-doProlog-.patch | ||||||
| Patch107:       0007-Address-segfault-found-in-CVE-2023-52425.patch | Patch107:       0007-Address-segfault-found-in-CVE-2023-52425.patch | ||||||
| Patch108:       0008-Prevent-integer-overflow-or-wraparound-CVE-2024-4549.patch | Patch108:       0008-Prevent-integer-overflow-or-wraparound-CVE-2024-4549.patch | ||||||
|  | Patch109:       0009-Restrict-XML-Entity-Expansion-Depth-in-libexpat-CVE-.patch | ||||||
|  | Patch110:       0010-Add-missing-files-for-the-benchmark-tests.patch | ||||||
| 
 | 
 | ||||||
| # Backported patches | # Backported patches | ||||||
| # https://sourceforge.net/p/xmlrpc-c/code/2981/ | # https://sourceforge.net/p/xmlrpc-c/code/2981/ | ||||||
| @ -198,6 +200,9 @@ tar xf %{SOURCE1} | |||||||
| %{_bindir}/xmlrpc_dumpserver | %{_bindir}/xmlrpc_dumpserver | ||||||
| 
 | 
 | ||||||
| %changelog | %changelog | ||||||
|  | * Wed Mar 19 2025 Rob Crittenden <rcritten@redhat.com> - 1.51.0-11 | ||||||
|  | - Restrict XML Entity Expansion Depth in libexpat CVE-2024-8176 | ||||||
|  | 
 | ||||||
| * Thu Sep 19 2024 Rob Crittenden <rcritten@redhat.com> - 1.51.0-10 | * Thu Sep 19 2024 Rob Crittenden <rcritten@redhat.com> - 1.51.0-10 | ||||||
| - Prevent integer overflow or wraparound, CVE-2024-4549 (RHEL-57519) | - Prevent integer overflow or wraparound, CVE-2024-4549 (RHEL-57519) | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user