Skip to content

Commit f1a47e7

Browse files
gh-149698: Update bundled expat to 2.8.1 (GH-149699)
1 parent 50476a7 commit f1a47e7

5 files changed

Lines changed: 44 additions & 18 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Update bundled `libexpat <https://libexpat.github.io/>`_ to version 2.8.1
2+
for the fix for :cve:`2026-45186`.

Misc/sbom.spdx.json

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/expat/expat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,7 @@ XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled);
10941094
*/
10951095
# define XML_MAJOR_VERSION 2
10961096
# define XML_MINOR_VERSION 8
1097-
# define XML_MICRO_VERSION 0
1097+
# define XML_MICRO_VERSION 1
10981098

10991099
# ifdef __cplusplus
11001100
}

Modules/expat/refresh.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ fi
1212

1313
# Update this when updating to a new version after verifying that the changes
1414
# the update brings in are good. These values are used for verifying the SBOM, too.
15-
expected_libexpat_tag="R_2_8_0"
16-
expected_libexpat_version="2.8.0"
17-
expected_libexpat_sha256="c7cec5f60ea3a42e7780781c6745255c19aa3dbfeeae58646b7132f88dc24780"
15+
expected_libexpat_tag="R_2_8_1"
16+
expected_libexpat_version="2.8.1"
17+
expected_libexpat_sha256="a52eb72108be160e190b5cafa5bba8663f1313f2013e26060d1c18e26e31067b"
1818

1919
expat_dir="$(realpath "$(dirname -- "${BASH_SOURCE[0]}")")"
2020
cd ${expat_dir}

Modules/expat/xmlparse.c

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* a5d18f6a50f536615ac1c70304f87d94f99cc85a86b502188952440610ccf0f8 (2.8.0+)
1+
/* 75ef4224f81c052e9e5aeea2ac7de75357d2169ff9908e39edc08b9dc3052513 (2.8.1+)
22
__ __ _
33
___\ \/ /_ __ __ _| |_
44
/ _ \\ /| '_ \ / _` | __|
@@ -387,6 +387,7 @@ typedef struct {
387387
int nDefaultAtts;
388388
int allocDefaultAtts;
389389
DEFAULT_ATTRIBUTE *defaultAtts;
390+
HASH_TABLE defaultAttsNames;
390391
} ELEMENT_TYPE;
391392

392393
typedef struct {
@@ -3769,6 +3770,8 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
37693770
sizeof(ELEMENT_TYPE));
37703771
if (! elementType)
37713772
return XML_ERROR_NO_MEMORY;
3773+
if (! elementType->defaultAttsNames.parser)
3774+
hashTableInit(&(elementType->defaultAttsNames), parser);
37723775
if (parser->m_ns && ! setElementTypePrefix(parser, elementType))
37733776
return XML_ERROR_NO_MEMORY;
37743777
}
@@ -7102,10 +7105,10 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
71027105
if (value || isId) {
71037106
/* The handling of default attributes gets messed up if we have
71047107
a default which duplicates a non-default. */
7105-
int i;
7106-
for (i = 0; i < type->nDefaultAtts; i++)
7107-
if (attId == type->defaultAtts[i].id)
7108-
return 1;
7108+
NAMED *const nameFound
7109+
= (NAMED *)lookup(parser, &(type->defaultAttsNames), attId->name, 0);
7110+
if (nameFound)
7111+
return 1;
71097112
if (isId && ! type->idAtt && ! attId->xmlns)
71107113
type->idAtt = attId;
71117114
}
@@ -7152,6 +7155,12 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
71527155
att->isCdata = isCdata;
71537156
if (! isCdata)
71547157
attId->maybeTokenized = XML_TRUE;
7158+
7159+
NAMED *const nameAddedOrFound = (NAMED *)lookup(
7160+
parser, &(type->defaultAttsNames), attId->name, sizeof(NAMED));
7161+
if (! nameAddedOrFound)
7162+
return 0;
7163+
71557164
type->nDefaultAtts += 1;
71567165
return 1;
71577166
}
@@ -7477,6 +7486,7 @@ dtdReset(DTD *p, XML_Parser parser) {
74777486
ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
74787487
if (! e)
74797488
break;
7489+
hashTableDestroy(&(e->defaultAttsNames));
74807490
if (e->allocDefaultAtts != 0)
74817491
FREE(parser, e->defaultAtts);
74827492
}
@@ -7518,6 +7528,7 @@ dtdDestroy(DTD *p, XML_Bool isDocEntity, XML_Parser parser) {
75187528
ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
75197529
if (! e)
75207530
break;
7531+
hashTableDestroy(&(e->defaultAttsNames));
75217532
if (e->allocDefaultAtts != 0)
75227533
FREE(parser, e->defaultAtts);
75237534
}
@@ -7611,6 +7622,10 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
76117622
sizeof(ELEMENT_TYPE));
76127623
if (! newE)
76137624
return 0;
7625+
7626+
if (! newE->defaultAttsNames.parser)
7627+
hashTableInit(&(newE->defaultAttsNames), parser);
7628+
76147629
if (oldE->nDefaultAtts) {
76157630
/* Detect and prevent integer overflow.
76167631
* The preprocessor guard addresses the "always false" warning
@@ -7635,8 +7650,9 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
76357650
newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
76367651
oldE->prefix->name, 0);
76377652
for (i = 0; i < newE->nDefaultAtts; i++) {
7653+
const XML_Char *const attributeName = oldE->defaultAtts[i].id->name;
76387654
newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(
7639-
oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
7655+
oldParser, &(newDtd->attributeIds), attributeName, 0);
76407656
newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
76417657
if (oldE->defaultAtts[i].value) {
76427658
newE->defaultAtts[i].value
@@ -7645,6 +7661,12 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
76457661
return 0;
76467662
} else
76477663
newE->defaultAtts[i].value = NULL;
7664+
7665+
NAMED *const nameAddedOrFound = (NAMED *)lookup(
7666+
parser, &(newE->defaultAttsNames), attributeName, sizeof(NAMED));
7667+
if (! nameAddedOrFound) {
7668+
return 0;
7669+
}
76487670
}
76497671
}
76507672

@@ -8391,6 +8413,8 @@ getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr,
83918413
sizeof(ELEMENT_TYPE));
83928414
if (! ret)
83938415
return NULL;
8416+
if (! ret->defaultAttsNames.parser)
8417+
hashTableInit(&(ret->defaultAttsNames), getRootParserOf(parser, NULL));
83948418
if (ret->name != name)
83958419
poolDiscard(&dtd->pool);
83968420
else {

0 commit comments

Comments
 (0)