Closed Bug 1988534 Opened 8 months ago Closed 4 months ago

Update libexpat to 2.7.3

Categories

(Core :: XML, defect)

defect

Tracking

()

RESOLVED FIXED
149 Branch
Tracking Status
firefox-esr115 --- wontfix
firefox-esr140 --- fixed
firefox147 --- wontfix
firefox148 --- wontfix
firefox149 --- fixed

People

(Reporter: mccr8, Assigned: mccr8)

References

()

Details

Attachments

(8 files)

Currently we are on 2.6.4 (bug 1950575). This is now using the vendoring system so hopefully updating will be less tricky.

2.7.0 was released shortly thereafter. This might be a pain to update to, because I think the major change is a large rewrite to completely avoid recursion due to DoS concerns. I wouldn't imagine it would fundamentally break any changes we've made, but the bitrot could be intense.

2.7.1 was released 2 weeks after that. It looks like the main issue was addressing some compat problems.

See Also: → CVE-2025-59375

Peter started working on the update to 2.7.0 in bug 1954018.

See Also: → 1954018

Little hint:
2025-09-16 — Expat 2.7.2 has been released, includes security fixes
https://github.com/libexpat/libexpat/blob/R_2_7_2/expat/Changes

See Also: CVE-2025-59375, 1954018
Summary: Update libexpat to 2.7.1 → Update libexpat to 2.7.2

And another Update:

2025-09-24 — Expat 2.7.3 has been released, includes security fixes
Release 2.7.3 Wed September 24 2025
Security fixes:
#1046 #1048 Fix alignment of internal allocations for some non-amd64
architectures (e.g. sparc32); fixes up on the fix to
CVE-2025-59375 from #1034 (of Expat 2.7.2 and related
backports)
#1059 Fix a class of false positives where input should have been
rejected with error XML_ERROR_ASYNC_ENTITY; regression from
CVE-2024-8176 fix pull request #973 (of Expat 2.7.0 and
related backports). Please check the added unit tests for
example documents.

Link: https://github.com/libexpat/libexpat/blob/R_2_7_3/expat/Changes

Blocks: 1192544
Blocks: 616361
Summary: Update libexpat to 2.7.2 → Update libexpat to 2.7.3

This issue was pointed out by distro maintainers, Andrew does your team have the cycles to address this or do you need help? I'm a bit swamped at the moment but I could do something on the side or find someone of my team to pick this up.

Flags: needinfo?(continuation)
Summary: Update libexpat to 2.7.3 → Update libexpat to 2.7.4

Would it be possible to add a --with-system-libexpat flag or similar, to choose system lib instead of the bundled one? What kind of patches do you apply on top, performance or some other mandatory browser-related ones?

I don't want to interrupt the upgrade discussion, but just an fyi: from the security side, expat is sandboxed with RLBox security framework and WebAssembly. So Firefox would not be affected by any vulnerabilities due to the current use of an older version of expat

https://blog.mozilla.org/attack-and-defense/2021/12/06/webassembly-and-back-again-fine-grained-sandboxing-in-firefox-95/

(This sandboxing is applied on all OSes)

Your view would be correct if the RLBox security framework and WebAssembly were guaranteed to be completely free of vulnerabilities, including unknown ones, and to function perfectly.

However, it's unreasonable to assume that Expat doesn't need to address security vulnerabilities just because RLBox and WebAssembly are supposed to protect us.

To clarify, I am not providing any recommendations on when/when not to upgrade (and frankly that discussion is outside my bailiwick). I am only providing relevant context around the security framework already in place for the current build in Firefox, as usually relevant to folks when they are assessing severity, priority, affected platforms fields etc. for the bug

Sorry, I accidentally messed up the title, fixed.

Summary: Update libexpat to 2.7.4 → Update libexpat to 2.7.3

