Closed Bug 1933023 (CVE-2025-0241) Opened 9 months ago Closed 9 months ago

Assertion failure: has<CharT>(), at js/src/builtin/intl/Segmenter.h:141

Categories

(Core :: JavaScript: Internationalization API, defect, P2)

defect

Tracking

()

RESOLVED FIXED
135 Branch
Tracking Status
firefox-esr115 --- unaffected
firefox-esr128 134+ fixed
firefox133 --- wontfix
firefox134 + fixed
firefox135 + fixed

People

(Reporter: sm-bugs, Assigned: jandem)

References

(Blocks 2 open bugs, Regression)

Details

(Keywords: regression, reporter-external, sec-moderate, Whiteboard: [adv-main134+][adv-ESR128.6+])

Attachments

(4 files)

Steps to reproduce:

Version: ee42ec590725439d33792bc8657d60f080786b2e
Args: js --fuzzing-safe <test-case>
Test case:

a = {
  "twoByte" : true}
b = newString("12345678901234567890", a)
c = Intl.Segmenter
d = new c
e = d.segment(b)
e.containing()
f = {}
Object.defineProperty(f, "12345678901234567890",
                      {value : e})[b].containing()

Actual results:

Assertion failure: has<CharT>(), at js/src/builtin/intl/Segmenter.h:141

#0 0x557462a3e128 in unsigned char* js::SegmentsStringChars::data<unsigned char>() const js/src/builtin/intl/Segmenter.h:141:5
#1 0x557462a3e128 in auto* CreateBreakIterator<GraphemeClusterSegmenterBreakIteratorLatin1, js::SegmentsObject>(JS::Handle<js::SegmentsObject*>) js/src/builtin/intl/Segmenter.cpp:753:29
#2 0x557462a3e128 in bool EnsureBreakIterator<js::SegmentsObject>(JSContext*, JS::Handle<js::SegmentsObject*>, int) js/src/builtin/intl/Segmenter.cpp:792:15
#3 0x557462a3e128 in js::ArrayObject* FindSegmentBoundaries<js::SegmentsObject>(JSContext*, JS::Handle<js::SegmentsObject*>, int) js/src/builtin/intl/Segmenter.cpp:857:8
#4 0x557462a3e128 in js::intl_FindSegmentBoundaries(JSContext*, unsigned int, JS::Value*) js/src/builtin/intl/Segmenter.cpp:955:18
#5 0x55746216521e in CallJSNative(JSContext*, bool (*)(JSContext*, unsigned int, JS::Value*), js::CallReason, JS::CallArgs const&) js/src/vm/Interpreter.cpp:532:13
#6 0x55746216447f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) js/src/vm/Interpreter.cpp:628:12
#7 0x55746217ea1c in js::CallFromStack(JSContext*, JS::CallArgs const&, js::CallReason) js/src/vm/Interpreter.cpp:700:10
#8 0x55746217ea1c in js::Interpret(JSContext*, js::RunState&) js/src/vm/Interpreter.cpp:3329:16
#9 0x5574621632b3 in js::RunScript(JSContext*, js::RunState&) js/src/vm/Interpreter.cpp:502:13
#10 0x557462168661 in js::ExecuteKernel(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, js::AbstractFramePtr, JS::MutableHandle<JS::Value>) js/src/vm/Interpreter.cpp:893:13
#11 0x557462168e6c in js::Execute(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, JS::MutableHandle<JS::Value>) js/src/vm/Interpreter.cpp:926:10
#12 0x557462363a79 in ExecuteScript(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSScript*>, JS::MutableHandle<JS::Value>) js/src/vm/CompilationAndEvaluation.cpp:496:10
#13 0x557462363cf7 in JS_ExecuteScript(JSContext*, JS::Handle<JSScript*>) js/src/vm/CompilationAndEvaluation.cpp:520:10
#14 0x5574620c11ce in RunFile(JSContext*, char const*, _IO_FILE*, CompileUtf8, bool, bool) js/src/shell/js.cpp:1324:10
#15 0x5574620c0275 in Process(JSContext*, char const*, bool, FileKind) js/src/shell/js.cpp
#16 0x5574620792c9 in ProcessArgs(JSContext*, js::cli::OptionParser*) js/src/shell/js.cpp:11801:10
#17 0x5574620792c9 in Shell(JSContext*, js::cli::OptionParser*) js/src/shell/js.cpp:12069:12
#18 0x55746206fecd in main js/src/shell/js.cpp:12495:12
#19 0x7fe55326d3b7 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#20 0x7fe55326d47a in __libc_start_main csu/../csu/libc-start.c:360:3
#21 0x557462039398 in _start (reproducebuild/dist/bin/js+0x1bed398) (BuildId: 8c078c7b81363595dd2ca0b88818a732)
Blocks: 1903968
Group: firefox-core-security → core-security
Component: Untriaged → JavaScript Engine
Product: Firefox → Core
Version: Firefox 132 → Trunk
Group: core-security → javascript-core-security
Component: JavaScript Engine → JavaScript: Internationalization API
Flags: needinfo?(jdemooij)

