Hi, bookworm's expat (2.5.0-1+deb12u5) is still open for four CVEs that 2.10.0-1 fixed in unstable: CVE-2026-113351 (<postponed>), CVE-2026-115506, CVE-2026-117610 and CVE-2026-118370. expat isn't in dla-needed.txt, and the debian/bookworm branch in lts-team/packages/expat is still at deb12u5, so I prepared backports of three of them on top of deb12u5. The debdiff is attached; please use as much or as little of it as is useful. I'm not on the LTS team and can't upload.
CVE-2026-117610 (upstream PR #1444) The library change applies unchanged. The bug does affect deb12u5: I ran upstream's test scenario (external entity subparser, an empty non-final XML_Parse(), then a document containing a PI) as a small standalone program under ASan+UBSan. On deb12u5, reportProcessingInstruction() reads enc->minBytesPerChar from uninitialized heap memory (UBSan: "signed integer overflow: -1094795586 * 2", i.e. ASan's 0xbe fill), deterministically. The same program SEGVs on upstream R_2_9_0. With the patch it runs clean and the handler gets target="target", data="data". The upstream regression test is ported into tests/runtests.c. Note that without sanitizers the ported test happened to pass on deb12u5 as well, since the uninitialized memory held usable values. CVE-2026-113351 (upstream PR #1431) The CVE text says 2.7.2 and later, but deb12u4 backported the 2.7.2 allocation tracker (CVE-2025-59375), so bookworm is affected, as the tracker says. I ported the two upstream tests: both fail on deb12u5 (after XML_ParserReset() the amplification limit set by the application is lost, and after one large document a small one is refused with XML_ERROR_NO_MEMORY), and both pass with the patch. The 2.5.0 differences (XmlBigCount, XML_DTD guard) are noted in the patch header. CVE-2026-118370 (upstream PR #1450) Hand-ported, because storeAtts() in 2.5.0 shares one "int i" between several loops; the loops over attIndex get their own size_t counters. Not reproduced, since triggering it needs more than 2^31 attributes; the affected code is the same as upstream before the fix. Not included: - CVE-2026-115506 (PR #1433): this adds about 400 lines of new code that precompute entity expansion sizes, to cut the CPU time of a billion-laughs style DoS. I don't think it is a reasonable backport for 2.5.0, so I'm leaving that decision to you. - CVE-2025-66382: no upstream fix yet. Side finding: tests/runtests on deb12u5 fails 1 of 365 checks (test_nsalloc_realloc_attributes). I bisected the series to CVE-2025-59375-10.patch: the same upstream commit (cfce28e17167) also changed that test's expectation for XML_GE=1, but the backport didn't carry the test change over. debian/rules builds the tests but never runs them, which is presumably why it went unnoticed. The debdiff adds the test change as CVE-2025-59375-tests.patch. Testing: - All 74 patches apply to the orig tarball with no fuzz or offset, and dpkg-source -b builds the source package. - Built with upstream's CMake build and -DXML_GE=1 as in debian/rules (automake isn't available on my build host, so Debian's autotools build was NOT run; the CMake build needed XML_DTD/XML_NS set to 1 in the generated expat_config.h, because the earlier backports use "#if XML_DTD == 1"). - runtests and runtestspp: 368/368 with -O2, and 368/368 with ASan+UBSan+LSan with no sanitizer reports. Unpatched deb12u5 in the same setup: 364/365. - The library also compiles with -DXML_UNICODE (libexpatw) and adds no new compiler warnings. Regards, Sumit Verma
diff -urN old/debian/changelog new/debian/changelog --- old/debian/changelog 2026-10-21 18:34:41.000000000 -0400 +++ new/debian/changelog 2026-11-05 15:20:17.000000000 -0500 @@ -1,3 +1,19 @@ +expat (2.5.0-1+deb12u6) bookworm-security; urgency=medium + + * Non-maintainer upload. + * Backport upstream security fixes: + - CVE-2026-118370: Protect attIndex and nPrefixes in storeAtts from + signed integer overflow. + - CVE-2026-117610: Fix initial non-final empty subparser call with a + handler. + - CVE-2026-113351: Fix XML_ParserReset interaction with allocation + tracking and amplification accounting. + * Update test_nsalloc_realloc_attributes for the allocation tracking + added in 2.5.0-1+deb12u4 (CVE-2025-59375), as upstream did in the + same commit; tests/runtests failed 1 of 365 checks. + + -- Sumit Verma <[email protected]> Thu, 05 Nov 2026 15:20:17 -0500 + expat (2.5.0-1+deb12u5) bookworm-security; urgency=medium * Backport upstream security patches: diff -urN old/debian/patches/CVE-2025-59375-tests.patch new/debian/patches/CVE-2025-59375-tests.patch --- old/debian/patches/CVE-2025-59375-tests.patch 1969-12-31 19:00:00.000000000 -0500 +++ new/debian/patches/CVE-2025-59375-tests.patch 2026-11-05 15:13:18.000000000 -0500 @@ -0,0 +1,30 @@ +Description: Update test_nsalloc_realloc_attributes for allocation tracking + With the CVE-2025-59375 allocation tracking (XML_GE=1, as set in debian/rules), + expat_realloc relies on expat_malloc, so the first parse already succeeds when + reallocations fail. Upstream changed the expectation of this test in the same + commit; the 2.5.0-1+deb12u4 backport (CVE-2025-59375-10.patch) took the library change but + not this test change, so tests/runtests failed 1 of 365 checks. This is the + tests/nsalloc_tests.c hunk of the same upstream commit, ported to runtests.c + (its other test hunk, in test_buffer_can_grow_to_max, has no 2.5.0 counterpart). +Origin: backport, https://github.com/libexpat/libexpat/commit/cfce28e171676fe6f70d17b97ed8a59eaeb83f15 +Forwarded: not-needed +Last-Update: 2026-11-05 +--- +--- a/expat/tests/runtests.c ++++ b/expat/tests/runtests.c +@@ -11781,10 +11781,15 @@ + nsalloc_teardown(); + nsalloc_setup(); + } ++#if XML_GE == 1 ++ assert_true( ++ i == 0); // because expat_realloc relies on expat_malloc to some extent ++#else + if (i == 0) + fail("Parsing worked despite failing reallocations"); + else if (i == max_realloc_count) + fail("Parsing failed at max reallocation count"); ++#endif + } + END_TEST + diff -urN old/debian/patches/CVE-2026-113351.patch new/debian/patches/CVE-2026-113351.patch --- old/debian/patches/CVE-2026-113351.patch 1969-12-31 19:00:00.000000000 -0500 +++ new/debian/patches/CVE-2026-113351.patch 2026-11-05 15:18:31.000000000 -0500 @@ -0,0 +1,214 @@ +Description: Fix XML_ParserReset interaction with allocation tracking and accounting (CVE-2026-113351) + Backport of upstream PR #1431 to expat 2.5.0-1+deb12u5, whose CVE-2025-59375 + backport added the allocation tracker. After XML_ParserReset(), the tracker + kept counting memory still held from the previous document while the + billion-laughs byte counters restarted from zero, so after one large document + every allocation for the next document was refused (XML_ERROR_NO_MEMORY). + The tracker now measures relative to the bytes allocated at the last reset, + and the reset no longer discards amplification limits set by the application. + . + 2.5.0 differences: the tracker uses XmlBigCount and the accounting block in + parserInit() is guarded by XML_DTD; the two new tests are ported from + tests/acc_tests.c and tests/alloc_tests.c into tests/runtests.c, parsing in one + XML_Parse() call (upstream skips them for chunked parsing) and registering the + alloc tracker test in tc_misc, since tc_alloc installs a failing allocator. +Origin: backport, https://github.com/libexpat/libexpat/commit/a6cf8a6944b6 https://github.com/libexpat/libexpat/commit/8b722a1453b8 https://github.com/libexpat/libexpat/commit/c400537c2df3 https://github.com/libexpat/libexpat/commit/f74501d61e09 +Bug: https://github.com/libexpat/libexpat/pull/1431 +Bug-Debian: https://bugs.debian.org/1151840 +Last-Update: 2026-11-05 +--- +--- a/expat/lib/xmlparse.c ++++ b/expat/lib/xmlparse.c +@@ -453,6 +453,7 @@ + typedef struct MALLOC_TRACKER { + XmlBigCount bytesAllocated; + XmlBigCount peakBytesAllocated; // updated live only for debug level >=2 ++ XmlBigCount bytesAllocatedWhenLastReset; + unsigned long debugLevel; + float maximumAmplificationFactor; // >=1.0 + XmlBigCount activationThresholdBytes; +@@ -605,7 +606,8 @@ + const XML_Char *nameSep, DTD *dtd, + XML_Parser parentParser); + +-static void parserInit(XML_Parser parser, const XML_Char *encodingName); ++static void parserInit(XML_Parser parser, const XML_Char *encodingName, ++ XML_Bool isReset); + + #ifdef XML_DTD + static float accountingGetCurrentAmplification(XML_Parser rootParser); +@@ -803,11 +805,22 @@ + XmlBigCount newTotal = 0; + bool tolerable = true; + ++ // The idea is to subtract the amount of memory that was already ++ // allocated the last time that `XML_ParserReset` was called for ++ // this parser, the memory use of one document could skew the ++ // memory stats of the next document. ++ const XmlBigCount bytesAllocated ++ = (rootParser->m_alloc_tracker.bytesAllocatedWhenLastReset ++ > rootParser->m_alloc_tracker.bytesAllocated) ++ ? 0 ++ : (rootParser->m_alloc_tracker.bytesAllocated ++ - rootParser->m_alloc_tracker.bytesAllocatedWhenLastReset); ++ + // Detect integer overflow +- if ((XmlBigCount)-1 - rootParser->m_alloc_tracker.bytesAllocated < increase) { ++ if ((XmlBigCount)-1 - bytesAllocated < increase) { + tolerable = false; + } else { +- newTotal = rootParser->m_alloc_tracker.bytesAllocated + increase; ++ newTotal = bytesAllocated + increase; + + if (newTotal >= rootParser->m_alloc_tracker.activationThresholdBytes) { + assert(newTotal > 0); +@@ -1513,7 +1526,7 @@ + + poolInit(&parser->m_tempPool, parser); + poolInit(&parser->m_temp2Pool, parser); +- parserInit(parser, encodingName); ++ parserInit(parser, encodingName, /*isReset=*/XML_FALSE); + + if (encodingName && ! parser->m_protocolEncodingName) { + if (dtd) { +@@ -1540,7 +1553,7 @@ + } + + static void +-parserInit(XML_Parser parser, const XML_Char *encodingName) { ++parserInit(XML_Parser parser, const XML_Char *encodingName, XML_Bool isReset) { + parser->m_processor = prologInitProcessor; + XmlPrologStateInit(&parser->m_prologState); + if (encodingName != NULL) { +@@ -1619,15 +1632,24 @@ + parser->m_hash_secret_salt = 0; + + #ifdef XML_DTD +- memset(&parser->m_accounting, 0, sizeof(ACCOUNTING)); +- parser->m_accounting.debugLevel = getDebugLevel("EXPAT_ACCOUNTING_DEBUG", 0u); +- parser->m_accounting.maximumAmplificationFactor +- = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT; +- parser->m_accounting.activationThresholdBytes +- = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT; +- +- memset(&parser->m_entity_stats, 0, sizeof(ENTITY_STATS)); +- parser->m_entity_stats.debugLevel = getDebugLevel("EXPAT_ENTITY_DEBUG", 0u); ++ parser->m_accounting.countBytesDirect = 0; ++ parser->m_accounting.countBytesIndirect = 0; ++ if (! isReset) { ++ parser->m_accounting.debugLevel ++ = getDebugLevel("EXPAT_ACCOUNTING_DEBUG", 0u); ++ parser->m_accounting.maximumAmplificationFactor ++ = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT; ++ parser->m_accounting.activationThresholdBytes ++ = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT; ++ } ++ ++ parser->m_entity_stats.countEverOpened = 0; ++ parser->m_entity_stats.currentDepth = 0; ++ parser->m_entity_stats.maximumDepthSeen = 0; ++ if (! isReset) ++ parser->m_entity_stats.debugLevel = getDebugLevel("EXPAT_ENTITY_DEBUG", 0u); ++#else ++ UNUSED_P(isReset); + #endif + } + +@@ -1696,8 +1718,14 @@ + poolClear(&parser->m_temp2Pool); + FREE(parser, (void *)parser->m_protocolEncodingName); + parser->m_protocolEncodingName = NULL; +- parserInit(parser, encodingName); ++ parserInit(parser, encodingName, /*isReset=*/XML_TRUE); + dtdReset(parser->m_dtd, parser); ++ ++#if XML_GE == 1 ++ parser->m_alloc_tracker.bytesAllocatedWhenLastReset ++ = parser->m_alloc_tracker.bytesAllocated; ++#endif ++ + return XML_TRUE; + } + +--- a/expat/tests/runtests.c ++++ b/expat/tests/runtests.c +@@ -13223,8 +13223,68 @@ + fail("unsignedCharToPrintable result mistaken"); + } + END_TEST ++ ++START_TEST(test_amplification_reset_neutrality) { ++ const char *const doc ++ = "<!DOCTYPE r [<!ENTITY e 'general entity'>]><r>&e;</r>"; ++ XML_Parser parser = XML_ParserCreate(NULL); ++ assert_true( ++ XML_SetBillionLaughsAttackProtectionMaximumAmplification(parser, 1.0f) ++ == XML_TRUE); ++ assert_true(XML_SetBillionLaughsAttackProtectionActivationThreshold(parser, 0) ++ == XML_TRUE); ++ ++ assert_true(XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_TRUE) ++ == XML_STATUS_ERROR); ++ assert_true(XML_GetErrorCode(parser) == XML_ERROR_AMPLIFICATION_LIMIT_BREACH); ++ ++ assert_true(XML_ParserReset(parser, NULL) == XML_TRUE); ++ ++ assert_true(XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_TRUE) ++ == XML_STATUS_ERROR); ++ assert_true(XML_GetErrorCode(parser) == XML_ERROR_AMPLIFICATION_LIMIT_BREACH); ++ ++ XML_ParserFree(parser); ++} ++END_TEST + #endif // defined(XML_DTD) + ++#if XML_GE == 1 ++START_TEST(test_alloc_tracker_reset_neutrality) { ++ XML_Parser parser = XML_ParserCreate(NULL); ++ assert_true(parser != NULL); ++ ++ const char *const small = "<hello/>"; ++ ++ // Create a document that drives `parser->m_alloc_tracker.bytesAllocated` ++ // towards the activation threshold ++ const size_t bigSizeBytes ++ = (size_t)(1.1f * EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT); ++ const char *const before = "<doc a='"; ++ const char *const after = "'/>"; ++ char *const big = (char *)malloc(bigSizeBytes); ++ assert_true(big != NULL); ++ memset(big, 'X', bigSizeBytes); ++ memcpy(big, before, strlen(before)); // without zero terminator ++ strcpy(big + (bigSizeBytes - strlen(after) - 1), ++ after); // with zero terminator ++ assert_true(strlen(big) == bigSizeBytes - 1); // self-test ++ ++ assert_true(XML_Parse(parser, big, (int)strlen(big), /*isFinal=*/XML_TRUE) ++ == XML_STATUS_OK); ++ ++ free(big); ++ ++ assert_true(XML_ParserReset(parser, NULL) == XML_TRUE); ++ ++ assert_true(XML_Parse(parser, small, (int)strlen(small), /*isFinal=*/XML_TRUE) ++ == XML_STATUS_OK); ++ ++ XML_ParserFree(parser); ++} ++END_TEST ++#endif // XML_GE == 1 ++ + static Suite * + make_suite(void) { + Suite *s = suite_create("basic"); +@@ -13637,6 +13697,10 @@ + tcase_add_test(tc_accounting, test_accounting_precision); + tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api); + tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable); ++ tcase_add_test(tc_accounting, test_amplification_reset_neutrality); ++#endif ++#if XML_GE == 1 ++ tcase_add_test(tc_misc, test_alloc_tracker_reset_neutrality); + #endif + + return s; diff -urN old/debian/patches/CVE-2026-117610.patch new/debian/patches/CVE-2026-117610.patch --- old/debian/patches/CVE-2026-117610.patch 1969-12-31 19:00:00.000000000 -0500 +++ new/debian/patches/CVE-2026-117610.patch 2026-11-05 15:04:23.000000000 -0500 @@ -0,0 +1,97 @@ +Description: Fix initial non-final empty subparser call with a handler (CVE-2026-117610) + Backport of upstream PR #1444 to expat 2.5.0. An external entity parser that + is first fed an empty, non-final buffer reached externalEntityInitProcessor3 + with XML_TOK_NONE; externalEntityInitProcessor2 now returns early and waits + for more input. The library change applies unchanged; the regression test is + ported from tests/misc_tests.c to the single tests/runtests.c used by 2.5.0 + (XCS()/xcstrcmp() instead of xcsdup_str()/xcscmp()). +Origin: backport, https://github.com/libexpat/libexpat/commit/bfc28346fa3e https://github.com/libexpat/libexpat/commit/cedb704d2cad +Bug: https://github.com/libexpat/libexpat/pull/1444 +Bug-Debian: https://bugs.debian.org/1152343 +Last-Update: 2026-11-05 +--- +--- a/expat/lib/xmlparse.c ++++ b/expat/lib/xmlparse.c +@@ -3271,6 +3271,11 @@ + } + parser->m_eventPtr = start; + return XML_ERROR_PARTIAL_CHAR; ++ case XML_TOK_NONE: ++ if (! parser->m_parsingStatus.finalBuffer) { ++ *endPtr = start; ++ } ++ return XML_ERROR_NONE; + } + parser->m_processor = externalEntityInitProcessor3; + return externalEntityInitProcessor3(parser, start, end, endPtr); +--- a/expat/tests/runtests.c ++++ b/expat/tests/runtests.c +@@ -9038,6 +9038,60 @@ + } + END_TEST + ++static void XMLCALL ++comparingPiHandler(void *userData, const XML_Char *target, ++ const XML_Char *data) { ++ UNUSED_P(userData); ++ assert_true(target != NULL); ++ assert_true(data != NULL); ++ assert_true(xcstrcmp(target, XCS("target")) == 0); ++ assert_true(xcstrcmp(data, XCS("data")) == 0); ++} ++ ++static int XMLCALL ++piParsingExternalEntityHandler(XML_Parser parent, const XML_Char *context, ++ const XML_Char *base, const XML_Char *systemId, ++ const XML_Char *publicId) { ++ UNUSED_P(base); ++ UNUSED_P(systemId); ++ UNUSED_P(publicId); ++ ++ const char *const doc = "<?target data?>"; ++ ++ XML_Parser subParser = XML_ExternalEntityParserCreate(parent, context, NULL); ++ assert_true(subParser != NULL); ++ ++ assert_true(_XML_Parse_SINGLE_BYTES(subParser, "", 0, /*isFinal=*/XML_FALSE) ++ == XML_STATUS_OK); ++ assert_true(_XML_Parse_SINGLE_BYTES(subParser, doc, (int)strlen(doc), ++ /*isFinal=*/XML_TRUE) ++ == XML_STATUS_OK); ++ ++ XML_ParserFree(subParser); ++ ++ return XML_STATUS_OK; ++} ++ ++START_TEST(test_misc_empty_nonfinal_subparser_parse) { ++ const char *const doc = "<!DOCTYPE root [\n" ++ " <!ENTITY ext SYSTEM 'external.dtd'>\n" ++ "]>\n" ++ "<root>&ext;</root>\n"; ++ ++ XML_Parser parser = XML_ParserCreate(NULL); ++ assert_true(parser != NULL); ++ ++ XML_SetProcessingInstructionHandler(parser, comparingPiHandler); ++ XML_SetExternalEntityRefHandler(parser, piParsingExternalEntityHandler); ++ ++ assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc), ++ /*isFinal=*/XML_TRUE) ++ == XML_STATUS_OK); ++ ++ XML_ParserFree(parser); ++} ++END_TEST ++ + static void + alloc_setup(void) { + XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free}; +@@ -13481,6 +13535,7 @@ + tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser); + tcase_add_test__ifdef_xml_dtd(tc_misc, test_renter_loop_finite_content); + tcase_add_test(tc_misc, test_misc_expected_event_ptr_issue_980); ++ tcase_add_test(tc_misc, test_misc_empty_nonfinal_subparser_parse); + + suite_add_tcase(s, tc_alloc); + tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown); diff -urN old/debian/patches/CVE-2026-118370.patch new/debian/patches/CVE-2026-118370.patch --- old/debian/patches/CVE-2026-118370.patch 1969-12-31 19:00:00.000000000 -0500 +++ new/debian/patches/CVE-2026-118370.patch 2026-11-05 15:03:39.000000000 -0500 @@ -0,0 +1,99 @@ +Description: Protect attIndex and nPrefixes in storeAtts from signed integer overflow (CVE-2026-118370) + Backport of upstream PR #1450 to expat 2.5.0. Upstream changes attIndex, + nPrefixes and the matching loop counters in storeAtts() to size_t and rejects + counts above INT_MAX before storing them in the int-typed + m_nSpecifiedAtts / m_idAttIndex fields. In 2.5.0 the function shares one + "int i" between several loops, so the loops over attIndex use their own + size_t counters (k, ai) instead. +Origin: backport, https://github.com/libexpat/libexpat/commit/621cb2c78b25 https://github.com/libexpat/libexpat/commit/1bac53c4fc46 +Bug: https://github.com/libexpat/libexpat/pull/1450 +Bug-Debian: https://bugs.debian.org/1152337 +Last-Update: 2026-11-05 +--- +--- a/expat/lib/xmlparse.c ++++ b/expat/lib/xmlparse.c +@@ -3908,12 +3908,12 @@ + ELEMENT_TYPE *elementType; + int nDefaultAtts; + const XML_Char **appAtts; /* the attribute list for the application */ +- int attIndex = 0; ++ size_t attIndex = 0; + int prefixLen; + int i; + int n; + XML_Char *uri; +- int nPrefixes = 0; ++ size_t nPrefixes = 0; + BINDING *binding; + const XML_Char *localPart; + +@@ -4095,11 +4095,16 @@ + } + + /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */ +- parser->m_nSpecifiedAtts = attIndex; ++ // Detect and reject integer overflow ++ if (attIndex > INT_MAX) ++ return XML_ERROR_NO_MEMORY; ++ parser->m_nSpecifiedAtts = (int)attIndex; + if (elementType->idAtt && (elementType->idAtt->name)[-1]) { +- for (i = 0; i < attIndex; i += 2) +- if (appAtts[i] == elementType->idAtt->name) { +- parser->m_idAttIndex = i; ++ for (size_t k = 0; k < attIndex; k += 2) ++ if (appAtts[k] == elementType->idAtt->name) { ++ if (k > INT_MAX) ++ return XML_ERROR_NO_MEMORY; ++ parser->m_idAttIndex = (int)k; + break; + } + } else +@@ -4132,7 +4137,7 @@ + + /* expand prefixed attribute names, check for duplicates, + and clear flags that say whether attributes were specified */ +- i = 0; ++ size_t ai = 0; + if (nPrefixes) { + int j; /* hash table index */ + unsigned long version = parser->m_nsAttsVersion; +@@ -4194,8 +4199,8 @@ + parser->m_nsAttsVersion = --version; + + /* expand prefixed names and check for duplicates */ +- for (; i < attIndex; i += 2) { +- const XML_Char *s = appAtts[i]; ++ for (; ai < attIndex; ai += 2) { ++ const XML_Char *s = appAtts[ai]; + if (s[-1] == 2) { /* prefixed */ + ATTRIBUTE_ID *id; + const BINDING *b; +@@ -4284,7 +4289,7 @@ + /* store expanded name in attribute list */ + s = poolStart(&parser->m_tempPool); + poolFinish(&parser->m_tempPool); +- appAtts[i] = s; ++ appAtts[ai] = s; + + /* fill empty slot with new version, uriName and hash value */ + parser->m_nsAtts[j].version = version; +@@ -4292,7 +4297,7 @@ + parser->m_nsAtts[j].uriName = s; + + if (! --nPrefixes) { +- i += 2; ++ ai += 2; + break; + } + } else /* not prefixed */ +@@ -4300,8 +4305,8 @@ + } + } + /* clear flags for the remaining attributes */ +- for (; i < attIndex; i += 2) +- ((XML_Char *)(appAtts[i]))[-1] = 0; ++ for (; ai < attIndex; ai += 2) ++ ((XML_Char *)(appAtts[ai]))[-1] = 0; + for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding) + binding->attId->name[-1] = 0; + diff -urN old/debian/patches/series new/debian/patches/series --- old/debian/patches/series 2026-10-21 18:22:05.000000000 -0400 +++ new/debian/patches/series 2026-11-05 15:18:31.000000000 -0500 @@ -68,3 +68,7 @@ CVE-2026-118370.patch +CVE-2026-117610.patch +CVE-2025-59375-tests.patch +CVE-2026-113351.patch
