mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
expat 2025-09-24 (4575e52f)
Code extracted from:
https://github.com/libexpat/libexpat.git
at commit 4575e52f83e0d6d7bd24939eab8952bbc7bc358f (R_2_7_3).
This commit is contained in:
committed by
Brad King
parent
865006f033
commit
60f52ff4c5
@@ -1,5 +1,5 @@
|
||||
Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper
|
||||
Copyright (c) 2001-2022 Expat maintainers
|
||||
Copyright (c) 2001-2025 Expat maintainers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
+14
-6
@@ -46,18 +46,26 @@ else(WORDS_BIGENDIAN)
|
||||
endif(WORDS_BIGENDIAN)
|
||||
|
||||
if(HAVE_SYS_TYPES_H)
|
||||
check_symbol_exists("off_t" "sys/types.h" off_t)
|
||||
check_symbol_exists("size_t" "sys/types.h" size_t)
|
||||
else(HAVE_SYS_TYPES_H)
|
||||
check_c_source_compiles("
|
||||
#include <sys/types.h>
|
||||
int main(void) {
|
||||
const off_t offset = -123;
|
||||
(void)offset;
|
||||
return 0;
|
||||
}"
|
||||
HAVE_OFF_T)
|
||||
endif()
|
||||
|
||||
if(NOT HAVE_OFF_T)
|
||||
set(off_t "long")
|
||||
set(size_t "unsigned")
|
||||
endif(HAVE_SYS_TYPES_H)
|
||||
endif()
|
||||
|
||||
check_c_source_compiles("
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h> /* for NULL */
|
||||
#include <unistd.h> /* for syscall */
|
||||
#include <sys/syscall.h> /* for SYS_getrandom */
|
||||
int main() {
|
||||
int main(void) {
|
||||
syscall(SYS_getrandom, NULL, 0, 0);
|
||||
return 0;
|
||||
}"
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
[](https://github.com/libexpat/libexpat/actions/workflows/linux.yml)
|
||||
[](https://ci.appveyor.com/project/libexpat/libexpat)
|
||||
[](https://repology.org/metapackage/expat/versions)
|
||||
[](https://sourceforge.net/projects/expat/files/)
|
||||
[](https://github.com/libexpat/libexpat/releases)
|
||||
[](https://www.bestpractices.dev/projects/10205)
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Expat is **understaffed** and without funding.
|
||||
> There is a [call for help with details](https://github.com/libexpat/libexpat/blob/master/expat/Changes)
|
||||
> at the top of the `Changes` file.
|
||||
|
||||
|
||||
# Expat, Release 2.6.2
|
||||
# Expat, Release 2.7.3
|
||||
|
||||
This is Expat, a C99 library for parsing
|
||||
[XML 1.0 Fourth Edition](https://www.w3.org/TR/2006/REC-xml-20060816/), started by
|
||||
@@ -16,11 +22,12 @@ are called when the parser discovers the associated structures in the
|
||||
document being parsed. A start tag is an example of the kind of
|
||||
structures for which you may register handlers.
|
||||
|
||||
Expat supports the following compilers:
|
||||
Expat supports the following C99 compilers:
|
||||
|
||||
- GNU GCC >=4.5
|
||||
- GNU GCC >=4.5 (for use from C) or GNU GCC >=4.8.1 (for use from C++)
|
||||
- LLVM Clang >=3.5
|
||||
- Microsoft Visual Studio >=15.0/2017 (rolling `${today} minus 5 years`)
|
||||
- Microsoft Visual Studio >=17.0/2022
|
||||
(the oldest version supported by the [official GitHub Actions Windows images](https://github.com/actions/runner-images))
|
||||
|
||||
Windows users can use the
|
||||
[`expat-win32bin-*.*.*.{exe,zip}` download](https://github.com/libexpat/libexpat/releases),
|
||||
@@ -37,16 +44,16 @@ This license is the same as the MIT/X Consortium license.
|
||||
|
||||
## Using libexpat in your CMake-Based Project
|
||||
|
||||
There are two ways of using libexpat with CMake:
|
||||
There are three documented ways of using libexpat with CMake:
|
||||
|
||||
### a) Module Mode
|
||||
### a) `find_package` with Module Mode
|
||||
|
||||
This approach leverages CMake's own [module `FindEXPAT`](https://cmake.org/cmake/help/latest/module/FindEXPAT.html).
|
||||
|
||||
Notice the *uppercase* `EXPAT` in the following example:
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.0) # or 3.10, see below
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(hello VERSION 1.0.0)
|
||||
|
||||
@@ -56,15 +63,10 @@ add_executable(hello
|
||||
hello.c
|
||||
)
|
||||
|
||||
# a) for CMake >=3.10 (see CMake's FindEXPAT docs)
|
||||
target_link_libraries(hello PUBLIC EXPAT::EXPAT)
|
||||
|
||||
# b) for CMake >=3.0
|
||||
target_include_directories(hello PRIVATE ${EXPAT_INCLUDE_DIRS})
|
||||
target_link_libraries(hello PUBLIC ${EXPAT_LIBRARIES})
|
||||
```
|
||||
|
||||
### b) Config Mode
|
||||
### b) `find_package` with Config Mode
|
||||
|
||||
This approach requires files from…
|
||||
|
||||
@@ -79,7 +81,7 @@ or
|
||||
Notice the *lowercase* `expat` in the following example:
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(hello VERSION 1.0.0)
|
||||
|
||||
@@ -92,6 +94,45 @@ add_executable(hello
|
||||
target_link_libraries(hello PUBLIC expat::expat)
|
||||
```
|
||||
|
||||
### c) The `FetchContent` module
|
||||
|
||||
This approach — as demonstrated below — requires CMake >=3.18 for both the
|
||||
[`FetchContent` module](https://cmake.org/cmake/help/latest/module/FetchContent.html)
|
||||
and its support for the `SOURCE_SUBDIR` option to be available.
|
||||
|
||||
Please note that:
|
||||
- Use of the `FetchContent` module with *non-release* SHA1s or `master`
|
||||
of libexpat is neither advised nor considered officially supported.
|
||||
- Pinning to a specific commit is great for robust CI.
|
||||
- Pinning to a specific commit needs updating every time there is a new
|
||||
release of libexpat — either manually or through automation —,
|
||||
to not miss out on libexpat security updates.
|
||||
|
||||
For an example that pulls in libexpat via Git:
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
project(hello VERSION 1.0.0)
|
||||
|
||||
FetchContent_Declare(
|
||||
expat
|
||||
GIT_REPOSITORY https://github.com/libexpat/libexpat/
|
||||
GIT_TAG 000000000_GIT_COMMIT_SHA1_HERE_000000000 # i.e. Git tag R_X_Y_Z
|
||||
SOURCE_SUBDIR expat/
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(expat)
|
||||
|
||||
add_executable(hello
|
||||
hello.c
|
||||
)
|
||||
|
||||
target_link_libraries(hello PUBLIC expat)
|
||||
```
|
||||
|
||||
|
||||
## Building from a Git Clone
|
||||
|
||||
@@ -158,10 +199,10 @@ support this mode of compilation (yet):
|
||||
|
||||
1. Mass-patch `Makefile.am` files to use `libexpatw.la` for a library name:
|
||||
<br/>
|
||||
`find -name Makefile.am -exec sed
|
||||
`find . -name Makefile.am -exec sed
|
||||
-e 's,libexpat\.la,libexpatw.la,'
|
||||
-e 's,libexpat_la,libexpatw_la,'
|
||||
-i {} +`
|
||||
-i.bak {} +`
|
||||
|
||||
1. Run `automake` to re-write `Makefile.in` files:<br/>
|
||||
`automake`
|
||||
@@ -250,7 +291,7 @@ EXPAT_ENABLE_INSTALL:BOOL=ON
|
||||
// Use /MT flag (static CRT) when compiling in MSVC
|
||||
EXPAT_MSVC_STATIC_CRT:BOOL=OFF
|
||||
|
||||
// Build fuzzers via ossfuzz for the expat library
|
||||
// Build fuzzers via OSS-Fuzz for the expat library
|
||||
EXPAT_OSSFUZZ_BUILD:BOOL=OFF
|
||||
|
||||
// Build a shared expat library
|
||||
|
||||
+12
-15
@@ -1,7 +1,7 @@
|
||||
/* expat_config.h.cmake. Based upon generated expat_config.h.in. */
|
||||
|
||||
#ifndef EXPAT_CONFIG_H
|
||||
#define EXPAT_CONFIG_H 1
|
||||
# define EXPAT_CONFIG_H 1
|
||||
|
||||
/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */
|
||||
#cmakedefine BYTEORDER @BYTEORDER@
|
||||
@@ -61,7 +61,7 @@
|
||||
#cmakedefine HAVE_UNISTD_H
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "@PACKAGE_NAME@"
|
||||
# define PACKAGE "@PACKAGE_NAME@"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#cmakedefine PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
|
||||
@@ -76,15 +76,15 @@
|
||||
#cmakedefine PACKAGE_TARNAME "@PACKAGE_TARNAME@"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
# define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#ifndef STDC_HEADERS
|
||||
# ifndef STDC_HEADERS
|
||||
#cmakedefine STDC_HEADERS
|
||||
#endif
|
||||
# endif
|
||||
|
||||
/* whether byteorder is bigendian */
|
||||
#cmakedefine WORDS_BIGENDIAN
|
||||
@@ -95,31 +95,28 @@
|
||||
|
||||
/* Define to specify how much context to retain around the current parse
|
||||
point, 0 to disable. */
|
||||
#define XML_CONTEXT_BYTES @XML_CONTEXT_BYTES@
|
||||
# define XML_CONTEXT_BYTES @XML_CONTEXT_BYTES@
|
||||
|
||||
#if ! defined(_WIN32)
|
||||
# if ! defined(_WIN32)
|
||||
/* Define to include code reading entropy from `/dev/urandom'. */
|
||||
#cmakedefine XML_DEV_URANDOM
|
||||
#endif
|
||||
# endif
|
||||
|
||||
/* Define to make parameter entity parsing functionality available. */
|
||||
#cmakedefine XML_DTD
|
||||
|
||||
/* Define as 1/0 to enable/disable support for general entities. */
|
||||
#define XML_GE @XML_GE@
|
||||
# define XML_GE @XML_GE@
|
||||
|
||||
/* Define to make XML Namespaces functionality available. */
|
||||
#cmakedefine XML_NS
|
||||
|
||||
/* Define to __FUNCTION__ or "" if `__func__' does not conform to ANSI C. */
|
||||
#ifdef _MSC_VER
|
||||
# define __func__ __FUNCTION__
|
||||
#endif
|
||||
# ifdef _MSC_VER
|
||||
# define __func__ __FUNCTION__
|
||||
# endif
|
||||
|
||||
/* Define to `long' if <sys/types.h> does not define. */
|
||||
#cmakedefine off_t @off_t@
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||
#cmakedefine size_t @size_t@
|
||||
|
||||
#endif // ndef EXPAT_CONFIG_H
|
||||
|
||||
+43
-27
@@ -11,7 +11,7 @@
|
||||
Copyright (c) 2000-2005 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
|
||||
Copyright (c) 2001-2002 Greg Stein <gstein@users.sourceforge.net>
|
||||
Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016 Cristian Rodríguez <crrodriguez@opensuse.org>
|
||||
Copyright (c) 2016 Thomas Beutlich <tc@tbeu.de>
|
||||
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
|
||||
@@ -19,6 +19,7 @@
|
||||
Copyright (c) 2023 Hanno Böck <hanno@gentoo.org>
|
||||
Copyright (c) 2023 Sony Corporation / Snild Dolkow <snild@sony.com>
|
||||
Copyright (c) 2024 Taichi Haradaguchi <20001722@ymail.ne.jp>
|
||||
Copyright (c) 2025 Matthew Fernandez <matthew.fernandez@gmail.com>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -42,21 +43,21 @@
|
||||
*/
|
||||
|
||||
#ifndef Expat_INCLUDED
|
||||
#define Expat_INCLUDED 1
|
||||
# define Expat_INCLUDED 1
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "expat_external.h"
|
||||
# include <stdlib.h>
|
||||
# include "expat_external.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
# endif
|
||||
|
||||
struct XML_ParserStruct;
|
||||
typedef struct XML_ParserStruct *XML_Parser;
|
||||
|
||||
typedef unsigned char XML_Bool;
|
||||
#define XML_TRUE ((XML_Bool)1)
|
||||
#define XML_FALSE ((XML_Bool)0)
|
||||
# define XML_TRUE ((XML_Bool)1)
|
||||
# define XML_FALSE ((XML_Bool)0)
|
||||
|
||||
/* The XML_Status enum gives the possible return values for several
|
||||
API functions. The preprocessor #defines are included so this
|
||||
@@ -73,11 +74,11 @@ typedef unsigned char XML_Bool;
|
||||
*/
|
||||
enum XML_Status {
|
||||
XML_STATUS_ERROR = 0,
|
||||
#define XML_STATUS_ERROR XML_STATUS_ERROR
|
||||
# define XML_STATUS_ERROR XML_STATUS_ERROR
|
||||
XML_STATUS_OK = 1,
|
||||
#define XML_STATUS_OK XML_STATUS_OK
|
||||
# define XML_STATUS_OK XML_STATUS_OK
|
||||
XML_STATUS_SUSPENDED = 2
|
||||
#define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED
|
||||
# define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED
|
||||
};
|
||||
|
||||
enum XML_Error {
|
||||
@@ -130,7 +131,9 @@ enum XML_Error {
|
||||
/* Added in 2.3.0. */
|
||||
XML_ERROR_NO_BUFFER,
|
||||
/* Added in 2.4.0. */
|
||||
XML_ERROR_AMPLIFICATION_LIMIT_BREACH
|
||||
XML_ERROR_AMPLIFICATION_LIMIT_BREACH,
|
||||
/* Added in 2.6.4. */
|
||||
XML_ERROR_NOT_STARTED,
|
||||
};
|
||||
|
||||
enum XML_Content_Type {
|
||||
@@ -274,7 +277,7 @@ XML_ParserCreate_MM(const XML_Char *encoding,
|
||||
|
||||
/* Prepare a parser object to be reused. This is particularly
|
||||
valuable when memory allocation overhead is disproportionately high,
|
||||
such as when a large number of small documnents need to be parsed.
|
||||
such as when a large number of small documents need to be parsed.
|
||||
All handlers are cleared from the parser, except for the
|
||||
unknownEncodingHandler. The parser's external state is re-initialized
|
||||
except for the values of ns and ns_triplets.
|
||||
@@ -678,7 +681,7 @@ XMLPARSEAPI(void)
|
||||
XML_SetUserData(XML_Parser parser, void *userData);
|
||||
|
||||
/* Returns the last value set by XML_SetUserData or NULL. */
|
||||
#define XML_GetUserData(parser) (*(void **)(parser))
|
||||
# define XML_GetUserData(parser) (*(void **)(parser))
|
||||
|
||||
/* This is equivalent to supplying an encoding argument to
|
||||
XML_ParserCreate. On success XML_SetEncoding returns non-zero,
|
||||
@@ -750,7 +753,7 @@ XML_GetSpecifiedAttributeCount(XML_Parser parser);
|
||||
XMLPARSEAPI(int)
|
||||
XML_GetIdAttributeIndex(XML_Parser parser);
|
||||
|
||||
#ifdef XML_ATTR_INFO
|
||||
# ifdef XML_ATTR_INFO
|
||||
/* Source file byte offsets for the start and end of attribute names and values.
|
||||
The value indices are exclusive of surrounding quotes; thus in a UTF-8 source
|
||||
file an attribute value of "blah" will yield:
|
||||
@@ -771,7 +774,7 @@ typedef struct {
|
||||
*/
|
||||
XMLPARSEAPI(const XML_AttrInfo *)
|
||||
XML_GetAttributeInfo(XML_Parser parser);
|
||||
#endif
|
||||
# endif
|
||||
|
||||
/* Parses some input. Returns XML_STATUS_ERROR if a fatal error is
|
||||
detected. The last call to XML_Parse must have isFinal true; len
|
||||
@@ -968,9 +971,9 @@ XMLPARSEAPI(const char *)
|
||||
XML_GetInputContext(XML_Parser parser, int *offset, int *size);
|
||||
|
||||
/* For backwards compatibility with previous versions. */
|
||||
#define XML_GetErrorLineNumber XML_GetCurrentLineNumber
|
||||
#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber
|
||||
#define XML_GetErrorByteIndex XML_GetCurrentByteIndex
|
||||
# define XML_GetErrorLineNumber XML_GetCurrentLineNumber
|
||||
# define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber
|
||||
# define XML_GetErrorByteIndex XML_GetCurrentByteIndex
|
||||
|
||||
/* Frees the content model passed to the element declaration handler */
|
||||
XMLPARSEAPI(void)
|
||||
@@ -1030,7 +1033,10 @@ enum XML_FeatureEnum {
|
||||
XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT,
|
||||
XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT,
|
||||
/* Added in Expat 2.6.0. */
|
||||
XML_FEATURE_GE
|
||||
XML_FEATURE_GE,
|
||||
/* Added in Expat 2.7.2. */
|
||||
XML_FEATURE_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT,
|
||||
XML_FEATURE_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT,
|
||||
/* Additional features must be added to the end of this enum. */
|
||||
};
|
||||
|
||||
@@ -1043,7 +1049,7 @@ typedef struct {
|
||||
XMLPARSEAPI(const XML_Feature *)
|
||||
XML_GetFeatureList(void);
|
||||
|
||||
#if defined(XML_DTD) || (defined(XML_GE) && XML_GE == 1)
|
||||
# if defined(XML_DTD) || (defined(XML_GE) && XML_GE == 1)
|
||||
/* Added in Expat 2.4.0 for XML_DTD defined and
|
||||
* added in Expat 2.6.0 for XML_GE == 1. */
|
||||
XMLPARSEAPI(XML_Bool)
|
||||
@@ -1055,7 +1061,17 @@ XML_SetBillionLaughsAttackProtectionMaximumAmplification(
|
||||
XMLPARSEAPI(XML_Bool)
|
||||
XML_SetBillionLaughsAttackProtectionActivationThreshold(
|
||||
XML_Parser parser, unsigned long long activationThresholdBytes);
|
||||
#endif
|
||||
|
||||
/* Added in Expat 2.7.2. */
|
||||
XMLPARSEAPI(XML_Bool)
|
||||
XML_SetAllocTrackerMaximumAmplification(XML_Parser parser,
|
||||
float maximumAmplificationFactor);
|
||||
|
||||
/* Added in Expat 2.7.2. */
|
||||
XMLPARSEAPI(XML_Bool)
|
||||
XML_SetAllocTrackerActivationThreshold(
|
||||
XML_Parser parser, unsigned long long activationThresholdBytes);
|
||||
# endif
|
||||
|
||||
/* Added in Expat 2.6.0. */
|
||||
XMLPARSEAPI(XML_Bool)
|
||||
@@ -1064,12 +1080,12 @@ XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled);
|
||||
/* Expat follows the semantic versioning convention.
|
||||
See https://semver.org
|
||||
*/
|
||||
#define XML_MAJOR_VERSION 2
|
||||
#define XML_MINOR_VERSION 6
|
||||
#define XML_MICRO_VERSION 2
|
||||
# define XML_MAJOR_VERSION 2
|
||||
# define XML_MINOR_VERSION 7
|
||||
# define XML_MICRO_VERSION 3
|
||||
|
||||
#ifdef __cplusplus
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
|
||||
#endif /* not Expat_INCLUDED */
|
||||
|
||||
+59
-58
@@ -38,7 +38,7 @@
|
||||
*/
|
||||
|
||||
#ifndef Expat_External_INCLUDED
|
||||
#define Expat_External_INCLUDED 1
|
||||
# define Expat_External_INCLUDED 1
|
||||
|
||||
/* External API definitions */
|
||||
|
||||
@@ -64,12 +64,12 @@
|
||||
compiled with the cdecl calling convention as the default since
|
||||
system headers may assume the cdecl convention.
|
||||
*/
|
||||
#ifndef XMLCALL
|
||||
# if defined(_MSC_VER)
|
||||
# define XMLCALL __cdecl
|
||||
# elif defined(__GNUC__) && defined(__i386) && ! defined(__INTEL_COMPILER)
|
||||
# define XMLCALL __attribute__((cdecl))
|
||||
# else
|
||||
# ifndef XMLCALL
|
||||
# if defined(_MSC_VER)
|
||||
# define XMLCALL __cdecl
|
||||
# elif defined(__GNUC__) && defined(__i386) && ! defined(__INTEL_COMPILER)
|
||||
# define XMLCALL __attribute__((cdecl))
|
||||
# else
|
||||
/* For any platform which uses this definition and supports more than
|
||||
one calling convention, we need to extend this definition to
|
||||
declare the convention used on that platform, if it's possible to
|
||||
@@ -80,86 +80,87 @@
|
||||
pre-processor and how to specify the same calling convention as the
|
||||
platform's malloc() implementation.
|
||||
*/
|
||||
# define XMLCALL
|
||||
# endif
|
||||
#endif /* not defined XMLCALL */
|
||||
# define XMLCALL
|
||||
# endif
|
||||
# endif /* not defined XMLCALL */
|
||||
|
||||
#if ! defined(XML_STATIC) && ! defined(XMLIMPORT)
|
||||
# ifndef XML_BUILDING_EXPAT
|
||||
# if ! defined(XML_STATIC) && ! defined(XMLIMPORT)
|
||||
# ifndef XML_BUILDING_EXPAT
|
||||
/* using Expat from an application */
|
||||
|
||||
# if defined(_MSC_EXTENSIONS) && ! defined(__BEOS__) && ! defined(__CYGWIN__)
|
||||
# define XMLIMPORT __declspec(dllimport)
|
||||
# if defined(_MSC_EXTENSIONS) && ! defined(__BEOS__) \
|
||||
&& ! defined(__CYGWIN__)
|
||||
# define XMLIMPORT __declspec(dllimport)
|
||||
# endif
|
||||
|
||||
# endif
|
||||
# endif /* not defined XML_STATIC */
|
||||
|
||||
# ifndef XML_ENABLE_VISIBILITY
|
||||
# define XML_ENABLE_VISIBILITY 0
|
||||
# endif
|
||||
#endif /* not defined XML_STATIC */
|
||||
|
||||
#ifndef XML_ENABLE_VISIBILITY
|
||||
# define XML_ENABLE_VISIBILITY 0
|
||||
#endif
|
||||
|
||||
#if ! defined(XMLIMPORT) && XML_ENABLE_VISIBILITY
|
||||
# define XMLIMPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
# if ! defined(XMLIMPORT) && XML_ENABLE_VISIBILITY
|
||||
# define XMLIMPORT __attribute__((visibility("default")))
|
||||
# endif
|
||||
|
||||
/* If we didn't define it above, define it away: */
|
||||
#ifndef XMLIMPORT
|
||||
# define XMLIMPORT
|
||||
#endif
|
||||
# ifndef XMLIMPORT
|
||||
# define XMLIMPORT
|
||||
# endif
|
||||
|
||||
#if defined(__GNUC__) \
|
||||
&& (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
|
||||
# define XML_ATTR_MALLOC __attribute__((__malloc__))
|
||||
#else
|
||||
# define XML_ATTR_MALLOC
|
||||
#endif
|
||||
# if defined(__GNUC__) \
|
||||
&& (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
|
||||
# define XML_ATTR_MALLOC __attribute__((__malloc__))
|
||||
# else
|
||||
# define XML_ATTR_MALLOC
|
||||
# endif
|
||||
|
||||
#if defined(__GNUC__) \
|
||||
&& ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
|
||||
# define XML_ATTR_ALLOC_SIZE(x) __attribute__((__alloc_size__(x)))
|
||||
#else
|
||||
# define XML_ATTR_ALLOC_SIZE(x)
|
||||
#endif
|
||||
# if defined(__GNUC__) \
|
||||
&& ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
|
||||
# define XML_ATTR_ALLOC_SIZE(x) __attribute__((__alloc_size__(x)))
|
||||
# else
|
||||
# define XML_ATTR_ALLOC_SIZE(x)
|
||||
# endif
|
||||
|
||||
#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL
|
||||
# define XMLPARSEAPI(type) XMLIMPORT type XMLCALL
|
||||
|
||||
#ifdef __cplusplus
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef XML_UNICODE_WCHAR_T
|
||||
# ifndef XML_UNICODE
|
||||
# define XML_UNICODE
|
||||
# endif
|
||||
# if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2)
|
||||
# error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef XML_UNICODE /* Information is UTF-16 encoded. */
|
||||
# ifdef XML_UNICODE_WCHAR_T
|
||||
# ifndef XML_UNICODE
|
||||
# define XML_UNICODE
|
||||
# endif
|
||||
# if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2)
|
||||
# error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc"
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef XML_UNICODE /* Information is UTF-16 encoded. */
|
||||
# ifdef XML_UNICODE_WCHAR_T
|
||||
typedef wchar_t XML_Char;
|
||||
typedef wchar_t XML_LChar;
|
||||
# else
|
||||
# else
|
||||
typedef unsigned short XML_Char;
|
||||
typedef char XML_LChar;
|
||||
# endif /* XML_UNICODE_WCHAR_T */
|
||||
#else /* Information is UTF-8 encoded. */
|
||||
# endif /* XML_UNICODE_WCHAR_T */
|
||||
# else /* Information is UTF-8 encoded. */
|
||||
typedef char XML_Char;
|
||||
typedef char XML_LChar;
|
||||
#endif /* XML_UNICODE */
|
||||
# endif /* XML_UNICODE */
|
||||
|
||||
#ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */
|
||||
# ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */
|
||||
typedef long long XML_Index;
|
||||
typedef unsigned long long XML_Size;
|
||||
#else
|
||||
# else
|
||||
typedef long XML_Index;
|
||||
typedef unsigned long XML_Size;
|
||||
#endif /* XML_LARGE_SIZE */
|
||||
# endif /* XML_LARGE_SIZE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
|
||||
#endif /* not Expat_External_INCLUDED */
|
||||
|
||||
+18
-1
@@ -28,7 +28,7 @@
|
||||
Copyright (c) 2002-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
|
||||
Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
|
||||
Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2018 Yury Gribov <tetra2005@gmail.com>
|
||||
Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
|
||||
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
|
||||
@@ -108,6 +108,7 @@
|
||||
#endif
|
||||
|
||||
#include <limits.h> // ULONG_MAX
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
#if defined(_WIN32) \
|
||||
&& (! defined(__USE_MINGW_ANSI_STDIO) \
|
||||
@@ -127,6 +128,9 @@
|
||||
# elif ULONG_MAX == 18446744073709551615u // 2^64-1
|
||||
# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld"
|
||||
# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "lu"
|
||||
# elif defined(EMSCRIPTEN) // 32bit mode Emscripten
|
||||
# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld"
|
||||
# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "zu"
|
||||
# else
|
||||
# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d"
|
||||
# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u"
|
||||
@@ -145,6 +149,16 @@
|
||||
100.0f
|
||||
#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT \
|
||||
8388608 // 8 MiB, 2^23
|
||||
|
||||
#define EXPAT_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT 100.0f
|
||||
#define EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT \
|
||||
67108864 // 64 MiB, 2^26
|
||||
|
||||
// NOTE: If function expat_alloc was user facing, EXPAT_MALLOC_ALIGNMENT would
|
||||
// have to take sizeof(long double) into account
|
||||
#define EXPAT_MALLOC_ALIGNMENT sizeof(long long) // largest parser (sub)member
|
||||
#define EXPAT_MALLOC_PADDING ((EXPAT_MALLOC_ALIGNMENT) - sizeof(size_t))
|
||||
|
||||
/* NOTE END */
|
||||
|
||||
#include "expat.h" // so we can use type XML_Parser below
|
||||
@@ -168,6 +182,9 @@ extern
|
||||
#endif
|
||||
XML_Bool g_reparseDeferralEnabledDefault; // written ONLY in runtests.c
|
||||
#if defined(XML_TESTING)
|
||||
void *expat_malloc(XML_Parser parser, size_t size, int sourceLine);
|
||||
void expat_free(XML_Parser parser, void *ptr, int sourceLine);
|
||||
void *expat_realloc(XML_Parser parser, void *ptr, size_t size, int sourceLine);
|
||||
extern unsigned int g_bytesScanned; // used for testing only
|
||||
#endif
|
||||
|
||||
|
||||
+1
-2
@@ -126,8 +126,7 @@
|
||||
| ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) \
|
||||
| ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
|
||||
|
||||
#define SIPHASH_INITIALIZER \
|
||||
{ 0, 0, 0, 0, {0}, 0, 0 }
|
||||
#define SIPHASH_INITIALIZER {0, 0, 0, 0, {0}, 0, 0}
|
||||
|
||||
struct siphash {
|
||||
uint64_t v0, v1, v2, v3;
|
||||
|
||||
+989
-313
@@ -1,4 +1,4 @@
|
||||
/* 2a14271ad4d35e82bde8ba210b4edb7998794bcbae54deab114046a300f9639a (2.6.2+)
|
||||
/* 28bcd8b1ba7eb595d82822908257fd9c3589b4243e3c922d0369f35bfcd7b506 (2.7.3+)
|
||||
__ __ _
|
||||
___\ \/ /_ __ __ _| |_
|
||||
/ _ \\ /| '_ \ / _` | __|
|
||||
@@ -13,7 +13,7 @@
|
||||
Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2005-2009 Steven Solie <steven@solie.ca>
|
||||
Copyright (c) 2016 Eric Rahm <erahm@mozilla.com>
|
||||
Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016 Gaurav <g.gupta@samsung.com>
|
||||
Copyright (c) 2016 Thomas Beutlich <tc@tbeu.de>
|
||||
Copyright (c) 2016 Gustavo Grieco <gustavo.grieco@imag.fr>
|
||||
@@ -39,6 +39,9 @@
|
||||
Copyright (c) 2022 Sean McBride <sean@rogue-research.com>
|
||||
Copyright (c) 2023 Owain Davies <owaind@bath.edu>
|
||||
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
|
||||
Copyright (c) 2024-2025 Berkay Eren Ürün <berkay.ueruen@siemens.com>
|
||||
Copyright (c) 2024 Hanno Böck <hanno@gentoo.org>
|
||||
Copyright (c) 2025 Matthew Fernandez <matthew.fernandez@gmail.com>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -95,7 +98,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h> /* memset(), memcpy() */
|
||||
#include <assert.h>
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <limits.h> /* INT_MAX, UINT_MAX */
|
||||
#include <stdio.h> /* fprintf */
|
||||
#include <stdlib.h> /* getenv, rand_s */
|
||||
#include <stdint.h> /* uintptr_t */
|
||||
@@ -232,7 +235,7 @@ typedef struct {
|
||||
unsigned char power;
|
||||
size_t size;
|
||||
size_t used;
|
||||
const XML_Memory_Handling_Suite *mem;
|
||||
XML_Parser parser;
|
||||
} HASH_TABLE;
|
||||
|
||||
static size_t keylen(KEY s);
|
||||
@@ -294,7 +297,7 @@ typedef struct {
|
||||
The name of the element is stored in both the document and API
|
||||
encodings. The memory buffer 'buf' is a separately-allocated
|
||||
memory area which stores the name. During the XML_Parse()/
|
||||
XMLParseBuffer() when the element is open, the memory for the 'raw'
|
||||
XML_ParseBuffer() when the element is open, the memory for the 'raw'
|
||||
version of the name (in the document encoding) is shared with the
|
||||
document buffer. If the element is open across calls to
|
||||
XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
|
||||
@@ -323,6 +326,10 @@ typedef struct {
|
||||
const XML_Char *publicId;
|
||||
const XML_Char *notation;
|
||||
XML_Bool open;
|
||||
XML_Bool hasMore; /* true if entity has not been completely processed */
|
||||
/* An entity can be open while being already completely processed (hasMore ==
|
||||
XML_FALSE). The reason is the delayed closing of entities until their inner
|
||||
entities are processed and closed */
|
||||
XML_Bool is_param;
|
||||
XML_Bool is_internal; /* true if declared in internal subset outside PE */
|
||||
} ENTITY;
|
||||
@@ -351,7 +358,7 @@ typedef struct {
|
||||
const XML_Char *end;
|
||||
XML_Char *ptr;
|
||||
XML_Char *start;
|
||||
const XML_Memory_Handling_Suite *mem;
|
||||
XML_Parser parser;
|
||||
} STRING_POOL;
|
||||
|
||||
/* The XML_Char before the name is used to determine whether
|
||||
@@ -413,6 +420,12 @@ typedef struct {
|
||||
int *scaffIndex;
|
||||
} DTD;
|
||||
|
||||
enum EntityType {
|
||||
ENTITY_INTERNAL,
|
||||
ENTITY_ATTRIBUTE,
|
||||
ENTITY_VALUE,
|
||||
};
|
||||
|
||||
typedef struct open_internal_entity {
|
||||
const char *internalEventPtr;
|
||||
const char *internalEventEndPtr;
|
||||
@@ -420,6 +433,7 @@ typedef struct open_internal_entity {
|
||||
ENTITY *entity;
|
||||
int startTagLevel;
|
||||
XML_Bool betweenDecl; /* WFC: PE Between Declarations */
|
||||
enum EntityType type;
|
||||
} OPEN_INTERNAL_ENTITY;
|
||||
|
||||
enum XML_Account {
|
||||
@@ -439,6 +453,14 @@ typedef struct accounting {
|
||||
unsigned long long activationThresholdBytes;
|
||||
} ACCOUNTING;
|
||||
|
||||
typedef struct MALLOC_TRACKER {
|
||||
XmlBigCount bytesAllocated;
|
||||
XmlBigCount peakBytesAllocated; // updated live only for debug level >=2
|
||||
unsigned long debugLevel;
|
||||
float maximumAmplificationFactor; // >=1.0
|
||||
XmlBigCount activationThresholdBytes;
|
||||
} MALLOC_TRACKER;
|
||||
|
||||
typedef struct entity_stats {
|
||||
unsigned int countEverOpened;
|
||||
unsigned int currentDepth;
|
||||
@@ -479,8 +501,8 @@ static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc,
|
||||
const char *next, const char **nextPtr,
|
||||
XML_Bool haveMore, XML_Bool allowClosingDoctype,
|
||||
enum XML_Account account);
|
||||
static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity,
|
||||
XML_Bool betweenDecl);
|
||||
static enum XML_Error processEntity(XML_Parser parser, ENTITY *entity,
|
||||
XML_Bool betweenDecl, enum EntityType type);
|
||||
static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
|
||||
const ENCODING *enc, const char *start,
|
||||
const char *end, const char **endPtr,
|
||||
@@ -511,18 +533,22 @@ static enum XML_Error storeAttributeValue(XML_Parser parser,
|
||||
const char *ptr, const char *end,
|
||||
STRING_POOL *pool,
|
||||
enum XML_Account account);
|
||||
static enum XML_Error appendAttributeValue(XML_Parser parser,
|
||||
const ENCODING *enc,
|
||||
XML_Bool isCdata, const char *ptr,
|
||||
const char *end, STRING_POOL *pool,
|
||||
enum XML_Account account);
|
||||
static enum XML_Error
|
||||
appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
|
||||
const char *ptr, const char *end, STRING_POOL *pool,
|
||||
enum XML_Account account, const char **nextPtr);
|
||||
static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc,
|
||||
const char *start, const char *end);
|
||||
static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType);
|
||||
#if XML_GE == 1
|
||||
static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
|
||||
const char *start, const char *end,
|
||||
enum XML_Account account);
|
||||
enum XML_Account account,
|
||||
const char **nextPtr);
|
||||
static enum XML_Error callStoreEntityValue(XML_Parser parser,
|
||||
const ENCODING *enc,
|
||||
const char *start, const char *end,
|
||||
enum XML_Account account);
|
||||
#else
|
||||
static enum XML_Error storeSelfEntityValue(XML_Parser parser, ENTITY *entity);
|
||||
#endif
|
||||
@@ -538,27 +564,24 @@ static XML_Bool setContext(XML_Parser parser, const XML_Char *context);
|
||||
|
||||
static void FASTCALL normalizePublicId(XML_Char *s);
|
||||
|
||||
static DTD *dtdCreate(const XML_Memory_Handling_Suite *ms);
|
||||
static DTD *dtdCreate(XML_Parser parser);
|
||||
/* do not call if m_parentParser != NULL */
|
||||
static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
|
||||
static void dtdDestroy(DTD *p, XML_Bool isDocEntity,
|
||||
const XML_Memory_Handling_Suite *ms);
|
||||
static void dtdReset(DTD *p, XML_Parser parser);
|
||||
static void dtdDestroy(DTD *p, XML_Bool isDocEntity, XML_Parser parser);
|
||||
static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
|
||||
const XML_Memory_Handling_Suite *ms);
|
||||
XML_Parser parser);
|
||||
static int copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable,
|
||||
STRING_POOL *newPool, const HASH_TABLE *oldTable);
|
||||
static NAMED *lookup(XML_Parser parser, HASH_TABLE *table, KEY name,
|
||||
size_t createSize);
|
||||
static void FASTCALL hashTableInit(HASH_TABLE *table,
|
||||
const XML_Memory_Handling_Suite *ms);
|
||||
static void FASTCALL hashTableInit(HASH_TABLE *table, XML_Parser parser);
|
||||
static void FASTCALL hashTableClear(HASH_TABLE *table);
|
||||
static void FASTCALL hashTableDestroy(HASH_TABLE *table);
|
||||
static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *iter,
|
||||
const HASH_TABLE *table);
|
||||
static NAMED *FASTCALL hashTableIterNext(HASH_TABLE_ITER *iter);
|
||||
|
||||
static void FASTCALL poolInit(STRING_POOL *pool,
|
||||
const XML_Memory_Handling_Suite *ms);
|
||||
static void FASTCALL poolInit(STRING_POOL *pool, XML_Parser parser);
|
||||
static void FASTCALL poolClear(STRING_POOL *pool);
|
||||
static void FASTCALL poolDestroy(STRING_POOL *pool);
|
||||
static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
|
||||
@@ -578,15 +601,15 @@ static XML_Content *build_model(XML_Parser parser);
|
||||
static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc,
|
||||
const char *ptr, const char *end);
|
||||
|
||||
static XML_Char *copyString(const XML_Char *s,
|
||||
const XML_Memory_Handling_Suite *memsuite);
|
||||
static XML_Char *copyString(const XML_Char *s, XML_Parser parser);
|
||||
|
||||
static unsigned long generate_hash_secret_salt(XML_Parser parser);
|
||||
static XML_Bool startParsing(XML_Parser parser);
|
||||
|
||||
static XML_Parser parserCreate(const XML_Char *encodingName,
|
||||
const XML_Memory_Handling_Suite *memsuite,
|
||||
const XML_Char *nameSep, DTD *dtd);
|
||||
const XML_Char *nameSep, DTD *dtd,
|
||||
XML_Parser parentParser);
|
||||
|
||||
static void parserInit(XML_Parser parser, const XML_Char *encodingName);
|
||||
|
||||
@@ -610,10 +633,10 @@ static void entityTrackingOnOpen(XML_Parser parser, ENTITY *entity,
|
||||
int sourceLine);
|
||||
static void entityTrackingOnClose(XML_Parser parser, ENTITY *entity,
|
||||
int sourceLine);
|
||||
#endif /* XML_GE == 1 */
|
||||
|
||||
static XML_Parser getRootParserOf(XML_Parser parser,
|
||||
unsigned int *outLevelDiff);
|
||||
#endif /* XML_GE == 1 */
|
||||
|
||||
static unsigned long getDebugLevel(const char *variableName,
|
||||
unsigned long defaultDebugLevel);
|
||||
@@ -707,6 +730,10 @@ struct XML_ParserStruct {
|
||||
const char *m_positionPtr;
|
||||
OPEN_INTERNAL_ENTITY *m_openInternalEntities;
|
||||
OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
|
||||
OPEN_INTERNAL_ENTITY *m_openAttributeEntities;
|
||||
OPEN_INTERNAL_ENTITY *m_freeAttributeEntities;
|
||||
OPEN_INTERNAL_ENTITY *m_openValueEntities;
|
||||
OPEN_INTERNAL_ENTITY *m_freeValueEntities;
|
||||
XML_Bool m_defaultExpandInternalEntities;
|
||||
int m_tagLevel;
|
||||
ENTITY *m_declEntity;
|
||||
@@ -752,13 +779,238 @@ struct XML_ParserStruct {
|
||||
unsigned long m_hash_secret_salt;
|
||||
#if XML_GE == 1
|
||||
ACCOUNTING m_accounting;
|
||||
MALLOC_TRACKER m_alloc_tracker;
|
||||
ENTITY_STATS m_entity_stats;
|
||||
#endif
|
||||
XML_Bool m_reenter;
|
||||
};
|
||||
|
||||
#define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
|
||||
#define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p), (s)))
|
||||
#define FREE(parser, p) (parser->m_mem.free_fcn((p)))
|
||||
#if XML_GE == 1
|
||||
# define MALLOC(parser, s) (expat_malloc((parser), (s), __LINE__))
|
||||
# define REALLOC(parser, p, s) (expat_realloc((parser), (p), (s), __LINE__))
|
||||
# define FREE(parser, p) (expat_free((parser), (p), __LINE__))
|
||||
#else
|
||||
# define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
|
||||
# define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p), (s)))
|
||||
# define FREE(parser, p) (parser->m_mem.free_fcn((p)))
|
||||
#endif
|
||||
|
||||
#if XML_GE == 1
|
||||
static void
|
||||
expat_heap_stat(XML_Parser rootParser, char operator, XmlBigCount absDiff,
|
||||
XmlBigCount newTotal, XmlBigCount peakTotal, int sourceLine) {
|
||||
// NOTE: This can be +infinity or -nan
|
||||
const float amplification
|
||||
= (float)newTotal / (float)rootParser->m_accounting.countBytesDirect;
|
||||
fprintf(
|
||||
stderr,
|
||||
"expat: Allocations(%p): Direct " EXPAT_FMT_ULL("10") ", allocated %c" EXPAT_FMT_ULL(
|
||||
"10") " to " EXPAT_FMT_ULL("10") " (" EXPAT_FMT_ULL("10") " peak), amplification %8.2f (xmlparse.c:%d)\n",
|
||||
(void *)rootParser, rootParser->m_accounting.countBytesDirect, operator,
|
||||
absDiff, newTotal, peakTotal, (double)amplification, sourceLine);
|
||||
}
|
||||
|
||||
static bool
|
||||
expat_heap_increase_tolerable(XML_Parser rootParser, XmlBigCount increase,
|
||||
int sourceLine) {
|
||||
assert(rootParser != NULL);
|
||||
assert(increase > 0);
|
||||
|
||||
XmlBigCount newTotal = 0;
|
||||
bool tolerable = true;
|
||||
|
||||
// Detect integer overflow
|
||||
if ((XmlBigCount)-1 - rootParser->m_alloc_tracker.bytesAllocated < increase) {
|
||||
tolerable = false;
|
||||
} else {
|
||||
newTotal = rootParser->m_alloc_tracker.bytesAllocated + increase;
|
||||
|
||||
if (newTotal >= rootParser->m_alloc_tracker.activationThresholdBytes) {
|
||||
assert(newTotal > 0);
|
||||
// NOTE: This can be +infinity when dividing by zero but not -nan
|
||||
const float amplification
|
||||
= (float)newTotal / (float)rootParser->m_accounting.countBytesDirect;
|
||||
if (amplification
|
||||
> rootParser->m_alloc_tracker.maximumAmplificationFactor) {
|
||||
tolerable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! tolerable && (rootParser->m_alloc_tracker.debugLevel >= 1)) {
|
||||
expat_heap_stat(rootParser, '+', increase, newTotal, newTotal, sourceLine);
|
||||
}
|
||||
|
||||
return tolerable;
|
||||
}
|
||||
|
||||
# if defined(XML_TESTING)
|
||||
void *
|
||||
# else
|
||||
static void *
|
||||
# endif
|
||||
expat_malloc(XML_Parser parser, size_t size, int sourceLine) {
|
||||
// Detect integer overflow
|
||||
if (SIZE_MAX - size < sizeof(size_t) + EXPAT_MALLOC_PADDING) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const XML_Parser rootParser = getRootParserOf(parser, NULL);
|
||||
assert(rootParser->m_parentParser == NULL);
|
||||
|
||||
const size_t bytesToAllocate = sizeof(size_t) + EXPAT_MALLOC_PADDING + size;
|
||||
|
||||
if ((XmlBigCount)-1 - rootParser->m_alloc_tracker.bytesAllocated
|
||||
< bytesToAllocate) {
|
||||
return NULL; // i.e. signal integer overflow as out-of-memory
|
||||
}
|
||||
|
||||
if (! expat_heap_increase_tolerable(rootParser, bytesToAllocate,
|
||||
sourceLine)) {
|
||||
return NULL; // i.e. signal violation as out-of-memory
|
||||
}
|
||||
|
||||
// Actually allocate
|
||||
void *const mallocedPtr = parser->m_mem.malloc_fcn(bytesToAllocate);
|
||||
|
||||
if (mallocedPtr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Update in-block recorded size
|
||||
*(size_t *)mallocedPtr = size;
|
||||
|
||||
// Update accounting
|
||||
rootParser->m_alloc_tracker.bytesAllocated += bytesToAllocate;
|
||||
|
||||
// Report as needed
|
||||
if (rootParser->m_alloc_tracker.debugLevel >= 2) {
|
||||
if (rootParser->m_alloc_tracker.bytesAllocated
|
||||
> rootParser->m_alloc_tracker.peakBytesAllocated) {
|
||||
rootParser->m_alloc_tracker.peakBytesAllocated
|
||||
= rootParser->m_alloc_tracker.bytesAllocated;
|
||||
}
|
||||
expat_heap_stat(rootParser, '+', bytesToAllocate,
|
||||
rootParser->m_alloc_tracker.bytesAllocated,
|
||||
rootParser->m_alloc_tracker.peakBytesAllocated, sourceLine);
|
||||
}
|
||||
|
||||
return (char *)mallocedPtr + sizeof(size_t) + EXPAT_MALLOC_PADDING;
|
||||
}
|
||||
|
||||
# if defined(XML_TESTING)
|
||||
void
|
||||
# else
|
||||
static void
|
||||
# endif
|
||||
expat_free(XML_Parser parser, void *ptr, int sourceLine) {
|
||||
assert(parser != NULL);
|
||||
|
||||
if (ptr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
const XML_Parser rootParser = getRootParserOf(parser, NULL);
|
||||
assert(rootParser->m_parentParser == NULL);
|
||||
|
||||
// Extract size (to the eyes of malloc_fcn/realloc_fcn) and
|
||||
// the original pointer returned by malloc/realloc
|
||||
void *const mallocedPtr = (char *)ptr - EXPAT_MALLOC_PADDING - sizeof(size_t);
|
||||
const size_t bytesAllocated
|
||||
= sizeof(size_t) + EXPAT_MALLOC_PADDING + *(size_t *)mallocedPtr;
|
||||
|
||||
// Update accounting
|
||||
assert(rootParser->m_alloc_tracker.bytesAllocated >= bytesAllocated);
|
||||
rootParser->m_alloc_tracker.bytesAllocated -= bytesAllocated;
|
||||
|
||||
// Report as needed
|
||||
if (rootParser->m_alloc_tracker.debugLevel >= 2) {
|
||||
expat_heap_stat(rootParser, '-', bytesAllocated,
|
||||
rootParser->m_alloc_tracker.bytesAllocated,
|
||||
rootParser->m_alloc_tracker.peakBytesAllocated, sourceLine);
|
||||
}
|
||||
|
||||
// NOTE: This may be freeing rootParser, so freeing has to come last
|
||||
parser->m_mem.free_fcn(mallocedPtr);
|
||||
}
|
||||
|
||||
# if defined(XML_TESTING)
|
||||
void *
|
||||
# else
|
||||
static void *
|
||||
# endif
|
||||
expat_realloc(XML_Parser parser, void *ptr, size_t size, int sourceLine) {
|
||||
assert(parser != NULL);
|
||||
|
||||
if (ptr == NULL) {
|
||||
return expat_malloc(parser, size, sourceLine);
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
expat_free(parser, ptr, sourceLine);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const XML_Parser rootParser = getRootParserOf(parser, NULL);
|
||||
assert(rootParser->m_parentParser == NULL);
|
||||
|
||||
// Extract original size (to the eyes of the caller) and the original
|
||||
// pointer returned by malloc/realloc
|
||||
void *mallocedPtr = (char *)ptr - EXPAT_MALLOC_PADDING - sizeof(size_t);
|
||||
const size_t prevSize = *(size_t *)mallocedPtr;
|
||||
|
||||
// Classify upcoming change
|
||||
const bool isIncrease = (size > prevSize);
|
||||
const size_t absDiff
|
||||
= (size > prevSize) ? (size - prevSize) : (prevSize - size);
|
||||
|
||||
// Ask for permission from accounting
|
||||
if (isIncrease) {
|
||||
if (! expat_heap_increase_tolerable(rootParser, absDiff, sourceLine)) {
|
||||
return NULL; // i.e. signal violation as out-of-memory
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Integer overflow detection has already been done for us
|
||||
// by expat_heap_increase_tolerable(..) above
|
||||
assert(SIZE_MAX - sizeof(size_t) - EXPAT_MALLOC_PADDING >= size);
|
||||
|
||||
// Actually allocate
|
||||
mallocedPtr = parser->m_mem.realloc_fcn(
|
||||
mallocedPtr, sizeof(size_t) + EXPAT_MALLOC_PADDING + size);
|
||||
|
||||
if (mallocedPtr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Update accounting
|
||||
if (isIncrease) {
|
||||
assert((XmlBigCount)-1 - rootParser->m_alloc_tracker.bytesAllocated
|
||||
>= absDiff);
|
||||
rootParser->m_alloc_tracker.bytesAllocated += absDiff;
|
||||
} else { // i.e. decrease
|
||||
assert(rootParser->m_alloc_tracker.bytesAllocated >= absDiff);
|
||||
rootParser->m_alloc_tracker.bytesAllocated -= absDiff;
|
||||
}
|
||||
|
||||
// Report as needed
|
||||
if (rootParser->m_alloc_tracker.debugLevel >= 2) {
|
||||
if (rootParser->m_alloc_tracker.bytesAllocated
|
||||
> rootParser->m_alloc_tracker.peakBytesAllocated) {
|
||||
rootParser->m_alloc_tracker.peakBytesAllocated
|
||||
= rootParser->m_alloc_tracker.bytesAllocated;
|
||||
}
|
||||
expat_heap_stat(rootParser, isIncrease ? '+' : '-', absDiff,
|
||||
rootParser->m_alloc_tracker.bytesAllocated,
|
||||
rootParser->m_alloc_tracker.peakBytesAllocated, sourceLine);
|
||||
}
|
||||
|
||||
// Update in-block recorded size
|
||||
*(size_t *)mallocedPtr = size;
|
||||
|
||||
return (char *)mallocedPtr + sizeof(size_t) + EXPAT_MALLOC_PADDING;
|
||||
}
|
||||
#endif // XML_GE == 1
|
||||
|
||||
XML_Parser XMLCALL
|
||||
XML_ParserCreate(const XML_Char *encodingName) {
|
||||
@@ -799,11 +1051,14 @@ writeRandomBytes_getrandom_nonblock(void *target, size_t count) {
|
||||
void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
|
||||
const size_t bytesToWrite = count - bytesWrittenTotal;
|
||||
|
||||
assert(bytesToWrite <= INT_MAX);
|
||||
|
||||
const int bytesWrittenMore =
|
||||
# if defined(HAVE_GETRANDOM)
|
||||
getrandom(currentTarget, bytesToWrite, getrandomFlags);
|
||||
(int)getrandom(currentTarget, bytesToWrite, getrandomFlags);
|
||||
# else
|
||||
syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
|
||||
(int)syscall(SYS_getrandom, currentTarget, bytesToWrite,
|
||||
getrandomFlags);
|
||||
# endif
|
||||
|
||||
if (bytesWrittenMore > 0) {
|
||||
@@ -990,9 +1245,10 @@ generate_hash_secret_salt(XML_Parser parser) {
|
||||
|
||||
static unsigned long
|
||||
get_hash_secret_salt(XML_Parser parser) {
|
||||
if (parser->m_parentParser != NULL)
|
||||
return get_hash_secret_salt(parser->m_parentParser);
|
||||
return parser->m_hash_secret_salt;
|
||||
const XML_Parser rootParser = getRootParserOf(parser, NULL);
|
||||
assert(! rootParser->m_parentParser);
|
||||
|
||||
return rootParser->m_hash_secret_salt;
|
||||
}
|
||||
|
||||
static enum XML_Error
|
||||
@@ -1026,7 +1282,29 @@ callProcessor(XML_Parser parser, const char *start, const char *end,
|
||||
#if defined(XML_TESTING)
|
||||
g_bytesScanned += (unsigned)have_now;
|
||||
#endif
|
||||
const enum XML_Error ret = parser->m_processor(parser, start, end, endPtr);
|
||||
// Run in a loop to eliminate dangerous recursion depths
|
||||
enum XML_Error ret;
|
||||
*endPtr = start;
|
||||
while (1) {
|
||||
// Use endPtr as the new start in each iteration, since it will
|
||||
// be set to the next start point by m_processor.
|
||||
ret = parser->m_processor(parser, *endPtr, end, endPtr);
|
||||
|
||||
// Make parsing status (and in particular XML_SUSPENDED) take
|
||||
// precedence over re-enter flag when they disagree
|
||||
if (parser->m_parsingStatus.parsing != XML_PARSING) {
|
||||
parser->m_reenter = XML_FALSE;
|
||||
}
|
||||
|
||||
if (! parser->m_reenter) {
|
||||
break;
|
||||
}
|
||||
|
||||
parser->m_reenter = XML_FALSE;
|
||||
if (ret != XML_ERROR_NONE)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret == XML_ERROR_NONE) {
|
||||
// if we consumed nothing, remember what we had on this parse attempt.
|
||||
if (*endPtr == start) {
|
||||
@@ -1056,19 +1334,43 @@ XML_Parser XMLCALL
|
||||
XML_ParserCreate_MM(const XML_Char *encodingName,
|
||||
const XML_Memory_Handling_Suite *memsuite,
|
||||
const XML_Char *nameSep) {
|
||||
return parserCreate(encodingName, memsuite, nameSep, NULL);
|
||||
return parserCreate(encodingName, memsuite, nameSep, NULL, NULL);
|
||||
}
|
||||
|
||||
static XML_Parser
|
||||
parserCreate(const XML_Char *encodingName,
|
||||
const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep,
|
||||
DTD *dtd) {
|
||||
XML_Parser parser;
|
||||
DTD *dtd, XML_Parser parentParser) {
|
||||
XML_Parser parser = NULL;
|
||||
|
||||
#if XML_GE == 1
|
||||
const size_t increase
|
||||
= sizeof(size_t) + EXPAT_MALLOC_PADDING + sizeof(struct XML_ParserStruct);
|
||||
|
||||
if (parentParser != NULL) {
|
||||
const XML_Parser rootParser = getRootParserOf(parentParser, NULL);
|
||||
if (! expat_heap_increase_tolerable(rootParser, increase, __LINE__)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
UNUSED_P(parentParser);
|
||||
#endif
|
||||
|
||||
if (memsuite) {
|
||||
XML_Memory_Handling_Suite *mtemp;
|
||||
#if XML_GE == 1
|
||||
void *const sizeAndParser
|
||||
= memsuite->malloc_fcn(sizeof(size_t) + EXPAT_MALLOC_PADDING
|
||||
+ sizeof(struct XML_ParserStruct));
|
||||
if (sizeAndParser != NULL) {
|
||||
*(size_t *)sizeAndParser = sizeof(struct XML_ParserStruct);
|
||||
parser = (XML_Parser)((char *)sizeAndParser + sizeof(size_t)
|
||||
+ EXPAT_MALLOC_PADDING);
|
||||
#else
|
||||
parser = memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
|
||||
if (parser != NULL) {
|
||||
#endif
|
||||
mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
|
||||
mtemp->malloc_fcn = memsuite->malloc_fcn;
|
||||
mtemp->realloc_fcn = memsuite->realloc_fcn;
|
||||
@@ -1076,39 +1378,86 @@ parserCreate(const XML_Char *encodingName,
|
||||
}
|
||||
} else {
|
||||
XML_Memory_Handling_Suite *mtemp;
|
||||
parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
|
||||
#if XML_GE == 1
|
||||
void *const sizeAndParser = malloc(sizeof(size_t) + EXPAT_MALLOC_PADDING
|
||||
+ sizeof(struct XML_ParserStruct));
|
||||
if (sizeAndParser != NULL) {
|
||||
*(size_t *)sizeAndParser = sizeof(struct XML_ParserStruct);
|
||||
parser = (XML_Parser)((char *)sizeAndParser + sizeof(size_t)
|
||||
+ EXPAT_MALLOC_PADDING);
|
||||
#else
|
||||
parser = malloc(sizeof(struct XML_ParserStruct));
|
||||
if (parser != NULL) {
|
||||
#endif
|
||||
mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
|
||||
mtemp->malloc_fcn = malloc;
|
||||
mtemp->realloc_fcn = realloc;
|
||||
mtemp->free_fcn = free;
|
||||
}
|
||||
}
|
||||
} // cppcheck-suppress[memleak symbolName=sizeAndParser] // Cppcheck >=2.18.0
|
||||
|
||||
if (! parser)
|
||||
return parser;
|
||||
|
||||
#if XML_GE == 1
|
||||
// Initialize .m_alloc_tracker
|
||||
memset(&parser->m_alloc_tracker, 0, sizeof(MALLOC_TRACKER));
|
||||
if (parentParser == NULL) {
|
||||
parser->m_alloc_tracker.debugLevel
|
||||
= getDebugLevel("EXPAT_MALLOC_DEBUG", 0u);
|
||||
parser->m_alloc_tracker.maximumAmplificationFactor
|
||||
= EXPAT_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT;
|
||||
parser->m_alloc_tracker.activationThresholdBytes
|
||||
= EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT;
|
||||
|
||||
// NOTE: This initialization needs to come this early because these fields
|
||||
// are read by allocation tracking code
|
||||
parser->m_parentParser = NULL;
|
||||
parser->m_accounting.countBytesDirect = 0;
|
||||
} else {
|
||||
parser->m_parentParser = parentParser;
|
||||
}
|
||||
|
||||
// Record XML_ParserStruct allocation we did a few lines up before
|
||||
const XML_Parser rootParser = getRootParserOf(parser, NULL);
|
||||
assert(rootParser->m_parentParser == NULL);
|
||||
assert(SIZE_MAX - rootParser->m_alloc_tracker.bytesAllocated >= increase);
|
||||
rootParser->m_alloc_tracker.bytesAllocated += increase;
|
||||
|
||||
// Report on allocation
|
||||
if (rootParser->m_alloc_tracker.debugLevel >= 2) {
|
||||
if (rootParser->m_alloc_tracker.bytesAllocated
|
||||
> rootParser->m_alloc_tracker.peakBytesAllocated) {
|
||||
rootParser->m_alloc_tracker.peakBytesAllocated
|
||||
= rootParser->m_alloc_tracker.bytesAllocated;
|
||||
}
|
||||
|
||||
expat_heap_stat(rootParser, '+', increase,
|
||||
rootParser->m_alloc_tracker.bytesAllocated,
|
||||
rootParser->m_alloc_tracker.peakBytesAllocated, __LINE__);
|
||||
}
|
||||
#else
|
||||
parser->m_parentParser = NULL;
|
||||
#endif // XML_GE == 1
|
||||
|
||||
parser->m_buffer = NULL;
|
||||
parser->m_bufferLim = NULL;
|
||||
|
||||
parser->m_attsSize = INIT_ATTS_SIZE;
|
||||
parser->m_atts
|
||||
= (ATTRIBUTE *)MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE));
|
||||
parser->m_atts = MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE));
|
||||
if (parser->m_atts == NULL) {
|
||||
FREE(parser, parser);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef XML_ATTR_INFO
|
||||
parser->m_attInfo = (XML_AttrInfo *)MALLOC(
|
||||
parser, parser->m_attsSize * sizeof(XML_AttrInfo));
|
||||
parser->m_attInfo = MALLOC(parser, parser->m_attsSize * sizeof(XML_AttrInfo));
|
||||
if (parser->m_attInfo == NULL) {
|
||||
FREE(parser, parser->m_atts);
|
||||
FREE(parser, parser);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
parser->m_dataBuf
|
||||
= (XML_Char *)MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char));
|
||||
parser->m_dataBuf = MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char));
|
||||
if (parser->m_dataBuf == NULL) {
|
||||
FREE(parser, parser->m_atts);
|
||||
#ifdef XML_ATTR_INFO
|
||||
@@ -1122,7 +1471,7 @@ parserCreate(const XML_Char *encodingName,
|
||||
if (dtd)
|
||||
parser->m_dtd = dtd;
|
||||
else {
|
||||
parser->m_dtd = dtdCreate(&parser->m_mem);
|
||||
parser->m_dtd = dtdCreate(parser);
|
||||
if (parser->m_dtd == NULL) {
|
||||
FREE(parser, parser->m_dataBuf);
|
||||
FREE(parser, parser->m_atts);
|
||||
@@ -1137,6 +1486,8 @@ parserCreate(const XML_Char *encodingName,
|
||||
parser->m_freeBindingList = NULL;
|
||||
parser->m_freeTagList = NULL;
|
||||
parser->m_freeInternalEntities = NULL;
|
||||
parser->m_freeAttributeEntities = NULL;
|
||||
parser->m_freeValueEntities = NULL;
|
||||
|
||||
parser->m_groupSize = 0;
|
||||
parser->m_groupConnector = NULL;
|
||||
@@ -1154,8 +1505,8 @@ parserCreate(const XML_Char *encodingName,
|
||||
|
||||
parser->m_protocolEncodingName = NULL;
|
||||
|
||||
poolInit(&parser->m_tempPool, &(parser->m_mem));
|
||||
poolInit(&parser->m_temp2Pool, &(parser->m_mem));
|
||||
poolInit(&parser->m_tempPool, parser);
|
||||
poolInit(&parser->m_temp2Pool, parser);
|
||||
parserInit(parser, encodingName);
|
||||
|
||||
if (encodingName && ! parser->m_protocolEncodingName) {
|
||||
@@ -1187,7 +1538,7 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
|
||||
parser->m_processor = prologInitProcessor;
|
||||
XmlPrologStateInit(&parser->m_prologState);
|
||||
if (encodingName != NULL) {
|
||||
parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
|
||||
parser->m_protocolEncodingName = copyString(encodingName, parser);
|
||||
}
|
||||
parser->m_curBase = NULL;
|
||||
XmlInitEncoding(&parser->m_initEncoding, &parser->m_encoding, 0);
|
||||
@@ -1239,6 +1590,8 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
|
||||
parser->m_eventEndPtr = NULL;
|
||||
parser->m_positionPtr = NULL;
|
||||
parser->m_openInternalEntities = NULL;
|
||||
parser->m_openAttributeEntities = NULL;
|
||||
parser->m_openValueEntities = NULL;
|
||||
parser->m_defaultExpandInternalEntities = XML_TRUE;
|
||||
parser->m_tagLevel = 0;
|
||||
parser->m_tagStack = NULL;
|
||||
@@ -1247,8 +1600,9 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
|
||||
parser->m_unknownEncodingMem = NULL;
|
||||
parser->m_unknownEncodingRelease = NULL;
|
||||
parser->m_unknownEncodingData = NULL;
|
||||
parser->m_parentParser = NULL;
|
||||
parser->m_parsingStatus.parsing = XML_INITIALIZED;
|
||||
// Reentry can only be triggered inside m_processor calls
|
||||
parser->m_reenter = XML_FALSE;
|
||||
#ifdef XML_DTD
|
||||
parser->m_isParamEntity = XML_FALSE;
|
||||
parser->m_useForeignDTD = XML_FALSE;
|
||||
@@ -1308,6 +1662,24 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) {
|
||||
openEntity->next = parser->m_freeInternalEntities;
|
||||
parser->m_freeInternalEntities = openEntity;
|
||||
}
|
||||
/* move m_openAttributeEntities to m_freeAttributeEntities (i.e. same task but
|
||||
* for attributes) */
|
||||
openEntityList = parser->m_openAttributeEntities;
|
||||
while (openEntityList) {
|
||||
OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
|
||||
openEntityList = openEntity->next;
|
||||
openEntity->next = parser->m_freeAttributeEntities;
|
||||
parser->m_freeAttributeEntities = openEntity;
|
||||
}
|
||||
/* move m_openValueEntities to m_freeValueEntities (i.e. same task but
|
||||
* for value entities) */
|
||||
openEntityList = parser->m_openValueEntities;
|
||||
while (openEntityList) {
|
||||
OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
|
||||
openEntityList = openEntity->next;
|
||||
openEntity->next = parser->m_freeValueEntities;
|
||||
parser->m_freeValueEntities = openEntity;
|
||||
}
|
||||
moveToFreeBindingList(parser, parser->m_inheritedBindings);
|
||||
FREE(parser, parser->m_unknownEncodingMem);
|
||||
if (parser->m_unknownEncodingRelease)
|
||||
@@ -1317,10 +1689,23 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) {
|
||||
FREE(parser, (void *)parser->m_protocolEncodingName);
|
||||
parser->m_protocolEncodingName = NULL;
|
||||
parserInit(parser, encodingName);
|
||||
dtdReset(parser->m_dtd, &parser->m_mem);
|
||||
dtdReset(parser->m_dtd, parser);
|
||||
return XML_TRUE;
|
||||
}
|
||||
|
||||
static XML_Bool
|
||||
parserBusy(XML_Parser parser) {
|
||||
switch (parser->m_parsingStatus.parsing) {
|
||||
case XML_PARSING:
|
||||
case XML_SUSPENDED:
|
||||
return XML_TRUE;
|
||||
case XML_INITIALIZED:
|
||||
case XML_FINISHED:
|
||||
default:
|
||||
return XML_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
enum XML_Status XMLCALL
|
||||
XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) {
|
||||
if (parser == NULL)
|
||||
@@ -1329,8 +1714,7 @@ XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) {
|
||||
XXX There's no way for the caller to determine which of the
|
||||
XXX possible error cases caused the XML_STATUS_ERROR return.
|
||||
*/
|
||||
if (parser->m_parsingStatus.parsing == XML_PARSING
|
||||
|| parser->m_parsingStatus.parsing == XML_SUSPENDED)
|
||||
if (parserBusy(parser))
|
||||
return XML_STATUS_ERROR;
|
||||
|
||||
/* Get rid of any previous encoding name */
|
||||
@@ -1341,7 +1725,7 @@ XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) {
|
||||
parser->m_protocolEncodingName = NULL;
|
||||
else {
|
||||
/* Copy the new encoding name into allocated memory */
|
||||
parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
|
||||
parser->m_protocolEncodingName = copyString(encodingName, parser);
|
||||
if (! parser->m_protocolEncodingName)
|
||||
return XML_STATUS_ERROR;
|
||||
}
|
||||
@@ -1450,9 +1834,10 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
|
||||
*/
|
||||
if (parser->m_ns) {
|
||||
XML_Char tmp[2] = {parser->m_namespaceSeparator, 0};
|
||||
parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
|
||||
parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd, oldParser);
|
||||
} else {
|
||||
parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
|
||||
parser
|
||||
= parserCreate(encodingName, &parser->m_mem, NULL, newDtd, oldParser);
|
||||
}
|
||||
|
||||
if (! parser)
|
||||
@@ -1496,7 +1881,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
|
||||
parser->m_prologState.inEntityValue = oldInEntityValue;
|
||||
if (context) {
|
||||
#endif /* XML_DTD */
|
||||
if (! dtdCopy(oldParser, parser->m_dtd, oldDtd, &parser->m_mem)
|
||||
if (! dtdCopy(oldParser, parser->m_dtd, oldDtd, parser)
|
||||
|| ! setContext(parser, context)) {
|
||||
XML_ParserFree(parser);
|
||||
return NULL;
|
||||
@@ -1567,7 +1952,34 @@ XML_ParserFree(XML_Parser parser) {
|
||||
entityList = entityList->next;
|
||||
FREE(parser, openEntity);
|
||||
}
|
||||
|
||||
/* free m_openAttributeEntities and m_freeAttributeEntities */
|
||||
entityList = parser->m_openAttributeEntities;
|
||||
for (;;) {
|
||||
OPEN_INTERNAL_ENTITY *openEntity;
|
||||
if (entityList == NULL) {
|
||||
if (parser->m_freeAttributeEntities == NULL)
|
||||
break;
|
||||
entityList = parser->m_freeAttributeEntities;
|
||||
parser->m_freeAttributeEntities = NULL;
|
||||
}
|
||||
openEntity = entityList;
|
||||
entityList = entityList->next;
|
||||
FREE(parser, openEntity);
|
||||
}
|
||||
/* free m_openValueEntities and m_freeValueEntities */
|
||||
entityList = parser->m_openValueEntities;
|
||||
for (;;) {
|
||||
OPEN_INTERNAL_ENTITY *openEntity;
|
||||
if (entityList == NULL) {
|
||||
if (parser->m_freeValueEntities == NULL)
|
||||
break;
|
||||
entityList = parser->m_freeValueEntities;
|
||||
parser->m_freeValueEntities = NULL;
|
||||
}
|
||||
openEntity = entityList;
|
||||
entityList = entityList->next;
|
||||
FREE(parser, openEntity);
|
||||
}
|
||||
destroyBindings(parser->m_freeBindingList, parser);
|
||||
destroyBindings(parser->m_inheritedBindings, parser);
|
||||
poolDestroy(&parser->m_tempPool);
|
||||
@@ -1581,14 +1993,16 @@ XML_ParserFree(XML_Parser parser) {
|
||||
#else
|
||||
if (parser->m_dtd)
|
||||
#endif /* XML_DTD */
|
||||
dtdDestroy(parser->m_dtd, (XML_Bool)! parser->m_parentParser,
|
||||
&parser->m_mem);
|
||||
FREE(parser, (void *)parser->m_atts);
|
||||
dtdDestroy(parser->m_dtd, (XML_Bool)! parser->m_parentParser, parser);
|
||||
FREE(parser, parser->m_atts);
|
||||
#ifdef XML_ATTR_INFO
|
||||
FREE(parser, (void *)parser->m_attInfo);
|
||||
FREE(parser, parser->m_attInfo);
|
||||
#endif
|
||||
FREE(parser, parser->m_groupConnector);
|
||||
FREE(parser, parser->m_buffer);
|
||||
// NOTE: We are avoiding FREE(..) here because parser->m_buffer
|
||||
// is not being allocated with MALLOC(..) but with plain
|
||||
// .malloc_fcn(..).
|
||||
parser->m_mem.free_fcn(parser->m_buffer);
|
||||
FREE(parser, parser->m_dataBuf);
|
||||
FREE(parser, parser->m_nsAtts);
|
||||
FREE(parser, parser->m_unknownEncodingMem);
|
||||
@@ -1609,8 +2023,7 @@ XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) {
|
||||
return XML_ERROR_INVALID_ARGUMENT;
|
||||
#ifdef XML_DTD
|
||||
/* block after XML_Parse()/XML_ParseBuffer() has been called */
|
||||
if (parser->m_parsingStatus.parsing == XML_PARSING
|
||||
|| parser->m_parsingStatus.parsing == XML_SUSPENDED)
|
||||
if (parserBusy(parser))
|
||||
return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
|
||||
parser->m_useForeignDTD = useDTD;
|
||||
return XML_ERROR_NONE;
|
||||
@@ -1625,8 +2038,7 @@ XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) {
|
||||
if (parser == NULL)
|
||||
return;
|
||||
/* block after XML_Parse()/XML_ParseBuffer() has been called */
|
||||
if (parser->m_parsingStatus.parsing == XML_PARSING
|
||||
|| parser->m_parsingStatus.parsing == XML_SUSPENDED)
|
||||
if (parserBusy(parser))
|
||||
return;
|
||||
parser->m_ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
|
||||
}
|
||||
@@ -1895,8 +2307,7 @@ XML_SetParamEntityParsing(XML_Parser parser,
|
||||
if (parser == NULL)
|
||||
return 0;
|
||||
/* block after XML_Parse()/XML_ParseBuffer() has been called */
|
||||
if (parser->m_parsingStatus.parsing == XML_PARSING
|
||||
|| parser->m_parsingStatus.parsing == XML_SUSPENDED)
|
||||
if (parserBusy(parser))
|
||||
return 0;
|
||||
#ifdef XML_DTD
|
||||
parser->m_paramEntityParsing = peParsing;
|
||||
@@ -1910,13 +2321,14 @@ int XMLCALL
|
||||
XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
|
||||
if (parser == NULL)
|
||||
return 0;
|
||||
if (parser->m_parentParser)
|
||||
return XML_SetHashSalt(parser->m_parentParser, hash_salt);
|
||||
|
||||
const XML_Parser rootParser = getRootParserOf(parser, NULL);
|
||||
assert(! rootParser->m_parentParser);
|
||||
|
||||
/* block after XML_Parse()/XML_ParseBuffer() has been called */
|
||||
if (parser->m_parsingStatus.parsing == XML_PARSING
|
||||
|| parser->m_parsingStatus.parsing == XML_SUSPENDED)
|
||||
if (parserBusy(rootParser))
|
||||
return 0;
|
||||
parser->m_hash_secret_salt = hash_salt;
|
||||
rootParser->m_hash_secret_salt = hash_salt;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2038,6 +2450,12 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) {
|
||||
|
||||
if (parser == NULL)
|
||||
return XML_STATUS_ERROR;
|
||||
|
||||
if (len < 0) {
|
||||
parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT;
|
||||
return XML_STATUS_ERROR;
|
||||
}
|
||||
|
||||
switch (parser->m_parsingStatus.parsing) {
|
||||
case XML_SUSPENDED:
|
||||
parser->m_errorCode = XML_ERROR_SUSPENDED;
|
||||
@@ -2178,7 +2596,9 @@ XML_GetBuffer(XML_Parser parser, int len) {
|
||||
parser->m_errorCode = XML_ERROR_NO_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
newBuf = (char *)MALLOC(parser, bufferSize);
|
||||
// NOTE: We are avoiding MALLOC(..) here to leave limiting
|
||||
// the input size to the application using Expat.
|
||||
newBuf = parser->m_mem.malloc_fcn(bufferSize);
|
||||
if (newBuf == 0) {
|
||||
parser->m_errorCode = XML_ERROR_NO_MEMORY;
|
||||
return NULL;
|
||||
@@ -2189,7 +2609,10 @@ XML_GetBuffer(XML_Parser parser, int len) {
|
||||
memcpy(newBuf, &parser->m_bufferPtr[-keep],
|
||||
EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr)
|
||||
+ keep);
|
||||
FREE(parser, parser->m_buffer);
|
||||
// NOTE: We are avoiding FREE(..) here because parser->m_buffer
|
||||
// is not being allocated with MALLOC(..) but with plain
|
||||
// .malloc_fcn(..).
|
||||
parser->m_mem.free_fcn(parser->m_buffer);
|
||||
parser->m_buffer = newBuf;
|
||||
parser->m_bufferEnd
|
||||
= parser->m_buffer
|
||||
@@ -2205,7 +2628,10 @@ XML_GetBuffer(XML_Parser parser, int len) {
|
||||
if (parser->m_bufferPtr) {
|
||||
memcpy(newBuf, parser->m_bufferPtr,
|
||||
EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr));
|
||||
FREE(parser, parser->m_buffer);
|
||||
// NOTE: We are avoiding FREE(..) here because parser->m_buffer
|
||||
// is not being allocated with MALLOC(..) but with plain
|
||||
// .malloc_fcn(..).
|
||||
parser->m_mem.free_fcn(parser->m_buffer);
|
||||
parser->m_bufferEnd
|
||||
= newBuf
|
||||
+ EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
|
||||
@@ -2222,11 +2648,19 @@ XML_GetBuffer(XML_Parser parser, int len) {
|
||||
return parser->m_bufferEnd;
|
||||
}
|
||||
|
||||
static void
|
||||
triggerReenter(XML_Parser parser) {
|
||||
parser->m_reenter = XML_TRUE;
|
||||
}
|
||||
|
||||
enum XML_Status XMLCALL
|
||||
XML_StopParser(XML_Parser parser, XML_Bool resumable) {
|
||||
if (parser == NULL)
|
||||
return XML_STATUS_ERROR;
|
||||
switch (parser->m_parsingStatus.parsing) {
|
||||
case XML_INITIALIZED:
|
||||
parser->m_errorCode = XML_ERROR_NOT_STARTED;
|
||||
return XML_STATUS_ERROR;
|
||||
case XML_SUSPENDED:
|
||||
if (resumable) {
|
||||
parser->m_errorCode = XML_ERROR_SUSPENDED;
|
||||
@@ -2237,7 +2671,7 @@ XML_StopParser(XML_Parser parser, XML_Bool resumable) {
|
||||
case XML_FINISHED:
|
||||
parser->m_errorCode = XML_ERROR_FINISHED;
|
||||
return XML_STATUS_ERROR;
|
||||
default:
|
||||
case XML_PARSING:
|
||||
if (resumable) {
|
||||
#ifdef XML_DTD
|
||||
if (parser->m_isParamEntity) {
|
||||
@@ -2248,6 +2682,9 @@ XML_StopParser(XML_Parser parser, XML_Bool resumable) {
|
||||
parser->m_parsingStatus.parsing = XML_SUSPENDED;
|
||||
} else
|
||||
parser->m_parsingStatus.parsing = XML_FINISHED;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return XML_STATUS_OK;
|
||||
}
|
||||
@@ -2372,28 +2809,43 @@ XML_GetCurrentColumnNumber(XML_Parser parser) {
|
||||
|
||||
void XMLCALL
|
||||
XML_FreeContentModel(XML_Parser parser, XML_Content *model) {
|
||||
if (parser != NULL)
|
||||
FREE(parser, model);
|
||||
if (parser == NULL)
|
||||
return;
|
||||
|
||||
// NOTE: We are avoiding FREE(..) here because the content model
|
||||
// has been created using plain .malloc_fcn(..) rather than MALLOC(..).
|
||||
parser->m_mem.free_fcn(model);
|
||||
}
|
||||
|
||||
void *XMLCALL
|
||||
XML_MemMalloc(XML_Parser parser, size_t size) {
|
||||
if (parser == NULL)
|
||||
return NULL;
|
||||
return MALLOC(parser, size);
|
||||
|
||||
// NOTE: We are avoiding MALLOC(..) here to not include
|
||||
// user allocations with allocation tracking and limiting.
|
||||
return parser->m_mem.malloc_fcn(size);
|
||||
}
|
||||
|
||||
void *XMLCALL
|
||||
XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) {
|
||||
if (parser == NULL)
|
||||
return NULL;
|
||||
return REALLOC(parser, ptr, size);
|
||||
|
||||
// NOTE: We are avoiding REALLOC(..) here to not include
|
||||
// user allocations with allocation tracking and limiting.
|
||||
return parser->m_mem.realloc_fcn(ptr, size);
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
XML_MemFree(XML_Parser parser, void *ptr) {
|
||||
if (parser != NULL)
|
||||
FREE(parser, ptr);
|
||||
if (parser == NULL)
|
||||
return;
|
||||
|
||||
// NOTE: We are avoiding FREE(..) here because XML_MemMalloc and
|
||||
// XML_MemRealloc are not using MALLOC(..) and REALLOC(..)
|
||||
// but plain .malloc_fcn(..) and .realloc_fcn(..), internally.
|
||||
parser->m_mem.free_fcn(ptr);
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
@@ -2512,6 +2964,9 @@ XML_ErrorString(enum XML_Error code) {
|
||||
case XML_ERROR_AMPLIFICATION_LIMIT_BREACH:
|
||||
return XML_L(
|
||||
"limit on input amplification factor (from DTD and entities) breached");
|
||||
/* Added in 2.6.4. */
|
||||
case XML_ERROR_NOT_STARTED:
|
||||
return XML_L("parser not started");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -2590,6 +3045,13 @@ XML_GetFeatureList(void) {
|
||||
EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT},
|
||||
/* Added in Expat 2.6.0. */
|
||||
{XML_FEATURE_GE, XML_L("XML_GE"), 0},
|
||||
/* Added in Expat 2.7.2. */
|
||||
{XML_FEATURE_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT,
|
||||
XML_L("XML_AT_MAX_AMP"),
|
||||
(long int)EXPAT_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT},
|
||||
{XML_FEATURE_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT,
|
||||
XML_L("XML_AT_ACT_THRES"),
|
||||
(long int)EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT},
|
||||
#endif
|
||||
{XML_FEATURE_END, NULL, 0}};
|
||||
|
||||
@@ -2618,6 +3080,29 @@ XML_SetBillionLaughsAttackProtectionActivationThreshold(
|
||||
parser->m_accounting.activationThresholdBytes = activationThresholdBytes;
|
||||
return XML_TRUE;
|
||||
}
|
||||
|
||||
XML_Bool XMLCALL
|
||||
XML_SetAllocTrackerMaximumAmplification(XML_Parser parser,
|
||||
float maximumAmplificationFactor) {
|
||||
if ((parser == NULL) || (parser->m_parentParser != NULL)
|
||||
|| isnan(maximumAmplificationFactor)
|
||||
|| (maximumAmplificationFactor < 1.0f)) {
|
||||
return XML_FALSE;
|
||||
}
|
||||
parser->m_alloc_tracker.maximumAmplificationFactor
|
||||
= maximumAmplificationFactor;
|
||||
return XML_TRUE;
|
||||
}
|
||||
|
||||
XML_Bool XMLCALL
|
||||
XML_SetAllocTrackerActivationThreshold(
|
||||
XML_Parser parser, unsigned long long activationThresholdBytes) {
|
||||
if ((parser == NULL) || (parser->m_parentParser != NULL)) {
|
||||
return XML_FALSE;
|
||||
}
|
||||
parser->m_alloc_tracker.activationThresholdBytes = activationThresholdBytes;
|
||||
return XML_TRUE;
|
||||
}
|
||||
#endif /* XML_GE == 1 */
|
||||
|
||||
XML_Bool XMLCALL
|
||||
@@ -2638,8 +3123,8 @@ static XML_Bool
|
||||
storeRawNames(XML_Parser parser) {
|
||||
TAG *tag = parser->m_tagStack;
|
||||
while (tag) {
|
||||
int bufSize;
|
||||
int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
|
||||
size_t bufSize;
|
||||
size_t nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
|
||||
size_t rawNameLen;
|
||||
char *rawNameBuf = tag->buf + nameLen;
|
||||
/* Stop if already stored. Since m_tagStack is a stack, we can stop
|
||||
@@ -2656,9 +3141,9 @@ storeRawNames(XML_Parser parser) {
|
||||
/* Detect and prevent integer overflow. */
|
||||
if (rawNameLen > (size_t)INT_MAX - nameLen)
|
||||
return XML_FALSE;
|
||||
bufSize = nameLen + (int)rawNameLen;
|
||||
if (bufSize > tag->bufEnd - tag->buf) {
|
||||
char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
|
||||
bufSize = nameLen + rawNameLen;
|
||||
if (bufSize > (size_t)(tag->bufEnd - tag->buf)) {
|
||||
char *temp = REALLOC(parser, tag->buf, bufSize);
|
||||
if (temp == NULL)
|
||||
return XML_FALSE;
|
||||
/* if tag->name.str points to tag->buf (only when namespace
|
||||
@@ -2687,8 +3172,9 @@ static enum XML_Error PTRCALL
|
||||
contentProcessor(XML_Parser parser, const char *start, const char *end,
|
||||
const char **endPtr) {
|
||||
enum XML_Error result = doContent(
|
||||
parser, 0, parser->m_encoding, start, end, endPtr,
|
||||
(XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT);
|
||||
parser, parser->m_parentParser ? 1 : 0, parser->m_encoding, start, end,
|
||||
endPtr, (XML_Bool)! parser->m_parsingStatus.finalBuffer,
|
||||
XML_ACCOUNT_DIRECT);
|
||||
if (result == XML_ERROR_NONE) {
|
||||
if (! storeRawNames(parser))
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
@@ -2776,6 +3262,11 @@ externalEntityInitProcessor3(XML_Parser parser, const char *start,
|
||||
return XML_ERROR_NONE;
|
||||
case XML_FINISHED:
|
||||
return XML_ERROR_ABORTED;
|
||||
case XML_PARSING:
|
||||
if (parser->m_reenter) {
|
||||
return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE
|
||||
}
|
||||
/* Fall through */
|
||||
default:
|
||||
start = next;
|
||||
}
|
||||
@@ -2949,7 +3440,7 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
|
||||
reportDefault(parser, enc, s, next);
|
||||
break;
|
||||
}
|
||||
result = processInternalEntity(parser, entity, XML_FALSE);
|
||||
result = processEntity(parser, entity, XML_FALSE, ENTITY_INTERNAL);
|
||||
if (result != XML_ERROR_NONE)
|
||||
return result;
|
||||
} else if (parser->m_externalEntityRefHandler) {
|
||||
@@ -2978,10 +3469,10 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
|
||||
tag = parser->m_freeTagList;
|
||||
parser->m_freeTagList = parser->m_freeTagList->parent;
|
||||
} else {
|
||||
tag = (TAG *)MALLOC(parser, sizeof(TAG));
|
||||
tag = MALLOC(parser, sizeof(TAG));
|
||||
if (! tag)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
tag->buf = (char *)MALLOC(parser, INIT_TAG_BUF_SIZE);
|
||||
tag->buf = MALLOC(parser, INIT_TAG_BUF_SIZE);
|
||||
if (! tag->buf) {
|
||||
FREE(parser, tag);
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
@@ -3014,7 +3505,7 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
|
||||
}
|
||||
bufSize = (int)(tag->bufEnd - tag->buf) << 1;
|
||||
{
|
||||
char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
|
||||
char *temp = REALLOC(parser, tag->buf, bufSize);
|
||||
if (temp == NULL)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
tag->buf = temp;
|
||||
@@ -3075,7 +3566,9 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
|
||||
}
|
||||
if ((parser->m_tagLevel == 0)
|
||||
&& (parser->m_parsingStatus.parsing != XML_FINISHED)) {
|
||||
if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
|
||||
if (parser->m_parsingStatus.parsing == XML_SUSPENDED
|
||||
|| (parser->m_parsingStatus.parsing == XML_PARSING
|
||||
&& parser->m_reenter))
|
||||
parser->m_processor = epilogProcessor;
|
||||
else
|
||||
return epilogProcessor(parser, next, end, nextPtr);
|
||||
@@ -3136,7 +3629,9 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
|
||||
}
|
||||
if ((parser->m_tagLevel == 0)
|
||||
&& (parser->m_parsingStatus.parsing != XML_FINISHED)) {
|
||||
if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
|
||||
if (parser->m_parsingStatus.parsing == XML_SUSPENDED
|
||||
|| (parser->m_parsingStatus.parsing == XML_PARSING
|
||||
&& parser->m_reenter))
|
||||
parser->m_processor = epilogProcessor;
|
||||
else
|
||||
return epilogProcessor(parser, next, end, nextPtr);
|
||||
@@ -3269,14 +3764,22 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
|
||||
break;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
*eventPP = s = next;
|
||||
switch (parser->m_parsingStatus.parsing) {
|
||||
case XML_SUSPENDED:
|
||||
*eventPP = next;
|
||||
*nextPtr = next;
|
||||
return XML_ERROR_NONE;
|
||||
case XML_FINISHED:
|
||||
*eventPP = next;
|
||||
return XML_ERROR_ABORTED;
|
||||
case XML_PARSING:
|
||||
if (parser->m_reenter) {
|
||||
*nextPtr = next;
|
||||
return XML_ERROR_NONE;
|
||||
}
|
||||
/* Fall through */
|
||||
default:;
|
||||
*eventPP = s = next;
|
||||
}
|
||||
}
|
||||
/* not reached */
|
||||
@@ -3381,8 +3884,8 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
|
||||
}
|
||||
#endif
|
||||
|
||||
temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts,
|
||||
parser->m_attsSize * sizeof(ATTRIBUTE));
|
||||
temp = REALLOC(parser, parser->m_atts,
|
||||
parser->m_attsSize * sizeof(ATTRIBUTE));
|
||||
if (temp == NULL) {
|
||||
parser->m_attsSize = oldAttsSize;
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
@@ -3400,8 +3903,8 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
|
||||
}
|
||||
# endif
|
||||
|
||||
temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo,
|
||||
parser->m_attsSize * sizeof(XML_AttrInfo));
|
||||
temp2 = REALLOC(parser, parser->m_attInfo,
|
||||
parser->m_attsSize * sizeof(XML_AttrInfo));
|
||||
if (temp2 == NULL) {
|
||||
parser->m_attsSize = oldAttsSize;
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
@@ -3536,7 +4039,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
|
||||
and clear flags that say whether attributes were specified */
|
||||
i = 0;
|
||||
if (nPrefixes) {
|
||||
int j; /* hash table index */
|
||||
unsigned int j; /* hash table index */
|
||||
unsigned long version = parser->m_nsAttsVersion;
|
||||
|
||||
/* Detect and prevent invalid shift */
|
||||
@@ -3577,8 +4080,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
|
||||
}
|
||||
#endif
|
||||
|
||||
temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts,
|
||||
nsAttsSize * sizeof(NS_ATT));
|
||||
temp = REALLOC(parser, parser->m_nsAtts, nsAttsSize * sizeof(NS_ATT));
|
||||
if (! temp) {
|
||||
/* Restore actual size of memory in m_nsAtts */
|
||||
parser->m_nsAttsPower = oldNsAttsPower;
|
||||
@@ -3631,7 +4133,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
|
||||
if (! b)
|
||||
return XML_ERROR_UNBOUND_PREFIX;
|
||||
|
||||
for (j = 0; j < b->uriLen; j++) {
|
||||
for (j = 0; j < (unsigned int)b->uriLen; j++) {
|
||||
const XML_Char c = b->uri[j];
|
||||
if (! poolAppendChar(&parser->m_tempPool, c))
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
@@ -3725,7 +4227,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
|
||||
return XML_ERROR_NONE;
|
||||
prefixLen = 0;
|
||||
if (parser->m_ns_triplets && binding->prefix->name) {
|
||||
for (; binding->prefix->name[prefixLen++];)
|
||||
while (binding->prefix->name[prefixLen++])
|
||||
; /* prefixLen includes null terminator */
|
||||
}
|
||||
tagNamePtr->localPart = localPart;
|
||||
@@ -3759,7 +4261,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
|
||||
}
|
||||
#endif
|
||||
|
||||
uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char));
|
||||
uri = MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char));
|
||||
if (! uri)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
binding->uriAlloc = n + EXPAND_SPARE;
|
||||
@@ -4005,8 +4507,8 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
|
||||
}
|
||||
#endif
|
||||
|
||||
XML_Char *temp = (XML_Char *)REALLOC(
|
||||
parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
|
||||
XML_Char *temp
|
||||
= REALLOC(parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
|
||||
if (temp == NULL)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
b->uri = temp;
|
||||
@@ -4014,7 +4516,7 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
|
||||
}
|
||||
parser->m_freeBindingList = b->nextTagBinding;
|
||||
} else {
|
||||
b = (BINDING *)MALLOC(parser, sizeof(BINDING));
|
||||
b = MALLOC(parser, sizeof(BINDING));
|
||||
if (! b)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
|
||||
@@ -4032,8 +4534,7 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
|
||||
}
|
||||
#endif
|
||||
|
||||
b->uri
|
||||
= (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
|
||||
b->uri = MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
|
||||
if (! b->uri) {
|
||||
FREE(parser, b);
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
@@ -4193,14 +4694,21 @@ doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
*eventPP = s = next;
|
||||
switch (parser->m_parsingStatus.parsing) {
|
||||
case XML_SUSPENDED:
|
||||
*eventPP = next;
|
||||
*nextPtr = next;
|
||||
return XML_ERROR_NONE;
|
||||
case XML_FINISHED:
|
||||
*eventPP = next;
|
||||
return XML_ERROR_ABORTED;
|
||||
case XML_PARSING:
|
||||
if (parser->m_reenter) {
|
||||
return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE
|
||||
}
|
||||
/* Fall through */
|
||||
default:;
|
||||
*eventPP = s = next;
|
||||
}
|
||||
}
|
||||
/* not reached */
|
||||
@@ -4532,7 +5040,7 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
|
||||
}
|
||||
/* found end of entity value - can store it now */
|
||||
return storeEntityValue(parser, parser->m_encoding, s, end,
|
||||
XML_ACCOUNT_DIRECT);
|
||||
XML_ACCOUNT_DIRECT, NULL);
|
||||
} else if (tok == XML_TOK_XML_DECL) {
|
||||
enum XML_Error result;
|
||||
result = processXmlDecl(parser, 0, start, next);
|
||||
@@ -4659,7 +5167,7 @@ entityValueProcessor(XML_Parser parser, const char *s, const char *end,
|
||||
break;
|
||||
}
|
||||
/* found end of entity value - can store it now */
|
||||
return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT);
|
||||
return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT, NULL);
|
||||
}
|
||||
start = next;
|
||||
}
|
||||
@@ -5102,9 +5610,9 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
|
||||
#if XML_GE == 1
|
||||
// This will store the given replacement text in
|
||||
// parser->m_declEntity->textPtr.
|
||||
enum XML_Error result
|
||||
= storeEntityValue(parser, enc, s + enc->minBytesPerChar,
|
||||
next - enc->minBytesPerChar, XML_ACCOUNT_NONE);
|
||||
enum XML_Error result = callStoreEntityValue(
|
||||
parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar,
|
||||
XML_ACCOUNT_NONE);
|
||||
if (parser->m_declEntity) {
|
||||
parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
|
||||
parser->m_declEntity->textLen
|
||||
@@ -5397,7 +5905,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
char *const new_connector = (char *)REALLOC(
|
||||
char *const new_connector = REALLOC(
|
||||
parser, parser->m_groupConnector, parser->m_groupSize *= 2);
|
||||
if (new_connector == NULL) {
|
||||
parser->m_groupSize /= 2;
|
||||
@@ -5417,15 +5925,14 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
|
||||
}
|
||||
#endif
|
||||
|
||||
int *const new_scaff_index = (int *)REALLOC(
|
||||
int *const new_scaff_index = REALLOC(
|
||||
parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int));
|
||||
if (new_scaff_index == NULL)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
dtd->scaffIndex = new_scaff_index;
|
||||
}
|
||||
} else {
|
||||
parser->m_groupConnector
|
||||
= (char *)MALLOC(parser, parser->m_groupSize = 32);
|
||||
parser->m_groupConnector = MALLOC(parser, parser->m_groupSize = 32);
|
||||
if (! parser->m_groupConnector) {
|
||||
parser->m_groupSize = 0;
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
@@ -5529,7 +6036,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
|
||||
enum XML_Error result;
|
||||
XML_Bool betweenDecl
|
||||
= (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
|
||||
result = processInternalEntity(parser, entity, betweenDecl);
|
||||
result = processEntity(parser, entity, betweenDecl, ENTITY_INTERNAL);
|
||||
if (result != XML_ERROR_NONE)
|
||||
return result;
|
||||
handleDefault = XML_FALSE;
|
||||
@@ -5582,8 +6089,11 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
|
||||
case XML_ROLE_CONTENT_EMPTY:
|
||||
if (dtd->in_eldecl) {
|
||||
if (parser->m_elementDeclHandler) {
|
||||
XML_Content *content
|
||||
= (XML_Content *)MALLOC(parser, sizeof(XML_Content));
|
||||
// NOTE: We are avoiding MALLOC(..) here to so that
|
||||
// applications that are not using XML_FreeContentModel but
|
||||
// plain free(..) or .free_fcn() to free the content model's
|
||||
// memory are safe.
|
||||
XML_Content *content = parser->m_mem.malloc_fcn(sizeof(XML_Content));
|
||||
if (! content)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
content->quant = XML_CQUANT_NONE;
|
||||
@@ -5639,7 +6149,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
|
||||
name = el->name;
|
||||
dtd->scaffold[myindex].name = name;
|
||||
nameLen = 0;
|
||||
for (; name[nameLen++];)
|
||||
while (name[nameLen++])
|
||||
;
|
||||
|
||||
/* Detect and prevent integer overflow */
|
||||
@@ -5734,6 +6244,12 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
|
||||
return XML_ERROR_NONE;
|
||||
case XML_FINISHED:
|
||||
return XML_ERROR_ABORTED;
|
||||
case XML_PARSING:
|
||||
if (parser->m_reenter) {
|
||||
*nextPtr = next;
|
||||
return XML_ERROR_NONE;
|
||||
}
|
||||
/* Fall through */
|
||||
default:
|
||||
s = next;
|
||||
tok = XmlPrologTok(enc, s, end, &next);
|
||||
@@ -5801,85 +6317,92 @@ epilogProcessor(XML_Parser parser, const char *s, const char *end,
|
||||
default:
|
||||
return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
|
||||
}
|
||||
parser->m_eventPtr = s = next;
|
||||
switch (parser->m_parsingStatus.parsing) {
|
||||
case XML_SUSPENDED:
|
||||
parser->m_eventPtr = next;
|
||||
*nextPtr = next;
|
||||
return XML_ERROR_NONE;
|
||||
case XML_FINISHED:
|
||||
parser->m_eventPtr = next;
|
||||
return XML_ERROR_ABORTED;
|
||||
case XML_PARSING:
|
||||
if (parser->m_reenter) {
|
||||
return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE
|
||||
}
|
||||
/* Fall through */
|
||||
default:;
|
||||
parser->m_eventPtr = s = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static enum XML_Error
|
||||
processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
|
||||
const char *textStart, *textEnd;
|
||||
const char *next;
|
||||
enum XML_Error result;
|
||||
OPEN_INTERNAL_ENTITY *openEntity;
|
||||
processEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl,
|
||||
enum EntityType type) {
|
||||
OPEN_INTERNAL_ENTITY *openEntity, **openEntityList, **freeEntityList;
|
||||
switch (type) {
|
||||
case ENTITY_INTERNAL:
|
||||
parser->m_processor = internalEntityProcessor;
|
||||
openEntityList = &parser->m_openInternalEntities;
|
||||
freeEntityList = &parser->m_freeInternalEntities;
|
||||
break;
|
||||
case ENTITY_ATTRIBUTE:
|
||||
openEntityList = &parser->m_openAttributeEntities;
|
||||
freeEntityList = &parser->m_freeAttributeEntities;
|
||||
break;
|
||||
case ENTITY_VALUE:
|
||||
openEntityList = &parser->m_openValueEntities;
|
||||
freeEntityList = &parser->m_freeValueEntities;
|
||||
break;
|
||||
/* default case serves merely as a safety net in case of a
|
||||
* wrong entityType. Therefore we exclude the following lines
|
||||
* from the test coverage.
|
||||
*
|
||||
* LCOV_EXCL_START
|
||||
*/
|
||||
default:
|
||||
// Should not reach here
|
||||
assert(0);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
if (parser->m_freeInternalEntities) {
|
||||
openEntity = parser->m_freeInternalEntities;
|
||||
parser->m_freeInternalEntities = openEntity->next;
|
||||
if (*freeEntityList) {
|
||||
openEntity = *freeEntityList;
|
||||
*freeEntityList = openEntity->next;
|
||||
} else {
|
||||
openEntity
|
||||
= (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
|
||||
openEntity = MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
|
||||
if (! openEntity)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
entity->open = XML_TRUE;
|
||||
entity->hasMore = XML_TRUE;
|
||||
#if XML_GE == 1
|
||||
entityTrackingOnOpen(parser, entity, __LINE__);
|
||||
#endif
|
||||
entity->processed = 0;
|
||||
openEntity->next = parser->m_openInternalEntities;
|
||||
parser->m_openInternalEntities = openEntity;
|
||||
openEntity->next = *openEntityList;
|
||||
*openEntityList = openEntity;
|
||||
openEntity->entity = entity;
|
||||
openEntity->type = type;
|
||||
openEntity->startTagLevel = parser->m_tagLevel;
|
||||
openEntity->betweenDecl = betweenDecl;
|
||||
openEntity->internalEventPtr = NULL;
|
||||
openEntity->internalEventEndPtr = NULL;
|
||||
textStart = (const char *)entity->textPtr;
|
||||
textEnd = (const char *)(entity->textPtr + entity->textLen);
|
||||
/* Set a safe default value in case 'next' does not get set */
|
||||
next = textStart;
|
||||
|
||||
#ifdef XML_DTD
|
||||
if (entity->is_param) {
|
||||
int tok
|
||||
= XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
|
||||
result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
|
||||
tok, next, &next, XML_FALSE, XML_FALSE,
|
||||
XML_ACCOUNT_ENTITY_EXPANSION);
|
||||
} else
|
||||
#endif /* XML_DTD */
|
||||
result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding,
|
||||
textStart, textEnd, &next, XML_FALSE,
|
||||
XML_ACCOUNT_ENTITY_EXPANSION);
|
||||
|
||||
if (result == XML_ERROR_NONE) {
|
||||
if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
|
||||
entity->processed = (int)(next - textStart);
|
||||
parser->m_processor = internalEntityProcessor;
|
||||
} else if (parser->m_openInternalEntities->entity == entity) {
|
||||
#if XML_GE == 1
|
||||
entityTrackingOnClose(parser, entity, __LINE__);
|
||||
#endif /* XML_GE == 1 */
|
||||
entity->open = XML_FALSE;
|
||||
parser->m_openInternalEntities = openEntity->next;
|
||||
/* put openEntity back in list of free instances */
|
||||
openEntity->next = parser->m_freeInternalEntities;
|
||||
parser->m_freeInternalEntities = openEntity;
|
||||
}
|
||||
// Only internal entities make use of the reenter flag
|
||||
// therefore no need to set it for other entity types
|
||||
if (type == ENTITY_INTERNAL) {
|
||||
triggerReenter(parser);
|
||||
}
|
||||
return result;
|
||||
return XML_ERROR_NONE;
|
||||
}
|
||||
|
||||
static enum XML_Error PTRCALL
|
||||
internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
|
||||
const char **nextPtr) {
|
||||
UNUSED_P(s);
|
||||
UNUSED_P(end);
|
||||
UNUSED_P(nextPtr);
|
||||
ENTITY *entity;
|
||||
const char *textStart, *textEnd;
|
||||
const char *next;
|
||||
@@ -5889,72 +6412,71 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
|
||||
return XML_ERROR_UNEXPECTED_STATE;
|
||||
|
||||
entity = openEntity->entity;
|
||||
textStart = ((const char *)entity->textPtr) + entity->processed;
|
||||
textEnd = (const char *)(entity->textPtr + entity->textLen);
|
||||
/* Set a safe default value in case 'next' does not get set */
|
||||
next = textStart;
|
||||
|
||||
#ifdef XML_DTD
|
||||
if (entity->is_param) {
|
||||
int tok
|
||||
= XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
|
||||
result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
|
||||
tok, next, &next, XML_FALSE, XML_TRUE,
|
||||
XML_ACCOUNT_ENTITY_EXPANSION);
|
||||
} else
|
||||
#endif /* XML_DTD */
|
||||
result = doContent(parser, openEntity->startTagLevel,
|
||||
parser->m_internalEncoding, textStart, textEnd, &next,
|
||||
XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION);
|
||||
// This will return early
|
||||
if (entity->hasMore) {
|
||||
textStart = ((const char *)entity->textPtr) + entity->processed;
|
||||
textEnd = (const char *)(entity->textPtr + entity->textLen);
|
||||
/* Set a safe default value in case 'next' does not get set */
|
||||
next = textStart;
|
||||
|
||||
if (result != XML_ERROR_NONE)
|
||||
if (entity->is_param) {
|
||||
int tok
|
||||
= XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
|
||||
result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
|
||||
tok, next, &next, XML_FALSE, XML_FALSE,
|
||||
XML_ACCOUNT_ENTITY_EXPANSION);
|
||||
} else {
|
||||
result = doContent(parser, openEntity->startTagLevel,
|
||||
parser->m_internalEncoding, textStart, textEnd, &next,
|
||||
XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION);
|
||||
}
|
||||
|
||||
if (result != XML_ERROR_NONE)
|
||||
return result;
|
||||
// Check if entity is complete, if not, mark down how much of it is
|
||||
// processed
|
||||
if (textEnd != next
|
||||
&& (parser->m_parsingStatus.parsing == XML_SUSPENDED
|
||||
|| (parser->m_parsingStatus.parsing == XML_PARSING
|
||||
&& parser->m_reenter))) {
|
||||
entity->processed = (int)(next - (const char *)entity->textPtr);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Entity is complete. We cannot close it here since we need to first
|
||||
// process its possible inner entities (which are added to the
|
||||
// m_openInternalEntities during doProlog or doContent calls above)
|
||||
entity->hasMore = XML_FALSE;
|
||||
if (! entity->is_param
|
||||
&& (openEntity->startTagLevel != parser->m_tagLevel)) {
|
||||
return XML_ERROR_ASYNC_ENTITY;
|
||||
}
|
||||
triggerReenter(parser);
|
||||
return result;
|
||||
} // End of entity processing, "if" block will return here
|
||||
|
||||
if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
|
||||
entity->processed = (int)(next - (const char *)entity->textPtr);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Remove fully processed openEntity from open entity list.
|
||||
#if XML_GE == 1
|
||||
entityTrackingOnClose(parser, entity, __LINE__);
|
||||
#endif
|
||||
// openEntity is m_openInternalEntities' head, as we set it at the start of
|
||||
// this function and we skipped doProlog and doContent calls with hasMore set
|
||||
// to false. This means we can directly remove the head of
|
||||
// m_openInternalEntities
|
||||
assert(parser->m_openInternalEntities == openEntity);
|
||||
entity->open = XML_FALSE;
|
||||
parser->m_openInternalEntities = openEntity->next;
|
||||
parser->m_openInternalEntities = parser->m_openInternalEntities->next;
|
||||
|
||||
/* put openEntity back in list of free instances */
|
||||
openEntity->next = parser->m_freeInternalEntities;
|
||||
parser->m_freeInternalEntities = openEntity;
|
||||
|
||||
// If there are more open entities we want to stop right here and have the
|
||||
// upcoming call to XML_ResumeParser continue with entity content, or it would
|
||||
// be ignored altogether.
|
||||
if (parser->m_openInternalEntities != NULL
|
||||
&& parser->m_parsingStatus.parsing == XML_SUSPENDED) {
|
||||
return XML_ERROR_NONE;
|
||||
}
|
||||
|
||||
#ifdef XML_DTD
|
||||
if (entity->is_param) {
|
||||
int tok;
|
||||
parser->m_processor = prologProcessor;
|
||||
tok = XmlPrologTok(parser->m_encoding, s, end, &next);
|
||||
return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
|
||||
(XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
|
||||
XML_ACCOUNT_DIRECT);
|
||||
} else
|
||||
#endif /* XML_DTD */
|
||||
{
|
||||
parser->m_processor = contentProcessor;
|
||||
/* see externalEntityContentProcessor vs contentProcessor */
|
||||
result = doContent(parser, parser->m_parentParser ? 1 : 0,
|
||||
parser->m_encoding, s, end, nextPtr,
|
||||
(XML_Bool)! parser->m_parsingStatus.finalBuffer,
|
||||
XML_ACCOUNT_DIRECT);
|
||||
if (result == XML_ERROR_NONE) {
|
||||
if (! storeRawNames(parser))
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
return result;
|
||||
if (parser->m_openInternalEntities == NULL) {
|
||||
parser->m_processor = entity->is_param ? prologProcessor : contentProcessor;
|
||||
}
|
||||
triggerReenter(parser);
|
||||
return XML_ERROR_NONE;
|
||||
}
|
||||
|
||||
static enum XML_Error PTRCALL
|
||||
@@ -5970,8 +6492,70 @@ static enum XML_Error
|
||||
storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
|
||||
const char *ptr, const char *end, STRING_POOL *pool,
|
||||
enum XML_Account account) {
|
||||
enum XML_Error result
|
||||
= appendAttributeValue(parser, enc, isCdata, ptr, end, pool, account);
|
||||
const char *next = ptr;
|
||||
enum XML_Error result = XML_ERROR_NONE;
|
||||
|
||||
while (1) {
|
||||
if (! parser->m_openAttributeEntities) {
|
||||
result = appendAttributeValue(parser, enc, isCdata, next, end, pool,
|
||||
account, &next);
|
||||
} else {
|
||||
OPEN_INTERNAL_ENTITY *const openEntity = parser->m_openAttributeEntities;
|
||||
if (! openEntity)
|
||||
return XML_ERROR_UNEXPECTED_STATE;
|
||||
|
||||
ENTITY *const entity = openEntity->entity;
|
||||
const char *const textStart
|
||||
= ((const char *)entity->textPtr) + entity->processed;
|
||||
const char *const textEnd
|
||||
= (const char *)(entity->textPtr + entity->textLen);
|
||||
/* Set a safe default value in case 'next' does not get set */
|
||||
const char *nextInEntity = textStart;
|
||||
if (entity->hasMore) {
|
||||
result = appendAttributeValue(
|
||||
parser, parser->m_internalEncoding, isCdata, textStart, textEnd,
|
||||
pool, XML_ACCOUNT_ENTITY_EXPANSION, &nextInEntity);
|
||||
if (result != XML_ERROR_NONE)
|
||||
break;
|
||||
// Check if entity is complete, if not, mark down how much of it is
|
||||
// processed. A XML_SUSPENDED check here is not required as
|
||||
// appendAttributeValue will never suspend the parser.
|
||||
if (textEnd != nextInEntity) {
|
||||
entity->processed
|
||||
= (int)(nextInEntity - (const char *)entity->textPtr);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Entity is complete. We cannot close it here since we need to first
|
||||
// process its possible inner entities (which are added to the
|
||||
// m_openAttributeEntities during appendAttributeValue)
|
||||
entity->hasMore = XML_FALSE;
|
||||
continue;
|
||||
} // End of entity processing, "if" block skips the rest
|
||||
|
||||
// Remove fully processed openEntity from open entity list.
|
||||
#if XML_GE == 1
|
||||
entityTrackingOnClose(parser, entity, __LINE__);
|
||||
#endif
|
||||
// openEntity is m_openAttributeEntities' head, since we set it at the
|
||||
// start of this function and because we skipped appendAttributeValue call
|
||||
// with hasMore set to false. This means we can directly remove the head
|
||||
// of m_openAttributeEntities
|
||||
assert(parser->m_openAttributeEntities == openEntity);
|
||||
entity->open = XML_FALSE;
|
||||
parser->m_openAttributeEntities = parser->m_openAttributeEntities->next;
|
||||
|
||||
/* put openEntity back in list of free instances */
|
||||
openEntity->next = parser->m_freeAttributeEntities;
|
||||
parser->m_freeAttributeEntities = openEntity;
|
||||
}
|
||||
|
||||
// Break if an error occurred or there is nothing left to process
|
||||
if (result || (parser->m_openAttributeEntities == NULL && end == next)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
return result;
|
||||
if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
|
||||
@@ -5984,7 +6568,7 @@ storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
|
||||
static enum XML_Error
|
||||
appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
|
||||
const char *ptr, const char *end, STRING_POOL *pool,
|
||||
enum XML_Account account) {
|
||||
enum XML_Account account, const char **nextPtr) {
|
||||
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
|
||||
#ifndef XML_DTD
|
||||
UNUSED_P(account);
|
||||
@@ -6002,6 +6586,9 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
|
||||
#endif
|
||||
switch (tok) {
|
||||
case XML_TOK_NONE:
|
||||
if (nextPtr) {
|
||||
*nextPtr = next;
|
||||
}
|
||||
return XML_ERROR_NONE;
|
||||
case XML_TOK_INVALID:
|
||||
if (enc == parser->m_encoding)
|
||||
@@ -6055,7 +6642,7 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
|
||||
case XML_TOK_ENTITY_REF: {
|
||||
const XML_Char *name;
|
||||
ENTITY *entity;
|
||||
char checkEntityDecl;
|
||||
bool checkEntityDecl;
|
||||
XML_Char ch = (XML_Char)XmlPredefinedEntityName(
|
||||
enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar);
|
||||
if (ch) {
|
||||
@@ -6142,21 +6729,11 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
|
||||
return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
|
||||
} else {
|
||||
enum XML_Error result;
|
||||
const XML_Char *textEnd = entity->textPtr + entity->textLen;
|
||||
entity->open = XML_TRUE;
|
||||
#if XML_GE == 1
|
||||
entityTrackingOnOpen(parser, entity, __LINE__);
|
||||
#endif
|
||||
result = appendAttributeValue(parser, parser->m_internalEncoding,
|
||||
isCdata, (const char *)entity->textPtr,
|
||||
(const char *)textEnd, pool,
|
||||
XML_ACCOUNT_ENTITY_EXPANSION);
|
||||
#if XML_GE == 1
|
||||
entityTrackingOnClose(parser, entity, __LINE__);
|
||||
#endif
|
||||
entity->open = XML_FALSE;
|
||||
if (result)
|
||||
return result;
|
||||
result = processEntity(parser, entity, XML_FALSE, ENTITY_ATTRIBUTE);
|
||||
if ((result == XML_ERROR_NONE) && (nextPtr != NULL)) {
|
||||
*nextPtr = next;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
@@ -6185,7 +6762,7 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
|
||||
static enum XML_Error
|
||||
storeEntityValue(XML_Parser parser, const ENCODING *enc,
|
||||
const char *entityTextPtr, const char *entityTextEnd,
|
||||
enum XML_Account account) {
|
||||
enum XML_Account account, const char **nextPtr) {
|
||||
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
|
||||
STRING_POOL *pool = &(dtd->entityValuePool);
|
||||
enum XML_Error result = XML_ERROR_NONE;
|
||||
@@ -6203,8 +6780,9 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
const char *next;
|
||||
for (;;) {
|
||||
const char *next
|
||||
next
|
||||
= entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */
|
||||
int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
|
||||
|
||||
@@ -6266,16 +6844,8 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
|
||||
} else
|
||||
dtd->keepProcessing = dtd->standalone;
|
||||
} else {
|
||||
entity->open = XML_TRUE;
|
||||
entityTrackingOnOpen(parser, entity, __LINE__);
|
||||
result = storeEntityValue(
|
||||
parser, parser->m_internalEncoding, (const char *)entity->textPtr,
|
||||
(const char *)(entity->textPtr + entity->textLen),
|
||||
XML_ACCOUNT_ENTITY_EXPANSION);
|
||||
entityTrackingOnClose(parser, entity, __LINE__);
|
||||
entity->open = XML_FALSE;
|
||||
if (result)
|
||||
goto endEntityValue;
|
||||
result = processEntity(parser, entity, XML_FALSE, ENTITY_VALUE);
|
||||
goto endEntityValue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -6363,6 +6933,81 @@ endEntityValue:
|
||||
# ifdef XML_DTD
|
||||
parser->m_prologState.inEntityValue = oldInEntityValue;
|
||||
# endif /* XML_DTD */
|
||||
// If 'nextPtr' is given, it should be updated during the processing
|
||||
if (nextPtr != NULL) {
|
||||
*nextPtr = next;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static enum XML_Error
|
||||
callStoreEntityValue(XML_Parser parser, const ENCODING *enc,
|
||||
const char *entityTextPtr, const char *entityTextEnd,
|
||||
enum XML_Account account) {
|
||||
const char *next = entityTextPtr;
|
||||
enum XML_Error result = XML_ERROR_NONE;
|
||||
while (1) {
|
||||
if (! parser->m_openValueEntities) {
|
||||
result
|
||||
= storeEntityValue(parser, enc, next, entityTextEnd, account, &next);
|
||||
} else {
|
||||
OPEN_INTERNAL_ENTITY *const openEntity = parser->m_openValueEntities;
|
||||
if (! openEntity)
|
||||
return XML_ERROR_UNEXPECTED_STATE;
|
||||
|
||||
ENTITY *const entity = openEntity->entity;
|
||||
const char *const textStart
|
||||
= ((const char *)entity->textPtr) + entity->processed;
|
||||
const char *const textEnd
|
||||
= (const char *)(entity->textPtr + entity->textLen);
|
||||
/* Set a safe default value in case 'next' does not get set */
|
||||
const char *nextInEntity = textStart;
|
||||
if (entity->hasMore) {
|
||||
result = storeEntityValue(parser, parser->m_internalEncoding, textStart,
|
||||
textEnd, XML_ACCOUNT_ENTITY_EXPANSION,
|
||||
&nextInEntity);
|
||||
if (result != XML_ERROR_NONE)
|
||||
break;
|
||||
// Check if entity is complete, if not, mark down how much of it is
|
||||
// processed. A XML_SUSPENDED check here is not required as
|
||||
// appendAttributeValue will never suspend the parser.
|
||||
if (textEnd != nextInEntity) {
|
||||
entity->processed
|
||||
= (int)(nextInEntity - (const char *)entity->textPtr);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Entity is complete. We cannot close it here since we need to first
|
||||
// process its possible inner entities (which are added to the
|
||||
// m_openValueEntities during storeEntityValue)
|
||||
entity->hasMore = XML_FALSE;
|
||||
continue;
|
||||
} // End of entity processing, "if" block skips the rest
|
||||
|
||||
// Remove fully processed openEntity from open entity list.
|
||||
# if XML_GE == 1
|
||||
entityTrackingOnClose(parser, entity, __LINE__);
|
||||
# endif
|
||||
// openEntity is m_openValueEntities' head, since we set it at the
|
||||
// start of this function and because we skipped storeEntityValue call
|
||||
// with hasMore set to false. This means we can directly remove the head
|
||||
// of m_openValueEntities
|
||||
assert(parser->m_openValueEntities == openEntity);
|
||||
entity->open = XML_FALSE;
|
||||
parser->m_openValueEntities = parser->m_openValueEntities->next;
|
||||
|
||||
/* put openEntity back in list of free instances */
|
||||
openEntity->next = parser->m_freeValueEntities;
|
||||
parser->m_freeValueEntities = openEntity;
|
||||
}
|
||||
|
||||
// Break if an error occurred or there is nothing left to process
|
||||
if (result
|
||||
|| (parser->m_openValueEntities == NULL && entityTextEnd == next)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -6524,8 +7169,8 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
|
||||
if (type->nDefaultAtts == type->allocDefaultAtts) {
|
||||
if (type->allocDefaultAtts == 0) {
|
||||
type->allocDefaultAtts = 8;
|
||||
type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(
|
||||
parser, type->allocDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
|
||||
type->defaultAtts
|
||||
= MALLOC(parser, type->allocDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
|
||||
if (! type->defaultAtts) {
|
||||
type->allocDefaultAtts = 0;
|
||||
return 0;
|
||||
@@ -6550,8 +7195,8 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
|
||||
}
|
||||
#endif
|
||||
|
||||
temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts,
|
||||
(count * sizeof(DEFAULT_ATTRIBUTE)));
|
||||
temp = REALLOC(parser, type->defaultAtts,
|
||||
(count * sizeof(DEFAULT_ATTRIBUTE)));
|
||||
if (temp == NULL)
|
||||
return 0;
|
||||
type->allocDefaultAtts = count;
|
||||
@@ -6842,19 +7487,19 @@ normalizePublicId(XML_Char *publicId) {
|
||||
}
|
||||
|
||||
static DTD *
|
||||
dtdCreate(const XML_Memory_Handling_Suite *ms) {
|
||||
DTD *p = ms->malloc_fcn(sizeof(DTD));
|
||||
dtdCreate(XML_Parser parser) {
|
||||
DTD *p = MALLOC(parser, sizeof(DTD));
|
||||
if (p == NULL)
|
||||
return p;
|
||||
poolInit(&(p->pool), ms);
|
||||
poolInit(&(p->entityValuePool), ms);
|
||||
hashTableInit(&(p->generalEntities), ms);
|
||||
hashTableInit(&(p->elementTypes), ms);
|
||||
hashTableInit(&(p->attributeIds), ms);
|
||||
hashTableInit(&(p->prefixes), ms);
|
||||
poolInit(&(p->pool), parser);
|
||||
poolInit(&(p->entityValuePool), parser);
|
||||
hashTableInit(&(p->generalEntities), parser);
|
||||
hashTableInit(&(p->elementTypes), parser);
|
||||
hashTableInit(&(p->attributeIds), parser);
|
||||
hashTableInit(&(p->prefixes), parser);
|
||||
#ifdef XML_DTD
|
||||
p->paramEntityRead = XML_FALSE;
|
||||
hashTableInit(&(p->paramEntities), ms);
|
||||
hashTableInit(&(p->paramEntities), parser);
|
||||
#endif /* XML_DTD */
|
||||
p->defaultPrefix.name = NULL;
|
||||
p->defaultPrefix.binding = NULL;
|
||||
@@ -6874,7 +7519,7 @@ dtdCreate(const XML_Memory_Handling_Suite *ms) {
|
||||
}
|
||||
|
||||
static void
|
||||
dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) {
|
||||
dtdReset(DTD *p, XML_Parser parser) {
|
||||
HASH_TABLE_ITER iter;
|
||||
hashTableIterInit(&iter, &(p->elementTypes));
|
||||
for (;;) {
|
||||
@@ -6882,7 +7527,7 @@ dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) {
|
||||
if (! e)
|
||||
break;
|
||||
if (e->allocDefaultAtts != 0)
|
||||
ms->free_fcn(e->defaultAtts);
|
||||
FREE(parser, e->defaultAtts);
|
||||
}
|
||||
hashTableClear(&(p->generalEntities));
|
||||
#ifdef XML_DTD
|
||||
@@ -6899,9 +7544,9 @@ dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) {
|
||||
|
||||
p->in_eldecl = XML_FALSE;
|
||||
|
||||
ms->free_fcn(p->scaffIndex);
|
||||
FREE(parser, p->scaffIndex);
|
||||
p->scaffIndex = NULL;
|
||||
ms->free_fcn(p->scaffold);
|
||||
FREE(parser, p->scaffold);
|
||||
p->scaffold = NULL;
|
||||
|
||||
p->scaffLevel = 0;
|
||||
@@ -6915,7 +7560,7 @@ dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) {
|
||||
}
|
||||
|
||||
static void
|
||||
dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) {
|
||||
dtdDestroy(DTD *p, XML_Bool isDocEntity, XML_Parser parser) {
|
||||
HASH_TABLE_ITER iter;
|
||||
hashTableIterInit(&iter, &(p->elementTypes));
|
||||
for (;;) {
|
||||
@@ -6923,7 +7568,7 @@ dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) {
|
||||
if (! e)
|
||||
break;
|
||||
if (e->allocDefaultAtts != 0)
|
||||
ms->free_fcn(e->defaultAtts);
|
||||
FREE(parser, e->defaultAtts);
|
||||
}
|
||||
hashTableDestroy(&(p->generalEntities));
|
||||
#ifdef XML_DTD
|
||||
@@ -6935,10 +7580,10 @@ dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) {
|
||||
poolDestroy(&(p->pool));
|
||||
poolDestroy(&(p->entityValuePool));
|
||||
if (isDocEntity) {
|
||||
ms->free_fcn(p->scaffIndex);
|
||||
ms->free_fcn(p->scaffold);
|
||||
FREE(parser, p->scaffIndex);
|
||||
FREE(parser, p->scaffold);
|
||||
}
|
||||
ms->free_fcn(p);
|
||||
FREE(parser, p);
|
||||
}
|
||||
|
||||
/* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
|
||||
@@ -6946,7 +7591,7 @@ dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) {
|
||||
*/
|
||||
static int
|
||||
dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
|
||||
const XML_Memory_Handling_Suite *ms) {
|
||||
XML_Parser parser) {
|
||||
HASH_TABLE_ITER iter;
|
||||
|
||||
/* Copy the prefix table. */
|
||||
@@ -7016,8 +7661,18 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
|
||||
if (! newE)
|
||||
return 0;
|
||||
if (oldE->nDefaultAtts) {
|
||||
/* Detect and prevent integer overflow.
|
||||
* The preprocessor guard addresses the "always false" warning
|
||||
* from -Wtype-limits on platforms where
|
||||
* sizeof(int) < sizeof(size_t), e.g. on x86_64. */
|
||||
#if UINT_MAX >= SIZE_MAX
|
||||
if ((size_t)oldE->nDefaultAtts
|
||||
> ((size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE))) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
newE->defaultAtts
|
||||
= ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
|
||||
= MALLOC(parser, oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
|
||||
if (! newE->defaultAtts) {
|
||||
return 0;
|
||||
}
|
||||
@@ -7179,7 +7834,7 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
|
||||
/* table->size is a power of 2 */
|
||||
table->size = (size_t)1 << INIT_POWER;
|
||||
tsize = table->size * sizeof(NAMED *);
|
||||
table->v = table->mem->malloc_fcn(tsize);
|
||||
table->v = MALLOC(table->parser, tsize);
|
||||
if (! table->v) {
|
||||
table->size = 0;
|
||||
return NULL;
|
||||
@@ -7219,7 +7874,7 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
|
||||
}
|
||||
|
||||
size_t tsize = newSize * sizeof(NAMED *);
|
||||
NAMED **newV = table->mem->malloc_fcn(tsize);
|
||||
NAMED **newV = MALLOC(table->parser, tsize);
|
||||
if (! newV)
|
||||
return NULL;
|
||||
memset(newV, 0, tsize);
|
||||
@@ -7235,7 +7890,7 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
|
||||
}
|
||||
newV[j] = table->v[i];
|
||||
}
|
||||
table->mem->free_fcn(table->v);
|
||||
FREE(table->parser, table->v);
|
||||
table->v = newV;
|
||||
table->power = newPower;
|
||||
table->size = newSize;
|
||||
@@ -7248,7 +7903,7 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
|
||||
}
|
||||
}
|
||||
}
|
||||
table->v[i] = table->mem->malloc_fcn(createSize);
|
||||
table->v[i] = MALLOC(table->parser, createSize);
|
||||
if (! table->v[i])
|
||||
return NULL;
|
||||
memset(table->v[i], 0, createSize);
|
||||
@@ -7261,7 +7916,7 @@ static void FASTCALL
|
||||
hashTableClear(HASH_TABLE *table) {
|
||||
size_t i;
|
||||
for (i = 0; i < table->size; i++) {
|
||||
table->mem->free_fcn(table->v[i]);
|
||||
FREE(table->parser, table->v[i]);
|
||||
table->v[i] = NULL;
|
||||
}
|
||||
table->used = 0;
|
||||
@@ -7271,17 +7926,17 @@ static void FASTCALL
|
||||
hashTableDestroy(HASH_TABLE *table) {
|
||||
size_t i;
|
||||
for (i = 0; i < table->size; i++)
|
||||
table->mem->free_fcn(table->v[i]);
|
||||
table->mem->free_fcn(table->v);
|
||||
FREE(table->parser, table->v[i]);
|
||||
FREE(table->parser, table->v);
|
||||
}
|
||||
|
||||
static void FASTCALL
|
||||
hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) {
|
||||
hashTableInit(HASH_TABLE *p, XML_Parser parser) {
|
||||
p->power = 0;
|
||||
p->size = 0;
|
||||
p->used = 0;
|
||||
p->v = NULL;
|
||||
p->mem = ms;
|
||||
p->parser = parser;
|
||||
}
|
||||
|
||||
static void FASTCALL
|
||||
@@ -7301,13 +7956,13 @@ hashTableIterNext(HASH_TABLE_ITER *iter) {
|
||||
}
|
||||
|
||||
static void FASTCALL
|
||||
poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) {
|
||||
poolInit(STRING_POOL *pool, XML_Parser parser) {
|
||||
pool->blocks = NULL;
|
||||
pool->freeBlocks = NULL;
|
||||
pool->start = NULL;
|
||||
pool->ptr = NULL;
|
||||
pool->end = NULL;
|
||||
pool->mem = ms;
|
||||
pool->parser = parser;
|
||||
}
|
||||
|
||||
static void FASTCALL
|
||||
@@ -7334,13 +7989,13 @@ poolDestroy(STRING_POOL *pool) {
|
||||
BLOCK *p = pool->blocks;
|
||||
while (p) {
|
||||
BLOCK *tem = p->next;
|
||||
pool->mem->free_fcn(p);
|
||||
FREE(pool->parser, p);
|
||||
p = tem;
|
||||
}
|
||||
p = pool->freeBlocks;
|
||||
while (p) {
|
||||
BLOCK *tem = p->next;
|
||||
pool->mem->free_fcn(p);
|
||||
FREE(pool->parser, p);
|
||||
p = tem;
|
||||
}
|
||||
}
|
||||
@@ -7495,8 +8150,7 @@ poolGrow(STRING_POOL *pool) {
|
||||
if (bytesToAllocate == 0)
|
||||
return XML_FALSE;
|
||||
|
||||
temp = (BLOCK *)pool->mem->realloc_fcn(pool->blocks,
|
||||
(unsigned)bytesToAllocate);
|
||||
temp = REALLOC(pool->parser, pool->blocks, bytesToAllocate);
|
||||
if (temp == NULL)
|
||||
return XML_FALSE;
|
||||
pool->blocks = temp;
|
||||
@@ -7536,7 +8190,7 @@ poolGrow(STRING_POOL *pool) {
|
||||
if (bytesToAllocate == 0)
|
||||
return XML_FALSE;
|
||||
|
||||
tem = pool->mem->malloc_fcn(bytesToAllocate);
|
||||
tem = MALLOC(pool->parser, bytesToAllocate);
|
||||
if (! tem)
|
||||
return XML_FALSE;
|
||||
tem->size = blockSize;
|
||||
@@ -7558,12 +8212,26 @@ nextScaffoldPart(XML_Parser parser) {
|
||||
int next;
|
||||
|
||||
if (! dtd->scaffIndex) {
|
||||
dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int));
|
||||
/* Detect and prevent integer overflow.
|
||||
* The preprocessor guard addresses the "always false" warning
|
||||
* from -Wtype-limits on platforms where
|
||||
* sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
|
||||
#if UINT_MAX >= SIZE_MAX
|
||||
if (parser->m_groupSize > ((size_t)(-1) / sizeof(int))) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
dtd->scaffIndex = MALLOC(parser, parser->m_groupSize * sizeof(int));
|
||||
if (! dtd->scaffIndex)
|
||||
return -1;
|
||||
dtd->scaffIndex[0] = 0;
|
||||
}
|
||||
|
||||
// Will casting to int be safe further down?
|
||||
if (dtd->scaffCount > INT_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dtd->scaffCount >= dtd->scaffSize) {
|
||||
CONTENT_SCAFFOLD *temp;
|
||||
if (dtd->scaffold) {
|
||||
@@ -7581,21 +8249,20 @@ nextScaffoldPart(XML_Parser parser) {
|
||||
}
|
||||
#endif
|
||||
|
||||
temp = (CONTENT_SCAFFOLD *)REALLOC(
|
||||
parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
|
||||
temp = REALLOC(parser, dtd->scaffold,
|
||||
dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
|
||||
if (temp == NULL)
|
||||
return -1;
|
||||
dtd->scaffSize *= 2;
|
||||
} else {
|
||||
temp = (CONTENT_SCAFFOLD *)MALLOC(parser, INIT_SCAFFOLD_ELEMENTS
|
||||
* sizeof(CONTENT_SCAFFOLD));
|
||||
temp = MALLOC(parser, INIT_SCAFFOLD_ELEMENTS * sizeof(CONTENT_SCAFFOLD));
|
||||
if (temp == NULL)
|
||||
return -1;
|
||||
dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
|
||||
}
|
||||
dtd->scaffold = temp;
|
||||
}
|
||||
next = dtd->scaffCount++;
|
||||
next = (int)dtd->scaffCount++;
|
||||
me = &dtd->scaffold[next];
|
||||
if (dtd->scaffLevel) {
|
||||
CONTENT_SCAFFOLD *parent
|
||||
@@ -7642,7 +8309,10 @@ build_model(XML_Parser parser) {
|
||||
const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content)
|
||||
+ (dtd->contentStringLen * sizeof(XML_Char)));
|
||||
|
||||
ret = (XML_Content *)MALLOC(parser, allocsize);
|
||||
// NOTE: We are avoiding MALLOC(..) here to so that
|
||||
// applications that are not using XML_FreeContentModel but plain
|
||||
// free(..) or .free_fcn() to free the content model's memory are safe.
|
||||
ret = parser->m_mem.malloc_fcn(allocsize);
|
||||
if (! ret)
|
||||
return NULL;
|
||||
|
||||
@@ -7763,7 +8433,7 @@ getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr,
|
||||
}
|
||||
|
||||
static XML_Char *
|
||||
copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {
|
||||
copyString(const XML_Char *s, XML_Parser parser) {
|
||||
size_t charsRequired = 0;
|
||||
XML_Char *result;
|
||||
|
||||
@@ -7775,7 +8445,7 @@ copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {
|
||||
charsRequired++;
|
||||
|
||||
/* Now allocate space for the copy */
|
||||
result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char));
|
||||
result = MALLOC(parser, charsRequired * sizeof(XML_Char));
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
/* Copy the original into place */
|
||||
@@ -7794,10 +8464,10 @@ accountingGetCurrentAmplification(XML_Parser rootParser) {
|
||||
+ rootParser->m_accounting.countBytesIndirect;
|
||||
const float amplificationFactor
|
||||
= rootParser->m_accounting.countBytesDirect
|
||||
? (countBytesOutput
|
||||
? ((float)countBytesOutput
|
||||
/ (float)(rootParser->m_accounting.countBytesDirect))
|
||||
: ((lenOfShortestInclude
|
||||
+ rootParser->m_accounting.countBytesIndirect)
|
||||
: ((float)(lenOfShortestInclude
|
||||
+ rootParser->m_accounting.countBytesIndirect)
|
||||
/ (float)lenOfShortestInclude);
|
||||
assert(! rootParser->m_parentParser);
|
||||
return amplificationFactor;
|
||||
@@ -7835,7 +8505,7 @@ accountingReportDiff(XML_Parser rootParser,
|
||||
assert(! rootParser->m_parentParser);
|
||||
|
||||
fprintf(stderr,
|
||||
" (+" EXPAT_FMT_PTRDIFF_T("6") " bytes %s|%d, xmlparse.c:%d) %*s\"",
|
||||
" (+" EXPAT_FMT_PTRDIFF_T("6") " bytes %s|%u, xmlparse.c:%d) %*s\"",
|
||||
bytesMore, (account == XML_ACCOUNT_DIRECT) ? "DIR" : "EXP",
|
||||
levelsAwayFromRootParser, source_line, 10, "");
|
||||
|
||||
@@ -7948,11 +8618,11 @@ entityTrackingReportStats(XML_Parser rootParser, ENTITY *entity,
|
||||
|
||||
fprintf(
|
||||
stderr,
|
||||
"expat: Entities(%p): Count %9d, depth %2d/%2d %*s%s%s; %s length %d (xmlparse.c:%d)\n",
|
||||
"expat: Entities(%p): Count %9u, depth %2u/%2u %*s%s%s; %s length %d (xmlparse.c:%d)\n",
|
||||
(void *)rootParser, rootParser->m_entity_stats.countEverOpened,
|
||||
rootParser->m_entity_stats.currentDepth,
|
||||
rootParser->m_entity_stats.maximumDepthSeen,
|
||||
(rootParser->m_entity_stats.currentDepth - 1) * 2, "",
|
||||
((int)rootParser->m_entity_stats.currentDepth - 1) * 2, "",
|
||||
entity->is_param ? "%" : "&", entityName, action, entity->textLen,
|
||||
sourceLine);
|
||||
}
|
||||
@@ -7981,6 +8651,8 @@ entityTrackingOnClose(XML_Parser originParser, ENTITY *entity, int sourceLine) {
|
||||
rootParser->m_entity_stats.currentDepth--;
|
||||
}
|
||||
|
||||
#endif /* XML_GE == 1 */
|
||||
|
||||
static XML_Parser
|
||||
getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) {
|
||||
XML_Parser rootParser = parser;
|
||||
@@ -7996,6 +8668,8 @@ getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) {
|
||||
return rootParser;
|
||||
}
|
||||
|
||||
#if XML_GE == 1
|
||||
|
||||
const char *
|
||||
unsignedCharToPrintable(unsigned char c) {
|
||||
switch (c) {
|
||||
@@ -8511,11 +9185,13 @@ unsignedCharToPrintable(unsigned char c) {
|
||||
return "\\xFE";
|
||||
case 255:
|
||||
return "\\xFF";
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
assert(0); /* never gets here */
|
||||
return "dead code";
|
||||
}
|
||||
assert(0); /* never gets here */
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
#endif /* XML_GE == 1 */
|
||||
|
||||
+15
-21
@@ -10,7 +10,7 @@
|
||||
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
|
||||
Copyright (c) 2002 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
|
||||
Copyright (c) 2017-2024 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2017-2025 Sebastian Pipping <sebastian@pipping.org>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -34,19 +34,13 @@
|
||||
*/
|
||||
|
||||
#ifndef XmlRole_INCLUDED
|
||||
#define XmlRole_INCLUDED 1
|
||||
# define XmlRole_INCLUDED 1
|
||||
|
||||
#ifdef __VMS
|
||||
/* 0 1 2 3 0 1 2 3
|
||||
1234567890123456789012345678901 1234567890123456789012345678901 */
|
||||
# define XmlPrologStateInitExternalEntity XmlPrologStateInitExternalEnt
|
||||
#endif
|
||||
# include "xmltok.h"
|
||||
|
||||
#include "xmltok.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
# endif
|
||||
|
||||
enum {
|
||||
XML_ROLE_ERROR = -1,
|
||||
@@ -107,11 +101,11 @@ enum {
|
||||
XML_ROLE_CONTENT_ELEMENT_PLUS,
|
||||
XML_ROLE_PI,
|
||||
XML_ROLE_COMMENT,
|
||||
#ifdef XML_DTD
|
||||
# ifdef XML_DTD
|
||||
XML_ROLE_TEXT_DECL,
|
||||
XML_ROLE_IGNORE_SECT,
|
||||
XML_ROLE_INNER_PARAM_ENTITY_REF,
|
||||
#endif /* XML_DTD */
|
||||
# endif /* XML_DTD */
|
||||
XML_ROLE_PARAM_ENTITY_REF
|
||||
};
|
||||
|
||||
@@ -120,23 +114,23 @@ typedef struct prolog_state {
|
||||
const char *end, const ENCODING *enc);
|
||||
unsigned level;
|
||||
int role_none;
|
||||
#ifdef XML_DTD
|
||||
# ifdef XML_DTD
|
||||
unsigned includeLevel;
|
||||
int documentEntity;
|
||||
int inEntityValue;
|
||||
#endif /* XML_DTD */
|
||||
# endif /* XML_DTD */
|
||||
} PROLOG_STATE;
|
||||
|
||||
void XmlPrologStateInit(PROLOG_STATE *state);
|
||||
#ifdef XML_DTD
|
||||
# ifdef XML_DTD
|
||||
void XmlPrologStateInitExternalEntity(PROLOG_STATE *state);
|
||||
#endif /* XML_DTD */
|
||||
# endif /* XML_DTD */
|
||||
|
||||
#define XmlTokenRole(state, tok, ptr, end, enc) \
|
||||
(((state)->handler)(state, tok, ptr, end, enc))
|
||||
# define XmlTokenRole(state, tok, ptr, end, enc) \
|
||||
(((state)->handler)(state, tok, ptr, end, enc))
|
||||
|
||||
#ifdef __cplusplus
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
|
||||
#endif /* not XmlRole_INCLUDED */
|
||||
|
||||
+2
-2
@@ -1398,7 +1398,7 @@ unknown_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
|
||||
}
|
||||
|
||||
ENCODING *
|
||||
XmlInitUnknownEncoding(void *mem, int *table, CONVERTER convert,
|
||||
XmlInitUnknownEncoding(void *mem, const int *table, CONVERTER convert,
|
||||
void *userData) {
|
||||
int i;
|
||||
struct unknown_encoding *e = (struct unknown_encoding *)mem;
|
||||
@@ -1661,7 +1661,7 @@ initScan(const ENCODING *const *encodingTable, const INIT_ENCODING *enc,
|
||||
# undef ns
|
||||
|
||||
ENCODING *
|
||||
XmlInitUnknownEncodingNS(void *mem, int *table, CONVERTER convert,
|
||||
XmlInitUnknownEncodingNS(void *mem, const int *table, CONVERTER convert,
|
||||
void *userData) {
|
||||
ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData);
|
||||
if (enc)
|
||||
|
||||
+113
-113
@@ -35,113 +35,113 @@
|
||||
*/
|
||||
|
||||
#ifndef XmlTok_INCLUDED
|
||||
#define XmlTok_INCLUDED 1
|
||||
# define XmlTok_INCLUDED 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
# endif
|
||||
|
||||
/* The following token may be returned by XmlContentTok */
|
||||
#define XML_TOK_TRAILING_RSQB \
|
||||
-5 /* ] or ]] at the end of the scan; might be \
|
||||
start of illegal ]]> sequence */
|
||||
# define XML_TOK_TRAILING_RSQB \
|
||||
-5 /* ] or ]] at the end of the scan; might be \
|
||||
start of illegal ]]> sequence */
|
||||
/* The following tokens may be returned by both XmlPrologTok and
|
||||
XmlContentTok.
|
||||
*/
|
||||
#define XML_TOK_NONE -4 /* The string to be scanned is empty */
|
||||
#define XML_TOK_TRAILING_CR \
|
||||
-3 /* A CR at the end of the scan; \
|
||||
might be part of CRLF sequence */
|
||||
#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */
|
||||
#define XML_TOK_PARTIAL -1 /* only part of a token */
|
||||
#define XML_TOK_INVALID 0
|
||||
# define XML_TOK_NONE -4 /* The string to be scanned is empty */
|
||||
# define XML_TOK_TRAILING_CR \
|
||||
-3 /* A CR at the end of the scan; \
|
||||
might be part of CRLF sequence */
|
||||
# define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */
|
||||
# define XML_TOK_PARTIAL -1 /* only part of a token */
|
||||
# define XML_TOK_INVALID 0
|
||||
|
||||
/* The following tokens are returned by XmlContentTok; some are also
|
||||
returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok.
|
||||
*/
|
||||
#define XML_TOK_START_TAG_WITH_ATTS 1
|
||||
#define XML_TOK_START_TAG_NO_ATTS 2
|
||||
#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */
|
||||
#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4
|
||||
#define XML_TOK_END_TAG 5
|
||||
#define XML_TOK_DATA_CHARS 6
|
||||
#define XML_TOK_DATA_NEWLINE 7
|
||||
#define XML_TOK_CDATA_SECT_OPEN 8
|
||||
#define XML_TOK_ENTITY_REF 9
|
||||
#define XML_TOK_CHAR_REF 10 /* numeric character reference */
|
||||
# define XML_TOK_START_TAG_WITH_ATTS 1
|
||||
# define XML_TOK_START_TAG_NO_ATTS 2
|
||||
# define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */
|
||||
# define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4
|
||||
# define XML_TOK_END_TAG 5
|
||||
# define XML_TOK_DATA_CHARS 6
|
||||
# define XML_TOK_DATA_NEWLINE 7
|
||||
# define XML_TOK_CDATA_SECT_OPEN 8
|
||||
# define XML_TOK_ENTITY_REF 9
|
||||
# define XML_TOK_CHAR_REF 10 /* numeric character reference */
|
||||
|
||||
/* The following tokens may be returned by both XmlPrologTok and
|
||||
XmlContentTok.
|
||||
*/
|
||||
#define XML_TOK_PI 11 /* processing instruction */
|
||||
#define XML_TOK_XML_DECL 12 /* XML decl or text decl */
|
||||
#define XML_TOK_COMMENT 13
|
||||
#define XML_TOK_BOM 14 /* Byte order mark */
|
||||
# define XML_TOK_PI 11 /* processing instruction */
|
||||
# define XML_TOK_XML_DECL 12 /* XML decl or text decl */
|
||||
# define XML_TOK_COMMENT 13
|
||||
# define XML_TOK_BOM 14 /* Byte order mark */
|
||||
|
||||
/* The following tokens are returned only by XmlPrologTok */
|
||||
#define XML_TOK_PROLOG_S 15
|
||||
#define XML_TOK_DECL_OPEN 16 /* <!foo */
|
||||
#define XML_TOK_DECL_CLOSE 17 /* > */
|
||||
#define XML_TOK_NAME 18
|
||||
#define XML_TOK_NMTOKEN 19
|
||||
#define XML_TOK_POUND_NAME 20 /* #name */
|
||||
#define XML_TOK_OR 21 /* | */
|
||||
#define XML_TOK_PERCENT 22
|
||||
#define XML_TOK_OPEN_PAREN 23
|
||||
#define XML_TOK_CLOSE_PAREN 24
|
||||
#define XML_TOK_OPEN_BRACKET 25
|
||||
#define XML_TOK_CLOSE_BRACKET 26
|
||||
#define XML_TOK_LITERAL 27
|
||||
#define XML_TOK_PARAM_ENTITY_REF 28
|
||||
#define XML_TOK_INSTANCE_START 29
|
||||
# define XML_TOK_PROLOG_S 15
|
||||
# define XML_TOK_DECL_OPEN 16 /* <!foo */
|
||||
# define XML_TOK_DECL_CLOSE 17 /* > */
|
||||
# define XML_TOK_NAME 18
|
||||
# define XML_TOK_NMTOKEN 19
|
||||
# define XML_TOK_POUND_NAME 20 /* #name */
|
||||
# define XML_TOK_OR 21 /* | */
|
||||
# define XML_TOK_PERCENT 22
|
||||
# define XML_TOK_OPEN_PAREN 23
|
||||
# define XML_TOK_CLOSE_PAREN 24
|
||||
# define XML_TOK_OPEN_BRACKET 25
|
||||
# define XML_TOK_CLOSE_BRACKET 26
|
||||
# define XML_TOK_LITERAL 27
|
||||
# define XML_TOK_PARAM_ENTITY_REF 28
|
||||
# define XML_TOK_INSTANCE_START 29
|
||||
|
||||
/* The following occur only in element type declarations */
|
||||
#define XML_TOK_NAME_QUESTION 30 /* name? */
|
||||
#define XML_TOK_NAME_ASTERISK 31 /* name* */
|
||||
#define XML_TOK_NAME_PLUS 32 /* name+ */
|
||||
#define XML_TOK_COND_SECT_OPEN 33 /* <![ */
|
||||
#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */
|
||||
#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */
|
||||
#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */
|
||||
#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */
|
||||
#define XML_TOK_COMMA 38
|
||||
# define XML_TOK_NAME_QUESTION 30 /* name? */
|
||||
# define XML_TOK_NAME_ASTERISK 31 /* name* */
|
||||
# define XML_TOK_NAME_PLUS 32 /* name+ */
|
||||
# define XML_TOK_COND_SECT_OPEN 33 /* <![ */
|
||||
# define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */
|
||||
# define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */
|
||||
# define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */
|
||||
# define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */
|
||||
# define XML_TOK_COMMA 38
|
||||
|
||||
/* The following token is returned only by XmlAttributeValueTok */
|
||||
#define XML_TOK_ATTRIBUTE_VALUE_S 39
|
||||
# define XML_TOK_ATTRIBUTE_VALUE_S 39
|
||||
|
||||
/* The following token is returned only by XmlCdataSectionTok */
|
||||
#define XML_TOK_CDATA_SECT_CLOSE 40
|
||||
# define XML_TOK_CDATA_SECT_CLOSE 40
|
||||
|
||||
/* With namespace processing this is returned by XmlPrologTok for a
|
||||
name with a colon.
|
||||
*/
|
||||
#define XML_TOK_PREFIXED_NAME 41
|
||||
# define XML_TOK_PREFIXED_NAME 41
|
||||
|
||||
#ifdef XML_DTD
|
||||
# define XML_TOK_IGNORE_SECT 42
|
||||
#endif /* XML_DTD */
|
||||
# ifdef XML_DTD
|
||||
# define XML_TOK_IGNORE_SECT 42
|
||||
# endif /* XML_DTD */
|
||||
|
||||
#ifdef XML_DTD
|
||||
# define XML_N_STATES 4
|
||||
#else /* not XML_DTD */
|
||||
# define XML_N_STATES 3
|
||||
#endif /* not XML_DTD */
|
||||
# ifdef XML_DTD
|
||||
# define XML_N_STATES 4
|
||||
# else /* not XML_DTD */
|
||||
# define XML_N_STATES 3
|
||||
# endif /* not XML_DTD */
|
||||
|
||||
#define XML_PROLOG_STATE 0
|
||||
#define XML_CONTENT_STATE 1
|
||||
#define XML_CDATA_SECTION_STATE 2
|
||||
#ifdef XML_DTD
|
||||
# define XML_IGNORE_SECTION_STATE 3
|
||||
#endif /* XML_DTD */
|
||||
# define XML_PROLOG_STATE 0
|
||||
# define XML_CONTENT_STATE 1
|
||||
# define XML_CDATA_SECTION_STATE 2
|
||||
# ifdef XML_DTD
|
||||
# define XML_IGNORE_SECTION_STATE 3
|
||||
# endif /* XML_DTD */
|
||||
|
||||
#define XML_N_LITERAL_TYPES 2
|
||||
#define XML_ATTRIBUTE_VALUE_LITERAL 0
|
||||
#define XML_ENTITY_VALUE_LITERAL 1
|
||||
# define XML_N_LITERAL_TYPES 2
|
||||
# define XML_ATTRIBUTE_VALUE_LITERAL 0
|
||||
# define XML_ENTITY_VALUE_LITERAL 1
|
||||
|
||||
/* The size of the buffer passed to XmlUtf8Encode must be at least this. */
|
||||
#define XML_UTF8_ENCODE_MAX 4
|
||||
# define XML_UTF8_ENCODE_MAX 4
|
||||
/* The size of the buffer passed to XmlUtf16Encode must be at least this. */
|
||||
#define XML_UTF16_ENCODE_MAX 2
|
||||
# define XML_UTF16_ENCODE_MAX 2
|
||||
|
||||
typedef struct position {
|
||||
/* first line and first column are 0 not 1 */
|
||||
@@ -220,63 +220,63 @@ struct encoding {
|
||||
the prolog outside literals, comments and processing instructions.
|
||||
*/
|
||||
|
||||
#define XmlTok(enc, state, ptr, end, nextTokPtr) \
|
||||
(((enc)->scanners[state])(enc, ptr, end, nextTokPtr))
|
||||
# define XmlTok(enc, state, ptr, end, nextTokPtr) \
|
||||
(((enc)->scanners[state])(enc, ptr, end, nextTokPtr))
|
||||
|
||||
#define XmlPrologTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr)
|
||||
# define XmlPrologTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr)
|
||||
|
||||
#define XmlContentTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr)
|
||||
# define XmlContentTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr)
|
||||
|
||||
#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
|
||||
# define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
|
||||
|
||||
#ifdef XML_DTD
|
||||
# ifdef XML_DTD
|
||||
|
||||
# define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr)
|
||||
# define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr)
|
||||
|
||||
#endif /* XML_DTD */
|
||||
# endif /* XML_DTD */
|
||||
|
||||
/* This is used for performing a 2nd-level tokenization on the content
|
||||
of a literal that has already been returned by XmlTok.
|
||||
*/
|
||||
#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \
|
||||
(((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr))
|
||||
# define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \
|
||||
(((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr))
|
||||
|
||||
#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr)
|
||||
# define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr)
|
||||
|
||||
#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr)
|
||||
# define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr)
|
||||
|
||||
#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \
|
||||
(((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2))
|
||||
# define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \
|
||||
(((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2))
|
||||
|
||||
#define XmlNameLength(enc, ptr) (((enc)->nameLength)(enc, ptr))
|
||||
# define XmlNameLength(enc, ptr) (((enc)->nameLength)(enc, ptr))
|
||||
|
||||
#define XmlSkipS(enc, ptr) (((enc)->skipS)(enc, ptr))
|
||||
# define XmlSkipS(enc, ptr) (((enc)->skipS)(enc, ptr))
|
||||
|
||||
#define XmlGetAttributes(enc, ptr, attsMax, atts) \
|
||||
(((enc)->getAtts)(enc, ptr, attsMax, atts))
|
||||
# define XmlGetAttributes(enc, ptr, attsMax, atts) \
|
||||
(((enc)->getAtts)(enc, ptr, attsMax, atts))
|
||||
|
||||
#define XmlCharRefNumber(enc, ptr) (((enc)->charRefNumber)(enc, ptr))
|
||||
# define XmlCharRefNumber(enc, ptr) (((enc)->charRefNumber)(enc, ptr))
|
||||
|
||||
#define XmlPredefinedEntityName(enc, ptr, end) \
|
||||
(((enc)->predefinedEntityName)(enc, ptr, end))
|
||||
# define XmlPredefinedEntityName(enc, ptr, end) \
|
||||
(((enc)->predefinedEntityName)(enc, ptr, end))
|
||||
|
||||
#define XmlUpdatePosition(enc, ptr, end, pos) \
|
||||
(((enc)->updatePosition)(enc, ptr, end, pos))
|
||||
# define XmlUpdatePosition(enc, ptr, end, pos) \
|
||||
(((enc)->updatePosition)(enc, ptr, end, pos))
|
||||
|
||||
#define XmlIsPublicId(enc, ptr, end, badPtr) \
|
||||
(((enc)->isPublicId)(enc, ptr, end, badPtr))
|
||||
# define XmlIsPublicId(enc, ptr, end, badPtr) \
|
||||
(((enc)->isPublicId)(enc, ptr, end, badPtr))
|
||||
|
||||
#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \
|
||||
(((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim))
|
||||
# define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \
|
||||
(((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim))
|
||||
|
||||
#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \
|
||||
(((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim))
|
||||
# define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \
|
||||
(((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim))
|
||||
|
||||
typedef struct {
|
||||
ENCODING initEnc;
|
||||
@@ -299,7 +299,7 @@ int XmlSizeOfUnknownEncoding(void);
|
||||
|
||||
typedef int(XMLCALL *CONVERTER)(void *userData, const char *p);
|
||||
|
||||
ENCODING *XmlInitUnknownEncoding(void *mem, int *table, CONVERTER convert,
|
||||
ENCODING *XmlInitUnknownEncoding(void *mem, const int *table, CONVERTER convert,
|
||||
void *userData);
|
||||
|
||||
int XmlParseXmlDeclNS(int isGeneralTextEntity, const ENCODING *enc,
|
||||
@@ -312,10 +312,10 @@ int XmlInitEncodingNS(INIT_ENCODING *p, const ENCODING **encPtr,
|
||||
const char *name);
|
||||
const ENCODING *XmlGetUtf8InternalEncodingNS(void);
|
||||
const ENCODING *XmlGetUtf16InternalEncodingNS(void);
|
||||
ENCODING *XmlInitUnknownEncodingNS(void *mem, int *table, CONVERTER convert,
|
||||
void *userData);
|
||||
#ifdef __cplusplus
|
||||
ENCODING *XmlInitUnknownEncodingNS(void *mem, const int *table,
|
||||
CONVERTER convert, void *userData);
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
|
||||
#endif /* not XmlTok_INCLUDED */
|
||||
|
||||
Reference in New Issue
Block a user