1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2024-10-26 12:25:09 +03:00

xpath: Report malloc failures

Fix many places where malloc failures aren't reported.

Rework XPath object cache to store free objects in a linked list to
avoid allocating an additional array. Remove some unneeded object pools.
This commit is contained in:
Nick Wellnhofer 2023-12-10 16:56:16 +01:00
parent f3455ecd52
commit e632d9f02e
4 changed files with 808 additions and 953 deletions

View File

@ -29,7 +29,7 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
xmlFuzzDataInit(data, size); xmlFuzzDataInit(data, size);
maxAlloc = xmlFuzzReadInt(4) % (size + 1); maxAlloc = xmlFuzzReadInt(4) % (size + 100);
expr = xmlFuzzReadString(&exprSize); expr = xmlFuzzReadString(&exprSize);
xml = xmlFuzzReadString(&xmlSize); xml = xmlFuzzReadString(&xmlSize);
@ -42,10 +42,19 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
xpctxt = xmlXPathNewContext(doc); xpctxt = xmlXPathNewContext(doc);
if (xpctxt != NULL) { if (xpctxt != NULL) {
int res;
/* Operation limit to avoid timeout */ /* Operation limit to avoid timeout */
xpctxt->opLimit = 500000; xpctxt->opLimit = 500000;
res = xmlXPathContextSetCache(xpctxt, 1, 4, 0);
xmlFuzzCheckMallocFailure("xmlXPathContextSetCache", res == -1);
xmlFuzzResetMallocFailed();
xmlXPathFreeObject(xmlXPtrEval(BAD_CAST expr, xpctxt)); xmlXPathFreeObject(xmlXPtrEval(BAD_CAST expr, xpctxt));
xmlFuzzCheckMallocFailure("xmlXPtrEval",
xpctxt->lastError.code ==
XML_ERR_NO_MEMORY);
xmlXPathFreeContext(xpctxt); xmlXPathFreeContext(xpctxt);
} }

View File

@ -1,7 +1,16 @@
#ifndef XML_XPATH_H_PRIVATE__ #ifndef XML_XPATH_H_PRIVATE__
#define XML_XPATH_H_PRIVATE__ #define XML_XPATH_H_PRIVATE__
#include <libxml/xpath.h>
XML_HIDDEN void XML_HIDDEN void
xmlInitXPathInternal(void); xmlInitXPathInternal(void);
#ifdef LIBXML_XPATH_ENABLED
XML_HIDDEN void
xmlXPathErrMemory(xmlXPathContextPtr ctxt, const char *extra);
XML_HIDDEN void
xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt, const char *extra);
#endif
#endif /* XML_XPATH_H_PRIVATE__ */ #endif /* XML_XPATH_H_PRIVATE__ */