(In reply to Joonas Niilola from comment #5)

Would it be possible to add a --with-system-libexpat flag or similar, to choose system lib instead of the bundled one? What kind of patches do you apply on top, performance or some other mandatory browser-related ones?

As mentioned, we use RLBox, which is like a C-to-C compiler that does a sort of software sandboxing, so I don't know that slotting in a system one will work or necessarily provide a safer end result.

(In reply to Gabriele Svelto [:gsvelto] from comment #4)

This issue was pointed out by distro maintainers, Andrew does your team have the cycles to address this or do you need help? I'm a bit swamped at the moment but I could do something on the side or find someone of my team to pick this up.

Sorry that I haven't been looking at it. I'll try to get to it soon. Getting our local version past the big refactor to get rid of all recursion might be a pain but hopefully once that is done it won't be too bad. I haven't actually done an upgrade, only reviewed an older one so I have to figure out how all of this works.

Assignee: nobody → continuation
Flags: needinfo?(continuation)

Also update the readme to mention git instead of hg.

Generated using
mach vendor parser/expat/moz.yaml --patch-mode=none

  • Mostly, this unbitrots the patches and updates line numbers.

  • Define MOZ_XML_GetMismatchedTag and MOZ_XML_ProcessingEntityValue are now
    defined in moz_xmlparse.c instead of these patches, to reduce future bitrot.
    This means that 06_report_processing_entity.patch can be removed entirely.

  • 11_nested_entities.patch handles some kind of issue with nested entities.
    This seems to correspond to code in internalEntityProcessor where there
    is now an assertion:
    assert(parser->m_openInternalEntities == openEntity);
    So I guess it is no longer needed? Peter removed it from his patch stack.

  • Renumber the patches to account for the two removed ones.

  • Remove some new malloc tracking debug info in 11_no_debug_report.patch

This was auto generated with
./mach vendor parser/expat/moz.yaml --patch-mode=only

For future reference, the way I initially made the diff-diffs was this (I'm sure a bunch of these steps could be simplified):

  1. First, I ran ./mach vendor parser/expat/moz.yaml --patch-mode=none to remove the patches and do the update.
  2. I changed directory to parser/expat.
  3. For each of the patches p.patch in the directory, I ran patch -r reject_path -p1 --directory ./ --no-backup-if-mismatch --batch --input p.patch.
  4. If any chunks didn't apply for a patch, I looked at the reject_path file and manually applied them, then deleted the reject_path file.
  5. I committed the changes for the patch to a commit with a name like PATCH p.patch.
  6. I updated the current patch with git show > p.patch. I had to manually edit the patch to remove header gunk, and to remove parser/expat/ from the patch directory.
  7. I committed the patch changes to a commit with a name like FIX p.patch and an explanation if appropriate.
  8. I had a few extra FIX patches in there to do renames because I was deleting some of the patches.

Once this was done for all of the patches, I squashed the FIX commits together and deleted the PATCH commits, then automatically applied the fixes via ./mach vendor parser/expat/moz.yaml --patch-mode=only. I tried doing this command at first, but mach vendor doesn't create intermediate commits for each patch, so if a patch is partially applied it is a pain figuring out what needs to be fixed up, then you have to revert the code and run it again from the start. With this approach, you have a bunch of stable intermediate states which is nice when you have so many patches to apply. This also fixes up the line numbers even in the case where patch was able to figure it out. I'm not sure if that actually helps anything.

Basically all of the clever bits of my patches, like moving a few definitions into moz_xmlparse.c, are taken from Peterv's patches in bug 1954018. My only real contribution here was further unbitrotting, and commenting out the malloc tracking stuff that is only used when a debug level is set (and I think was added after Peter made his patches).

Attachment #9537345 - Attachment description: Bug 1988534, part 1 - Add README_MOZILLA to the keep list. → Bug 1988534, part 1 - Add README_MOZILLA to the keep list for Expat.
Attachment #9537346 - Attachment description: Bug 1988534, part 2 - Upgrade from R_2_6_4 to R_2_7_3. → Bug 1988534, part 2 - Upgrade Expat from R_2_6_4 to R_2_7_3.
Attachment #9537347 - Attachment description: Bug 1988534, part 3 - Fix expat patches. → Bug 1988534, part 3 - Fix Firefox patches for Expat.
No longer blocks: 616361
No longer blocks: 1192544

It turns out the two older XML DoS issues are handled correctly by the current version of libexpat we are shipping in Firefox, but there's a bug in our harness that causes them to crash with a release assert. I've moved those to block a new bug, bug 2010288.

See Also: → 2010288

I guess we could consider uplifting this to esr140, but we probably want to wait until this update gets to release or whatever in case there are compatibility problems. For similar reasons, I don't think we want to uplift this to beta. I also marked ESR115 as WONTFIX because we didn't even uplift the prior update there, and it is almost end of life anyways.

QA Whiteboard: [qa-triage-done-c150/b149]

Also update the readme to mention git instead of hg.

Original Revision: https://phabricator.services.mozilla.com/D278890

Attachment #9550570 - Flags: approval-mozilla-esr140?

Generated using
mach vendor parser/expat/moz.yaml --patch-mode=none

Original Revision: https://phabricator.services.mozilla.com/D278891

Attachment #9550571 - Flags: approval-mozilla-esr140?
  • Mostly, this unbitrots the patches and updates line numbers.

  • Define MOZ_XML_GetMismatchedTag and MOZ_XML_ProcessingEntityValue in
    moz_xmlparse.c instead of these patches, to reduce future bitrot. This means
    that 06_report_processing_entity.patch can be removed entirely.

  • For 06_always_store_rawnames.patch, in the section from line 33 to 71 nothing
    is really changing. The old diff was just really awful for some reason. For
    the final chunk from line 72 to 86, that chunk of code with a call to
    storeRawNames in internalEntityProcessor, so it could be deleted.

  • 11_nested_entities.patch handles some kind of issue with nested entities.
    This seems to correspond to code in internalEntityProcessor where there
    is now an assertion:
    assert(parser->m_openInternalEntities == openEntity);
    So I guess it is no longer needed. Peter removed it from his patch stack.

  • Renumber the patches to account for the two removed ones.

  • In 11_no_debug_report.patch, a new struct MALLOC_TRACKER has been added.
    I had to remove new debugLevel here, as well as peakBytesAllocated, which
    as it says is only used when debugLevel is set. expat_heap_stat is also
    only used by that code, so it gets removed, too.

  • 12_unused.patch removes a bunch of unused code. The stuff around line 56
    had to change because a new function, parserBusy, that is used was added
    into the middle of a bunch of unused functions.

Original Revision: https://phabricator.services.mozilla.com/D278892

Attachment #9550572 - Flags: approval-mozilla-esr140?

This was auto generated with
./mach vendor parser/expat/moz.yaml --patch-mode=only

Original Revision: https://phabricator.services.mozilla.com/D278893

Attachment #9550573 - Flags: approval-mozilla-esr140?
Attachment #9550573 - Flags: approval-mozilla-esr140? → approval-mozilla-esr140+
Attachment #9550572 - Flags: approval-mozilla-esr140? → approval-mozilla-esr140+
Attachment #9550571 - Flags: approval-mozilla-esr140? → approval-mozilla-esr140+
Attachment #9550570 - Flags: approval-mozilla-esr140? → approval-mozilla-esr140+
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: