Skip to content

Commit 46db25f

Browse files
committed
Merge commit '60d3056c97067e6cb2125284878ed7c99c90ed81'
2 parents f2f90ca + 60d3056 commit 46db25f

19 files changed

+169
-57
lines changed

NEWS

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,32 @@
11
NEWS file for libxml2
22

3+
v2.13.4: Sep 18 2024
4+
5+
### Regressions
6+
7+
- parser: Make unsupported encodings an error in declarations
8+
- io: don't set the executable bit when creating files (triallax)
9+
- xmlcatalog: Improved fix for #699
10+
- Revert "catalog: Fetch XML catalog before dumping"
11+
- io: Add missing calls to xmlInitParser
12+
- tree: Restore return value of xmlNodeListGetString with NULL list
13+
- parser: Fix error handling after reaching limit
14+
- parser: Make xmlParseChunk return an error if parser was stopped
15+
16+
### Bug fixes
17+
18+
- python: Fix SAX driver with character streams
19+
20+
### Improvements
21+
22+
- xpath: Make recursion check work with xmlXPathCompile
23+
- parser: Report at least one fatal error
24+
25+
### Portability
26+
27+
- include: Check whether _MSC_VER is defined
28+
29+
330
v2.13.3: Jul 24 2024
431

532
### Security

catalog.c

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@
5959
#define XML_SGML_DEFAULT_CATALOG "file://" SYSCONFDIR "/sgml/catalog"
6060
#endif
6161

62+
static xmlChar *xmlCatalogNormalizePublic(const xmlChar *pubID);
63+
static int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename);
64+
6265
/************************************************************************
6366
* *
6467
* Types, all private *
@@ -173,21 +176,6 @@ static xmlRMutexPtr xmlCatalogMutex = NULL;
173176
*/
174177
static int xmlCatalogInitialized = 0;
175178

176-
/************************************************************************
177-
* *
178-
* Forward declarations *
179-
* *
180-
************************************************************************/
181-
182-
static xmlChar *
183-
xmlCatalogNormalizePublic(const xmlChar *pubID);
184-
185-
static int
186-
xmlExpandCatalog(xmlCatalogPtr catal, const char *filename);
187-
188-
static int
189-
xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal);
190-
191179
/************************************************************************
192180
* *
193181
* Catalog error handlers *
@@ -538,9 +526,6 @@ static void xmlDumpXMLCatalogNode(xmlCatalogEntryPtr catal, xmlNodePtr catalog,
538526
case XML_CATA_BROKEN_CATALOG:
539527
case XML_CATA_CATALOG:
540528
if (cur == catal) {
541-
if (cur->children == NULL) {
542-
xmlFetchXMLCatalogFile(cur);
543-
}
544529
cur = cur->children;
545530
continue;
546531
}

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ AC_PREREQ([2.63])
33

44
m4_define([MAJOR_VERSION], 2)
55
m4_define([MINOR_VERSION], 13)
6-
m4_define([MICRO_VERSION], 3)
6+
m4_define([MICRO_VERSION], 4)
77

88
AC_INIT([libxml2],[MAJOR_VERSION.MINOR_VERSION.MICRO_VERSION])
99
AC_CONFIG_SRCDIR([entities.c])

fuzz/api.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2522,30 +2522,38 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
25222522
}
25232523

25242524
case OP_XML_NODE_LIST_GET_STRING: {
2525+
xmlDocPtr doc;
2526+
xmlNodePtr list;
25252527
xmlChar *string;
25262528

25272529
startOp("xmlNodeListGetString");
25282530
incStrIdx();
2531+
doc = getDoc(0);
2532+
list = getNode(1);
25292533
string = xmlNodeListGetString(
2530-
getDoc(0),
2531-
getNode(1),
2534+
doc,
2535+
list,
25322536
getInt(0));
2533-
oomReport = (string == NULL);
2537+
oomReport = (list != NULL && string == NULL);
25342538
moveStr(0, string);
25352539
endOp();
25362540
break;
25372541
}
25382542

25392543
case OP_XML_NODE_LIST_GET_RAW_STRING: {
2544+
xmlDocPtr doc;
2545+
xmlNodePtr list;
25402546
xmlChar *string;
25412547

25422548
startOp("xmlNodeListGetRawString");
25432549
incStrIdx();
2550+
doc = getDoc(0);
2551+
list = getNode(1);
25442552
string = xmlNodeListGetRawString(
2545-
getDoc(0),
2546-
getNode(1),
2553+
doc,
2554+
list,
25472555
getInt(0));
2548-
oomReport = (string == NULL);
2556+
oomReport = (list != NULL && string == NULL);
25492557
moveStr(0, string);
25502558
endOp();
25512559
break;

include/libxml/xmlexports.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
#define XML_DEPRECATED
6868
#elif __GNUC__ * 100 + __GNUC_MINOR__ >= 301
6969
#define XML_DEPRECATED __attribute__((deprecated))
70-
#elif _MSC_VER >= 1400
70+
#elif defined(_MSC_VER) && _MSC_VER >= 1400
7171
/* Available since Visual Studio 2005 */
7272
#define XML_DEPRECATED __declspec(deprecated)
7373
#else
@@ -100,7 +100,7 @@
100100
#define XML_POP_WARNINGS \
101101
_Pragma("GCC diagnostic pop")
102102