Reduced test below.

The segments object has the JS string and SegmentsStringChars. The JS string is initially a two-byte string but is later turned into a Latin1 atom-ref string. This confuses EnsureBreakIterator.

var str = "12345678901234567890";
var strTwoByte = newString(str, {twoByte: true});
var segments = new Intl.Segmenter().segment(strTwoByte);
segments.containing();
var obj = {[strTwoByte]: 1};
segments.containing();
Flags: needinfo?(jdemooij)
Assignee: nobody → jdemooij
Status: NEW → ASSIGNED

Regression from bug 1881995.

Regressed by: 1881995
No longer regressed by: 1423593

Yes this goes back to atom-refs (bug 1881995) but was uncovered by the patch for bug 1928407 because it added this assertion.

I'm not sure what security rating to give this. We call into ICU4X with the wrong character type but I don't know if it's exploitable. Interpreting a char16_t buffer as an unsigned char buffer probably doesn't read out-of-bounds memory, but I don't know what else ICU4X is doing with the string chars.

We should probably uplift bug 1928407 and this patch to ESR 128.

Keywords: sec-moderate
Flags: sec-bounty?
Blocks: sm-security
Severity: -- → S3
Priority: -- → P2
Attachment #9440175 - Flags: approval-mozilla-esr128?

Comment on attachment 9439717 [details]
Bug 1933023 - Check whether the segment's chars are Latin1 instead of the JS string. r?anba!

Beta/Release Uplift Approval Request

  • User impact if declined/Reason for urgency: Broken websites and maybe crashes or security issues.
  • Is this code covered by automated tests?: Yes
  • Has the fix been verified in Nightly?: No
  • Needs manual test from QE?: No
  • If yes, steps to reproduce:
  • List of other uplifts needed: None
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky): Small patch and pretty self-contained.
  • String changes made/needed:
  • Is Android affected?: Yes
Attachment #9439717 - Flags: approval-mozilla-beta?
Pushed by jdemooij@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/ee678c4855f6 Check whether the segment's chars are Latin1 instead of the JS string. r=anba
Group: javascript-core-security → core-security-release
Status: ASSIGNED → RESOLVED
Closed: 9 months ago
Resolution: --- → FIXED
Target Milestone: --- → 135 Branch
Attachment #9439717 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
QA Whiteboard: [post-critsmash-triage]
Flags: qe-verify-
Flags: needinfo?(jdemooij)
Flags: sec-bounty? → sec-bounty+

Comment on attachment 9440175 [details]
Bug 1933023 (patch for ESR128) - Check whether the segment's chars are Latin1 instead of the JS string. r?anba!

Approved for 128.6esr.

Attachment #9440175 - Flags: approval-mozilla-esr128? → approval-mozilla-esr128+
Whiteboard: [adv-main134+][adv-ESR128.6+]
Alias: CVE-2025-0241
Flags: needinfo?(jdemooij)
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: