1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-03-30 02:50:07 +03:00

memory: Implement xmlGrowCapacity to safely grow arrays

xmlGrowCapacity makes sure that dynamic arrays don't grow beyond an
explicit maximum size. size_t considerations are also taken into account.
A macro XML_MAX_ITEMS is provided as default maximum with value
1 billion.

When fuzzing, the initial size is set to 1 to cause more reallocations.
This can require adjustments if callers really need larger arrays.
This commit is contained in:
Nick Wellnhofer 2024-12-15 23:35:28 +01:00
parent afbc0a0405
commit 5320a4aa38
3 changed files with 57 additions and 1 deletions

@ -18,7 +18,7 @@ gcc:c89:
extends: .test
variables:
CONFIG: "--without-python"
CFLAGS: "-O2 -std=c89 -D_XOPEN_SOURCE=600"
CFLAGS: "-O2 -std=c89 -D_XOPEN_SOURCE=600 -Wno-error=unused-function"
gcc:minimum:
extends: .test

@ -1,9 +1,53 @@
#ifndef XML_MEMORY_H_PRIVATE__
#define XML_MEMORY_H_PRIVATE__
#include "../../libxml.h"
#include <limits.h>
#include <stddef.h>
#ifndef SIZE_MAX
#define SIZE_MAX ((size_t) -1)
#endif
#define XML_MAX_ITEMS 1000000000 /* 1 billion */
XML_HIDDEN void
xmlInitMemoryInternal(void);
XML_HIDDEN void
xmlCleanupMemoryInternal(void);
/**
* xmlGrowCapacity:
* @array: pointer to array
* @capacity: pointer to capacity (in/out)
* @elemSize: size of an element in bytes
* @min: elements in initial allocation
* @max: maximum elements in the array
*
* Grow an array by at least one element, checking for overflow.
*
* Returns the new array size on success, -1 on failure.
*/
static XML_INLINE int
xmlGrowCapacity(int capacity, size_t elemSize, int min, int max) {
if (capacity <= 0) {
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
(void) min;
return(1);
#else
return(min);
#endif
}
if ((capacity >= max) ||
((size_t) capacity > SIZE_MAX / 2 / elemSize))
return(-1);
if (capacity > max / 2)
return(max);
return(capacity * 2);
}
#endif /* XML_MEMORY_H_PRIVATE__ */

@ -29,6 +29,18 @@
#include "config.h"
#include <libxml/xmlversion.h>
#if __STDC_VERSION__ >= 199901L
#define XML_INLINE inline
#elif defined(_MSC_VER)
#if _MSC_VER >= 1900
#define XML_INLINE inline
#else
#define XML_INLINE _inline
#endif
#else
#define XML_INLINE
#endif
#if !defined(_WIN32) && \
!defined(__CYGWIN__) && \
(defined(__clang__) || \