Heap buffer overflow read in [@ little2_toUtf16] via lone-high-surrogate entity value
Categories
(Core :: XML, defect)
Tracking
()
People
(Reporter: bugmon, Assigned: hsivonen)
References
Details
(5 keywords, Whiteboard: [adv-main154+r][adv-esr153.1+r])
Attachments
(4 files, 3 external files)
The DEFINE_UTF16_TO_UTF16 macro in expat's xmltok.c (instantiated as little2_toUtf16) contains a surrogate-detection bug: the check (GET_HI(fromLim - 2) & 0xF8) == 0xD8 is intended to avoid copying only the first half of a surrogate pair when the output buffer is one code unit too small, but the mask 0xF8 matches the entire 0xD8-0xDF range, i.e. both high (0xD8-0xDB) and low (0xDC-0xDF) surrogates. When an internal entity value is exactly one UTF-16 code unit longer than the fresh entityValuePool block (INIT_BLOCK_SIZE = 1018 shorts on 64-bit XML_UNICODE builds) and ends in a well-formed surrogate pair, the last code unit β a low surrogate β is misidentified as a lead surrogate, fromLim is trimmed by 2, and the function returns XML_CONVERT_INPUT_INCOMPLETE instead of XML_CONVERT_OUTPUT_EXHAUSTED. poolAppend treats INPUT_INCOMPLETE as terminal and stops without growing the pool, so the stored entity->textPtr ends with a lone high surrogate placed at the exact end of the malloc'd block.
When that entity is later referenced inside an attribute value, appendAttributeValue re-tokenizes entity->textPtr with the internal little2 encoding. attributeValueTok trusts that the internal encoding is already validated and, on BT_LEAD4, unconditionally executes ptr += 4, producing next = textEnd + 2. poolAppend is then invoked with an end pointer 2 bytes past the allocation, and little2_toUtf16 reads (and copies into the destination pool) two bytes of adjacent heap memory. This is directly reachable from unprivileged web content via new DOMParser().parseFromString(xml, 'application/xml').
Firefox builds expat with XML_UNICODE and always feeds it UTF-16, so the vulnerable UTF-16βUTF-16 path is always taken. In shipping Firefox, expat runs inside the RLBox WASM sandbox, so the out-of-bounds read is confined to the sandbox's linear memory and cannot leak Firefox process heap; the ASAN report requires --without-wasm-sandboxed-libraries to observe the corruption directly. The underlying bug is nonetheless a genuine memory-safety defect in expat that Firefox ships and that upstream expat (in its default non-XML_UNICODE build) does not exercise.
Build Info
- Branch: main
- Revision: d4a2cc2aa48ba5e56ce90680e90038843a7298c7
- Timestamp: 2026-07-01T00:30:50+00:00
Affected Code
File: parser/expat/expat/lib/xmltok.c, line 699-718
#define DEFINE_UTF16_TO_UTF16(E) \
static enum XML_Convert_Result PTRCALL E##toUtf16( \
const ENCODING *enc, const char **fromP, const char *fromLim, \
unsigned short **toP, const unsigned short *toLim) { \
enum XML_Convert_Result res = XML_CONVERT_COMPLETED; \
UNUSED_P(enc); \
fromLim = *fromP + (((fromLim - *fromP) >> 1) << 1); /* shrink to even */ \
/* Avoid copying first half only of surrogate */ \
if (fromLim - *fromP > ((toLim - *toP) << 1) \
&& (GET_HI(fromLim - 2) & 0xF8) == 0xD8) { /* BUG: 0xF8 also matches 0xDC-0xDF (low surrogates) */ \
fromLim -= 2; \
res = XML_CONVERT_INPUT_INCOMPLETE; /* wrong result for a trailing low surrogate */ \
} \
for (; *fromP < fromLim && *toP < toLim; *fromP += 2) \
*(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
if ((*toP == toLim) && (*fromP < fromLim)) \
return XML_CONVERT_OUTPUT_EXHAUSTED; \
else \
return res; \
}
File: parser/expat/expat/lib/xmlparse.c, line 8297-8312
static XML_Char *
poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
const char *end) {
if (! pool->ptr && ! poolGrow(pool))
return NULL;
for (;;) {
const enum XML_Convert_Result convert_res = XmlConvert(
enc, &ptr, end, (ICHAR **)&(pool->ptr), (const ICHAR *)pool->end);
if ((convert_res == XML_CONVERT_COMPLETED)
|| (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) /* stops here β low surrogate silently dropped */
break;
if (! poolGrow(pool))
return NULL;
}
return pool->start;
}
File: parser/expat/expat/lib/xmltok_impl.c, line 1275-1284
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
# define LEAD_CASE(n) \
case BT_LEAD##n: \
ptr += n; /* NOTE: The encoding has already been validated. */ \
break; /* lone high surrogate at end-2 β ptr = end + 2 */
LEAD_CASE(2)
LEAD_CASE(3)
LEAD_CASE(4)
# undef LEAD_CASE
File: parser/expat/expat/lib/xmlparse.c, line 6873-6876
case XML_TOK_DATA_CHARS:
if (! poolAppend(pool, enc, ptr, next)) /* next = textEnd + 2 β OOB read in little2_toUtf16 */
return XML_ERROR_NO_MEMORY;
break;
Root cause is the over-broad surrogate mask in DEFINE_UTF16_TO_UTF16, which lets poolAppend terminate early and leave a lone high surrogate at the end of the pool block. The internal-encoding attribute tokenizer then over-advances past the buffer.
Exploit Chain
- Web content calls new DOMParser().parseFromString(xml, 'application/xml') with an internal entity whose replacement text is exactly INIT_BLOCK_SIZE + 1 = 1019 UTF-16 code units and ends in a valid surrogate pair (e.g. 1017 Γ 'a' + U+1F600).
- storeEntityValue β poolAppend β little2_toUtf16 sees fromLim - *fromP (2038) > (toLim - *toP) << 1 (2036) and GET_HI of the last unit is 0xDE; 0xDE & 0xF8 == 0xD8, so fromLim -= 2 and res = XML_CONVERT_INPUT_INCOMPLETE.
- 1018 code units are copied β the last one is the high surrogate 0xD83D β and INPUT_INCOMPLETE is returned. poolAppend breaks without calling poolGrow. entity->textPtr now ends with a lone high surrogate at the exact end of the 2056-byte pool block.
- The document references the entity in an attribute value: <r a="&e;"/>. storeAttributeValue β appendAttributeValue re-tokenizes entity->textPtr with the internal little2 encoding.
- little2_attributeValueTok reaches the lone high surrogate at textEnd - 2, classifies it as BT_LEAD4, and executes ptr += 4 unconditionally, yielding next = textEnd + 2.
- appendAttributeValue calls poolAppend(pool, enc, ptr, textEnd + 2); little2_toUtf16 reads bytes textEnd[0..1] β 2 bytes past the allocation β and copies them into the attribute-value pool. ASAN reports heap-buffer-overflow READ of size 1 at allocation+1.
Steps to Reproduce
- Build Firefox with an ASAN mozconfig that includes
ac_add_options --without-wasm-sandboxed-libraries(so the OOB is directly observable by ASAN rather than contained inside the RLBox WASM sandbox). - Serve and load the following testcase.html:
- <!DOCTYPE html>\n<meta charset="utf-8">\n<script>\nconst v = 'a'.repeat(1017) + 'π';\nconst xml = '<?xml version="1.0"?>\n<!DOCTYPE r [<!ENTITY e "' + v + '">]>\n<r a="&e;"/>';\nnew DOMParser().parseFromString(xml, 'application/xml');\n</script>
- Observe ASAN heap-buffer-overflow READ in little2_toUtf16 (parser/expat/expat/lib/xmltok.c:724).
Security Impact
- Severity: Low
- Attacker capability: A web page can trigger a 2-byte out-of-bounds heap read past the end of expat's entity-value pool block; the two bytes are copied into the parsed attribute value and are in principle observable to script. In shipping Firefox this occurs inside the RLBox WASM sandbox for expat, so the leaked bytes come from adjacent objects inside the sandbox's linear memory (parser state derived from the same input document), not from Firefox process heap. In builds without RLBox WASM sandboxing (e.g. --without-wasm-sandboxed-libraries) the read touches real content-process heap and could disclose 2 bytes of adjacent heap data.
- Preconditions: None beyond the ability to run script (DOMParser) or otherwise feed XML with an internal DTD entity to Firefox's expat-backed XML parser. Directly observing the OOB under ASAN requires building with --without-wasm-sandboxed-libraries, since default builds run expat inside the RLBox WASM sandbox where the corruption is contained.
ASAN Report
==171187==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7894b178b289 at pc 0x76c48683af85 bp 0x7ffd544bc340 sp 0x7ffd544bc338
READ of size 1 at 0x7894b178b289 thread T0 (WebCOOP+COEP Co)
#0 0x76c48683af84 in little2_toUtf16 /firefox/parser/expat/expat/lib/xmltok.c:724:1
#1 0x76c48681bbe9 in poolAppend /firefox/parser/expat/expat/lib/xmlparse.c:8303:49
#2 0x76c48681bbe9 in appendAttributeValue /firefox/parser/expat/expat/lib/xmlparse.c:6874:13
#3 0x76c4868078fd in storeAttributeValue /firefox/parser/expat/expat/lib/xmlparse.c:6760:18
#4 0x76c486813dac in storeAtts /firefox/parser/expat/expat/lib/xmlparse.c:4115:16
#5 0x76c48680cc9c in doContentInternal /firefox/parser/expat/expat/lib/xmlparse.c:3660:16
#6 0x76c48680cc9c in doContent /firefox/parser/expat/expat/lib/xmlparse.c:3405:27
#7 0x76c486801c3e in contentProcessor /firefox/parser/expat/expat/lib/xmlparse.c:3260:27
#8 0x76c486801c3e in doProlog /firefox/parser/expat/expat/lib/xmlparse.c:5716:14
#9 0x76c4867f9114 in prologProcessor /firefox/parser/expat/expat/lib/xmlparse.c:5419:10
#10 0x76c4867f9114 in prologInitProcessor /firefox/parser/expat/expat/lib/xmlparse.c:5212:10
#11 0x76c4867f6484 in callProcessor /firefox/parser/expat/expat/lib/xmlparse.c:1260:11
#12 0x76c4867f5c3d in XML_Parse /firefox/parser/expat/expat/lib/xmlparse.c:2447:11
#13 0x76c486865a99 in rlbox::rlbox_noop_sandbox::impl_invoke_with_func_ptr<...> /firefox/obj-firefox-asan/dist/include/mozilla/rlbox/rlbox_noop_sandbox.hpp:187:12
#15 0x76c486865a99 in nsExpatDriver::ParseChunk(...) /firefox/parser/htmlparser/nsExpatDriver.cpp:1240:14
#20 0x76c4893fe358 in mozilla::dom::DOMParser::ParseFromStream(...) /firefox/dom/base/DOMParser.cpp:246:20
#22 0x76c4893fec6d in mozilla::dom::DOMParser::ParseFromString(...) /firefox/dom/base/DOMParser.cpp:117:10
0x7894b178b289 is located 1 bytes after 2056-byte region [0x7894b178aa80,0x7894b178b288)
allocated by thread T0 (WebCOOP+COEP Co) here:
#0 0x5c8b9e1f9994 in __interceptor_malloc _asan_rtl_:3
#1 0x76c486807346 in expat_malloc /firefox/parser/expat/expat/lib/xmlparse.c:938:29
#2 0x76c486807346 in poolGrow /firefox/parser/expat/expat/lib/xmlparse.c:8504:11
#3 0x76c48681c6c4 in storeEntityValue /firefox/parser/expat/expat/lib/xmlparse.c:7030:11
#4 0x76c4867fbf65 in callStoreEntityValue /firefox/parser/expat/expat/lib/xmlparse.c:7210:13
#5 0x76c4867fbf65 in doProlog /firefox/parser/expat/expat/lib/xmlparse.c:5849:33
SUMMARY: AddressSanitizer: heap-buffer-overflow (/firefox/obj-firefox-asan/dist/bin/libxul.so+0x14606f84)
| Reporter | ||
Comment 1•4 months ago
|
||
| Reporter | ||
Comment 2•4 months ago
|
||
| Reporter | ||
Comment 3•4 months ago
|
||
| Reporter | ||
Comment 4•4 months ago
|
||
| Reporter | ||
Comment 5•4 months ago
|
||
| Reporter | ||
Comment 6•4 months ago
|
||
| Reporter | ||
Comment 7•4 months ago
|
||
| Reporter | ||
Comment 8•4 months ago
|
||
Updated•4 months ago
|
Comment 10•3 months ago
|
||
The severity field is not set for this bug.
:hsinyi, could you have a look please?
For more information, please visit BugBot documentation.
Comment 11•3 months ago
|
||
Please let me know if you don't agree with S3 rating.
| Assignee | ||
Updated•3 months ago
|
| Assignee | ||
Comment 12•3 months ago
|
||
| Assignee | ||
Comment 13•3 months ago
|
||
CCing the upstream maintainer.
In the Firefox case, RLBox mitigates the impact of this change, so it's probably the best if upstream lands the fix first to address non-RLBoxed deployments of expat.
| Assignee | ||
Comment 14•3 months ago
|
||
This is now ready to land as far as Firefox sec bug processes go, but I think it would be appropriate to land a fix upstream before I land the Firefox patch.
Sebastian Pipping, how would you prefer to proceed?
Comment 15•3 months ago
|
||
:hsivonen, please update all release status flags to reflect the affected/unaffected/disabled state correctly. Which branches (beta, release, and/or ESR) are affected by this flaw?
Updated•3 months ago
|
Comment 16•3 months ago
|
||
:hsivonen, I appreciate the CC. I will try to find find time for a first closer look next week, starting August 3rd.
Comment 17•3 months ago
|
||
Hello!
I had a chance at a first closer look now and I would like to report back that:
-
I was able to reproduce some form of the issue, and the symtom is an infinite loop for me in practice so far (without sanitizers). That raises two questions with me:
- Does this issue have two flavors and we are each seeing a different one so far?
- Whether (or how) the sandbox would protect against an infinite loop if end-user Firefox is build without sanitizers (which I consider default, please correct me).
-
Please note that Firefox has a different INIT_BLOCK_SIZE than Expat upstream, see Firefox downstream patch
https://github.com/mozilla-firefox/firefox/blob/d3e7ce6714d38e3f706f480aef3b3f17b1445682/parser/expat/01_noslop.patch#L8-L11 . -
Because the issue needs 16bit character types to hit, it is rather nasty to reproduce on Linux (e.g. because wchar_t is 4 bytes on Linux). If you would like to reproduce the issue using MinGW on Linux, this CMake command may be of help:
cmake -DCMAKE_TOOLCHAIN_FILE=cmake/mingw-toolchain.cmake -DEXPAT_CHAR_TYPE=wchar_t -DEXPAT_BUILD_TESTS=ON -DEXPAT_BUILD_TOOLS=OFF -S . -B build_mingw_wchart_tests
-
I do not have MinGW with sanitizers or MinGW GDB ready or in CI as of the moment, but I plan to set that up in the next few days if possible.
-
I'd be curious which AI tools and LLM models have been used to facilitate this finding, if any. I would want to give credit to the LLM model company also in that case.
-
My related work-in-progress upstream can be found at: https://github.com/libexpat/libexpat/compare/master...mozilla-2053153
What do you think?
Best, Sebastian
Comment 18•3 months ago
|
||
PS: I've been working semi-publicly on the issue in GitHub only because a single full CI run of Expat eats most of the total CI budget for private repositories that I have, and running CI twice and then being blind to CI doesn't get us very far. I hope that's okay with you, thanks for your understanding.
| Assignee | ||
Comment 19•3 months ago
|
||
(In reply to sebastian from comment #16)
I will try to find find time for a first closer look next week, starting August 3rd.
Thank you for looking into this. I'm sorry that I hadn't seen the summer of bliss announcement before CCing.
(In reply to sebastian from comment #17)
- I was able to reproduce some form of the issue, and the symtom is an infinite loop for me in practice so far (without sanitizers). That raises two questions with me:
- Does this issue have two flavors and we are each seeing a different one so far?
I don't see an infinite loop on either x86_64 Linux or aarch64 macOS with the sandbox enabled and without ASAN, so it's possible that without ASAN catching the out of bounds read immediately, the symptoms depend on what value the out of bounds read yields, and it may be different in Firefox with the reproducer attached here vs. your port of the reproducer.
The extent of the checking that I did was:
- I manually verified on x86_64 Linux that the reported out of bounds access was visible to ASAN when RLBox is disabled.
- I concluded that the code is meant to check for a high surrogate only, so changing it to check for a high surrogate only instead of any surrogate looked like the right fix.
- Whether (or how) the sandbox would protect against an infinite loop if end-user Firefox is build without sanitizers (which I consider default, please correct me).
As far as I know, the sandbox doesn't protect against an infinite loop, so there's something else about the specifics that cause an infine loop not to occur with this reproducer in Firefox.
Because the issue needs 16bit character types to hit, it is rather nasty to reproduce on Linux (e.g. because wchar_t is 4 bytes on Linux).
Yeah, I expected the test case rather than the actual code change to be the hard part for the upstream.
- I'd be curious which AI tools and LLM models have been used to facilitate this finding, if any. I would want to give credit to the LLM model company also in that case.
Needinfoing jkratzer for appropriate credit formulation.
- My related work-in-progress upstream can be found at: https://github.com/libexpat/libexpat/compare/master...mozilla-2053153
What do you think?
Looks good to me.
(In reply to sebastian from comment #18)
PS: I've been working semi-publicly on the issue in GitHub only because a single full CI run of Expat eats most of the total CI budget for private repositories that I have, and running CI twice and then being blind to CI doesn't get us very far. I hope that's okay with you, thanks for your understanding.
Since this is now public there, I have queued the fix (but not the test case) for landing in Firefox.
| Assignee | ||
Updated•3 months ago
|
Comment 20•3 months ago
|
||
Comment 21•3 months ago
|
||
Comment 22•3 months ago
|
||
Please add Beta and ESR153 uplift requests on this.
Comment 23•3 months ago
|
||
Hello Henri, thanks for your reply!
I would like to share these updates from my side:
-
(I have not yet managed to get the combination "MinGW Clang ASan Wine Ubuntu 2[46].04" to run (only without ASan (..)), and I am currently unsure whether it is economically possible. If anyone has success with that case, please let me know!)
-
I managed to attach a GUI debugger (KDbg) to MinGW on Linux now. For anyone curious to do the same:
winedbg --gdb --no-start --port 55555 tests/runtests.exe # first half
kdbg -r localhost:55555 # second half, other terminal
-
That led me to confirm that there is indeed an infinite loop upstream for the very test case that I added and it's caused by function
storeAttributeValuecalling intoappendAttributeValuewithptr == end + 2(i.e. stepping over the end) over and over again. -
Once I apply Mozilla's patch
01_noslop.patch(https://github.com/mozilla-firefox/firefox/blob/d3e7ce6714d38e3f706f480aef3b3f17b1445682/parser/expat/01_noslop.patch#L8-L11) that infinite loop no longer occurs. So upstream Expat and Firefox Expat indeed behave differently. -
I would be glad to understand the idea/motivation/details behind Mozilla's
01_noslop.patch, it is not clear to me, happy to learn more. It's not urgent, but would be great.
Comment 24•3 months ago
|
||
(In reply to sebastian from comment #23)
- I would be glad to understand the idea/motivation/details behind Mozilla's
01_noslop.patch, it is not clear to me, happy to learn more. It's not urgent, but would be great.
Appears to have been added in bug 1016153.
Comment 25•3 months ago
|
||
(In reply to Ryan VanderMeulen [:RyanVM] from comment #24)
Appears to have been added in bug 1016153.
Yes, comment 0 explains it but I can answer further questions. It is only relevant if your allocator rounds up the allocation to the nearest power of 2. It is a common pattern where somebody has a buffer-ish kind of data structure and they decide to be thoughtful and make it a power of 2, but then they forget about some extra header information that ends up pushing the total size of the object just over a power of 2, which means that in an allocator that rounds up to the nearest power of 2, almost half of the memory is wasted.
Comment 26•3 months ago
•
|
||
Thanks Andrew and Ryan! I am happy to include a version of that upstream, I would just want to add an in-code comment with the idea and why/how the formula is correct. I will give a PR a shot myself in the next few days unless someone beats me to it.
PS: Public PR on the infinite loop OOB read thing now upstream at https://github.com/libexpat/libexpat/pull/1296 . Will take a few days for extra review and then requesting and receiving a CVE also.
PPS: I have added hanno@hboeck.de to CC now.
Comment 27•3 months ago
•
|
||
Deleted, it was too late. Sorry.
Comment 28•3 months ago
•
|
||
Deleted, it was too late. Sorry.
Comment 29•3 months ago
|
||
firefox-beta Uplift Approval Request
- User impact if declined/Reason for urgency: Fixes an out-of-bounds read in expat inside the RLBox sandbox. It's unclear what the user impact is. Per upstream findings, perhaps there could be an infinite loop with our memory layout and different input than the provided test case.
- Code covered by automated testing?: no
- Fix verified in Nightly?: no
- Needs manual QE testing?: no
- Steps to reproduce for manual QE testing:
- Risk associated with taking this patch: low
- Explanation of risk level: Low risk, because this changes a general surrogate check to a high surrogate check in a place where the code clearly intends to check only for high surrogates.
- String changes made/needed?: None
- Is Android affected?: yes
| Assignee | ||
Comment 30•3 months ago
|
||
Original Revision: https://phabricator.services.mozilla.com/D314632
Comment 31•3 months ago
|
||
firefox-esr153 Uplift Approval Request
- User impact if declined/Reason for urgency: Fixes an out-of-bounds read in expat inside the RLBox sandbox. It's unclear what the user impact is. Per upstream findings, perhaps there could be an infinite loop with our memory layout and different input than the provided test case.
- Code covered by automated testing?: no
- Fix verified in Nightly?: no
- Needs manual QE testing?: no
- Steps to reproduce for manual QE testing:
- Risk associated with taking this patch: low
- Explanation of risk level: Low risk, because this changes a general surrogate check to a high surrogate check in a place where the code clearly intends to check only for high surrogates.
- String changes made/needed?: None
- Is Android affected?: yes
| Assignee | ||
Comment 32•3 months ago
|
||
Original Revision: https://phabricator.services.mozilla.com/D314632
| Assignee | ||
Comment 33•3 months ago
|
||
(In reply to Ryan VanderMeulen [:RyanVM] from comment #22)
Please add Beta and ESR153 uplift requests on this.
Requested.
(In reply to sebastian from comment #23)
- That led me to confirm that there is indeed an infinite loop upstream for the very test case that I added and it's caused by function
storeAttributeValuecalling intoappendAttributeValuewithptr == end + 2(i.e. stepping over the end) over and over again.
Thanks. I think I'm going to defer fixing that in Firefox until our next sync from the upstream.
Updated•3 months ago
|
Updated•3 months ago
|
Comment 34•3 months ago
|
||
| uplift | ||
Updated•3 months ago
|
Updated•3 months ago
|
Comment 35•3 months ago
|
||
| uplift | ||
Comment 36•3 months ago
|
||
Adding Berkay to CCβ¦
Comment 37•3 months ago
|
||
CVE requested (for Expat upstream only) from Mitre just now
Comment 38•2 months ago
|
||
(In reply to Henri Sivonen (:hsivonen) from comment #19)
(In reply to sebastian from comment #16)
Needinfoing jkratzer for appropriate credit formulation.
I spoke with Sebastian directly and provided them with attribution information.
Comment 39•2 months ago
|
||
I confirm! :)
The Expat issue was assigned CVE-2026-72522 by now. Release 2.8.3 with the fix is expected for later today (UTC+2 evening).
Comment 40•2 months ago
|
||
Update: There are more steps like writing a related blog post left to do (progress details at https://github.com/libexpat/libexpat/issues/1313) but the release 2.8.3 "itself" is out and up at https://github.com/libexpat/libexpat/releases/tag/R_2_8_3 . Enjoy! :)
| Assignee | ||
Comment 41•2 months ago
|
||
Thank you. I added the CVE to the bug alias field.
Updated•2 months ago
|
Updated•2 months ago
|
Updated•2 months ago
|
Comment 42•2 months ago
|
||
(In reply to Andrew McCreight [:mccr8] from comment #25)
(In reply to Ryan VanderMeulen [:RyanVM] from comment #24)
Appears to have been added in bug 1016153.
Yes, comment 0 explains it but I can answer further questions. It is only relevant if your allocator rounds up the allocation to the nearest power of 2. It is a common pattern where somebody has a buffer-ish kind of data structure and they decide to be thoughtful and make it a power of 2, but then they forget about some extra header information that ends up pushing the total size of the object just over a power of 2, which means that in an allocator that rounds up to the nearest power of 2, almost half of the memory is wasted.
FYI In the meantime I noticed that the changes in 2.7.2 to fix CVE-2025-59375 changed the size of allocations and so the current 01_noslop.patch is unlikely to ensure multiples-of-two allocations with Expat >=2.7.2. It can be forward-ported to latest Expat but that's non-trivial to do.
Updated•10 days ago
|
Description
•