103-
#elif _MSC_VER >= 1400
103+
#elif defined(_MSC_VER) && _MSC_VER >= 1400
104104

105105
#define XML_IGNORE_FPTR_CAST_WARNINGS __pragma(warning(push))
106106
#define XML_POP_WARNINGS __pragma(warning(pop))

meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
project(
22
'libxml2',
33
'c',
4-
version: '2.13.3',
4+
version: '2.13.4',
55
license: 'MIT',
66
default_options: ['buildtype=debug', 'warning_level=3'],
77
meson_version: '>= 0.61',

parser.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11575,7 +11575,7 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
1157511575
xmlHaltParser(ctxt);
1157611576
}
1157711577

11578-
if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
11578+
if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX != 0))
1157911579
return(ctxt->errNo);
1158011580

1158111581
if ((end_in_lf == 1) && (ctxt->input != NULL) &&

parserInternals.c

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,13 @@ xmlCtxtVErr(xmlParserCtxtPtr ctxt, xmlNodePtr node, xmlErrorDomain domain,
253253

254254
if (level == XML_ERR_WARNING) {
255255
if (ctxt->nbWarnings >= XML_MAX_ERRORS)
256-
return;
256+
goto done;
257257
ctxt->nbWarnings += 1;
258258
} else {
259-
if (ctxt->nbErrors >= XML_MAX_ERRORS)
260-
return;
259+
/* Report at least one fatal error. */
260+
if ((ctxt->nbErrors >= XML_MAX_ERRORS) &&
261+
((level < XML_ERR_FATAL) || (ctxt->wellFormed == 0)))
262+
goto done;
261263
ctxt->nbErrors += 1;
262264
}
263265

@@ -308,6 +310,7 @@ xmlCtxtVErr(xmlParserCtxtPtr ctxt, xmlNodePtr node, xmlErrorDomain domain,
308310
return;
309311
}
310312

313+
done:
311314
if (level >= XML_ERR_ERROR)
312315
ctxt->errNo = code;
313316
if (level == XML_ERR_FATAL) {
@@ -361,20 +364,14 @@ void
361364
xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors code, const char *info)
362365
{
363366
const char *errmsg;
364-
xmlErrorLevel level;
365-
366-
if (code == XML_ERR_UNSUPPORTED_ENCODING)
367-
level = XML_ERR_WARNING;
368-
else
369-
level = XML_ERR_FATAL;
370367

371368
errmsg = xmlErrString(code);
372369

373370
if (info == NULL) {
374-
xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, code, level,
371+
xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, code, XML_ERR_FATAL,
375372
NULL, NULL, NULL, 0, "%s\n", errmsg);
376373
} else {
377-
xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, code, level,
374+
xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, code, XML_ERR_FATAL,
378375
(const xmlChar *) info, NULL, NULL, 0,
379376
"%s: %s\n", errmsg, info);
380377
}
@@ -1119,7 +1116,11 @@ xmlSwitchInputEncodingName(xmlParserCtxtPtr ctxt, xmlParserInputPtr input,
11191116
return(-1);
11201117

11211118
res = xmlOpenCharEncodingHandler(encoding, /* output */ 0, &handler);
1122-
if (res != 0) {
1119+
if (res == XML_ERR_UNSUPPORTED_ENCODING) {
1120+
xmlWarningMsg(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
1121+
"Unsupported encoding: %s\n", BAD_CAST encoding, NULL);
1122+
return(-1);
1123+
} else if (res != XML_ERR_OK) {
11231124
xmlFatalErr(ctxt, res, encoding);
11241125
return(-1);
11251126
}
@@ -1380,7 +1381,28 @@ void
13801381
xmlSetDeclaredEncoding(xmlParserCtxtPtr ctxt, xmlChar *encoding) {
13811382
if (((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) &&
13821383
((ctxt->options & XML_PARSE_IGNORE_ENC) == 0)) {
1383-
xmlSwitchEncodingName(ctxt, (const char *) encoding);
1384+
xmlCharEncodingHandlerPtr handler;
1385+
int res;
1386+
1387+
/*
1388+
* xmlSwitchInputEncodingName treats unsupported encodings as
1389+
* warnings, but we want it to be an error in an encoding
1390+
* declaration.
1391+
*/
1392+
res = xmlOpenCharEncodingHandler((const char *) encoding,
1393+
/* output */ 0, &handler);
1394+
if (res != XML_ERR_OK) {
1395+
xmlFatalErr(ctxt, res, (const char *) encoding);
1396+
xmlFree(encoding);
1397+
return;
1398+
}
1399+
1400+
res = xmlSwitchInputEncoding(ctxt, ctxt->input, handler);
1401+
if (res != XML_ERR_OK) {
1402+
xmlFree(encoding);
1403+
return;
1404+
}
1405+
13841406
ctxt->input->flags |= XML_INPUT_USES_ENC_DECL;
13851407
} else if (ctxt->input->flags & XML_INPUT_AUTO_ENCODING) {
13861408
static const char *allowedUTF8[] = {

python/drv_libxml2.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,10 @@ def parse(self, source):
146146
reader = libxml2.newTextReaderFilename(source)
147147
else:
148148
source = saxutils.prepare_input_source(source)
149-
input = libxml2.inputBuffer(source.getByteStream())
149+
stream = source.getCharacterStream()
150+
if stream is None:
151+
stream = source.getByteStream()
152+
input = libxml2.inputBuffer(stream)
150153
reader = input.newTextReader(source.getSystemId())
151154
reader.SetErrorHandler(self._errorHandler,None)
152155
# configure reader
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
./test/errors/unsupported-encoding.xml:1: parser error : Unsupported encoding: unsupported-encoding
2+
<?xml version="1.0" encoding="unsupported-encoding"?>
3+
^
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
./test/errors/unsupported-encoding.xml:1: parser error : Unsupported encoding: unsupported-encoding
2+
<?xml version="1.0" encoding="unsupported-encoding"?>
3+
^
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
./test/errors/unsupported-encoding.xml:1: parser error : Unsupported encoding: unsupported-encoding
2+
<?xml version="1.0" encoding="unsupported-encoding"?>
3+
^
4+
./test/errors/unsupported-encoding.xml : failed to parse

test/errors/unsupported-encoding.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="unsupported-encoding"?>
2+
<doc/>

tree.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,11 +1594,11 @@ xmlNodeListGetStringInternal(xmlDocPtr doc, const xmlNode *node, int escMode) {
15941594
/**
15951595
* xmlNodeListGetString:
15961596
* @doc: a document (optional)
1597-
* @list: a node list of attribute children (optional)
1597+
* @list: a node list of attribute children
15981598
* @inLine: whether entity references are substituted
15991599
*
16001600
* Serializes attribute children (text and entity reference nodes)
1601-
* into a string. An empty list produces an empty string.
1601+
* into a string.
16021602
*
16031603
* If @inLine is true, entity references will be substituted.
16041604
* Otherwise, entity references will be kept and special characters
@@ -1612,11 +1612,14 @@ xmlNodeListGetString(xmlDocPtr doc, const xmlNode *list, int inLine)
16121612
{
16131613
int escMode;
16141614

1615+
/* backward compatibility */
1616+
if (list == NULL)
1617+
return(NULL);
1618+
16151619
if (inLine) {
16161620
escMode = 0;
16171621
} else {
1618-
if ((list != NULL) &&
1619-
(list->parent != NULL) &&
1622+
if ((list->parent != NULL) &&
16201623
(list->parent->type == XML_ATTRIBUTE_NODE))
16211624
escMode = 2;
16221625
else
@@ -1630,11 +1633,11 @@ xmlNodeListGetString(xmlDocPtr doc, const xmlNode *list, int inLine)
16301633
/**
16311634
* xmlNodeListGetRawString:
16321635
* @doc: a document (optional)
1633-
* @list: a node list of attribute children (optional)
1636+
* @list: a node list of attribute children
16341637
* @inLine: whether entity references are substituted
16351638
*
16361639
* Serializes attribute children (text and entity reference nodes)
1637-
* into a string. An empty list produces an empty string.
1640+
* into a string.
16381641
*
16391642
* If @inLine is true, entity references will be substituted.
16401643
* Otherwise, entity references will be kept and special characters
@@ -1646,6 +1649,11 @@ xmlChar *
16461649
xmlNodeListGetRawString(const xmlDoc *doc, const xmlNode *list, int inLine)
16471650
{
16481651
int escMode = inLine ? 0 : 3;
1652+
1653+
/* backward compatibility */
1654+
if (list == NULL)
1655+
return(NULL);
1656+
16491657
return(xmlNodeListGetStringInternal((xmlDocPtr) doc, list, escMode));
16501658
}
16511659
#endif /* LIBXML_TREE_ENABLED */

valid.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6224,7 +6224,10 @@ xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr root) {
62246224
if (elem->type == XML_ELEMENT_NODE) {
62256225
attr = elem->properties;
62266226
while (attr != NULL) {
6227-
value = xmlNodeListGetString(doc, attr->children, 0);
6227+
if (attr->children == NULL)
6228+
value = xmlStrdup(BAD_CAST "");
6229+
else
6230+
value = xmlNodeListGetString(doc, attr->children, 0);
62286231
if (value == NULL) {
62296232
xmlVErrMemory(ctxt);
62306233
ret = 0;

0 commit comments

Comments
 (0)