1681
xpath.c

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,7 @@
#define XPTR_XMLNS_SCHEME #define XPTR_XMLNS_SCHEME
#include "private/error.h" #include "private/error.h"
#include "private/xpath.h"
#define TODO \ #define TODO \
xmlGenericError(xmlGenericErrorContext, \ xmlGenericError(xmlGenericErrorContext, \
@ -62,32 +63,19 @@
* * * *
************************************************************************/ ************************************************************************/
/**
* xmlXPtrErrMemory:
* @extra: extra information
*
* Handle a redefinition of attribute error
*/
static void
xmlXPtrErrMemory(const char *extra)
{
__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_XPOINTER,
XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, extra,
NULL, NULL, 0, 0,
"Memory allocation failed : %s\n", extra);
}
/** /**
* xmlXPtrErr: * xmlXPtrErr:
* @ctxt: an XPTR evaluation context * @ctxt: an XPTR evaluation context
* @extra: extra information * @extra: extra information
* *
* Handle a redefinition of attribute error * Handle an XPointer error
*/ */
static void LIBXML_ATTR_FORMAT(3,0) static void LIBXML_ATTR_FORMAT(3,0)
xmlXPtrErr(xmlXPathParserContextPtr ctxt, int error, xmlXPtrErr(xmlXPathParserContextPtr ctxt, int error,
const char * msg, const xmlChar *extra) const char * msg, const xmlChar *extra)
{ {
if (ctxt->context->lastError.code == XML_ERR_NO_MEMORY)
return;
if (ctxt != NULL) if (ctxt != NULL)
ctxt->error = error; ctxt->error = error;
if ((ctxt == NULL) || (ctxt->context == NULL)) { if ((ctxt == NULL) || (ctxt->context == NULL)) {
@ -106,18 +94,26 @@ xmlXPtrErr(xmlXPathParserContextPtr ctxt, int error,
ctxt->context->lastError.code = error; ctxt->context->lastError.code = error;
ctxt->context->lastError.level = XML_ERR_ERROR; ctxt->context->lastError.level = XML_ERR_ERROR;
ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base); ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base);
if (ctxt->context->lastError.str1 == NULL) {
xmlXPathPErrMemory(ctxt, NULL);
return;
}
ctxt->context->lastError.int1 = ctxt->cur - ctxt->base; ctxt->context->lastError.int1 = ctxt->cur - ctxt->base;
ctxt->context->lastError.node = ctxt->context->debugNode; ctxt->context->lastError.node = ctxt->context->debugNode;
if (ctxt->context->error != NULL) { if (ctxt->context->error != NULL) {
ctxt->context->error(ctxt->context->userData, ctxt->context->error(ctxt->context->userData,
&ctxt->context->lastError); &ctxt->context->lastError);
} else { } else {
__xmlRaiseError(NULL, NULL, NULL, int res;
res = __xmlRaiseError(NULL, NULL, NULL,
NULL, ctxt->context->debugNode, XML_FROM_XPOINTER, NULL, ctxt->context->debugNode, XML_FROM_XPOINTER,
error, XML_ERR_ERROR, NULL, 0, error, XML_ERR_ERROR, NULL, 0,
(const char *) extra, (const char *) ctxt->base, NULL, (const char *) extra, (const char *) ctxt->base, NULL,
ctxt->cur - ctxt->base, 0, ctxt->cur - ctxt->base, 0,
msg, extra); msg, extra);
if (res < 0)
xmlXPathPErrMemory(ctxt, NULL);
} }
} }
@ -208,6 +204,21 @@ xmlXPtrGetNthChild(xmlNodePtr cur, int no) {
* * * *
************************************************************************/ ************************************************************************/
/**
* xmlXPtrErrMemory:
* @extra: extra information
*
* Handle a redefinition of attribute error
*/
static void
xmlXPtrErrMemory(const char *extra)
{
__xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_XPOINTER,
XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, extra,
NULL, NULL, 0, 0,
"Memory allocation failed : %s\n", extra);
}
/** /**
* xmlXPtrCmpPoints: * xmlXPtrCmpPoints:
* @node1: the first node * @node1: the first node
@ -959,7 +970,7 @@ xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) {
len++; len++;
buffer = (xmlChar *) xmlMallocAtomic(len); buffer = (xmlChar *) xmlMallocAtomic(len);
if (buffer == NULL) { if (buffer == NULL) {
xmlXPtrErrMemory("allocating buffer"); xmlXPathPErrMemory(ctxt, "allocating buffer");
xmlFree(name); xmlFree(name);
return; return;
} }
@ -1230,7 +1241,7 @@ xmlXPtrEvalXPointer(xmlXPathParserContextPtr ctxt) {
ctxt->valueTab = (xmlXPathObjectPtr *) ctxt->valueTab = (xmlXPathObjectPtr *)
xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
if (ctxt->valueTab == NULL) { if (ctxt->valueTab == NULL) {
xmlXPtrErrMemory("allocating evaluation context"); xmlXPathPErrMemory(ctxt, "allocating evaluation context");
return; return;
} }
ctxt->valueNr = 0; ctxt->valueNr = 0;
@ -1351,10 +1362,16 @@ xmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) {
if ((ctx == NULL) || (str == NULL)) if ((ctx == NULL) || (str == NULL))
return(NULL); return(NULL);
xmlResetError(&ctx->lastError);
ctxt = xmlXPathNewParserContext(str, ctx); ctxt = xmlXPathNewParserContext(str, ctx);
if (ctxt == NULL) if (ctxt == NULL) {
xmlXPathErrMemory(ctx, NULL);
return(NULL); return(NULL);
}
xmlXPtrEvalXPointer(ctxt); xmlXPtrEvalXPointer(ctxt);
if (ctx->lastError.code != XML_ERR_OK)
goto error;
if ((ctxt->value != NULL) && if ((ctxt->value != NULL) &&
#ifdef LIBXML_XPTR_LOCS_ENABLED #ifdef LIBXML_XPTR_LOCS_ENABLED
@ -1392,11 +1409,12 @@ xmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) {
"xmlXPtrEval: object(s) left on the eval stack\n", "xmlXPtrEval: object(s) left on the eval stack\n",
NULL); NULL);
} }
if (ctxt->error != XPATH_EXPRESSION_OK) { if (ctx->lastError.code != XML_ERR_OK) {
xmlXPathFreeObject(res); xmlXPathFreeObject(res);
res = NULL; res = NULL;
} }
error:
xmlXPathFreeParserContext(ctxt); xmlXPathFreeParserContext(ctxt);
return(res); return(res);
} }