Closed Bug 1747114 Opened 2 years ago Closed 2 years ago

Assertion failure: idx < storage_.size(), at /builds/worker/workspace/obj-build/dist/include/mozilla/Span.h:713

Categories

(Core :: DOM: Serializers, defect)

defect

Tracking

()

VERIFIED FIXED
97 Branch
Tracking Status
firefox-esr91 --- unaffected
firefox95 --- wontfix
firefox96 --- fixed
firefox97 --- verified

People

(Reporter: tsmith, Assigned: jfkthame)

References

(Blocks 1 open bug, Regression)

Details

(4 keywords, Whiteboard: [bugmon:bisected,confirmed])

Attachments

(2 files)

Attached file testcase.html

Found while fuzzing m-c 20211219-b8d670354ba2 (--enable-address-sanitizer --enable-fuzzing)

To reproduce via Grizzly Replay:

$ pip install fuzzfetch grizzly-framework
$ python -m fuzzfetch -a --fuzzing -n firefox
$ python -m grizzly.replay ./firefox/firefox testcase.html --xvfb

Assertion failure: idx < storage_.size(), at /builds/worker/workspace/obj-build/dist/include/mozilla/Span.h:713

#0 0x7f6d5e9bcf18 in mozilla::Span<char16_t const, 18446744073709551615ul>::operator[](unsigned long) const /builds/worker/workspace/obj-build/dist/include/mozilla/Span.h:713:5
#1 0x7f6d66775ac5 in GetUnicharStringWidth(mozilla::Span<char16_t const, 18446744073709551615ul>) /gecko/dom/serializers/nsPlainTextSerializer.cpp:1815:9
#2 0x7f6d66775218 in nsPlainTextSerializer::CurrentLine::FindWrapIndexForContent(unsigned int, bool) const /gecko/dom/serializers/nsPlainTextSerializer.cpp:135:16
#3 0x7f6d667807f9 in nsPlainTextSerializer::MaybeWrapAndOutputCompleteLines() /gecko/dom/serializers/nsPlainTextSerializer.cpp:1236:22
#4 0x7f6d6677dd04 in nsPlainTextSerializer::Write(nsTSubstring<char16_t> const&) /gecko/dom/serializers/nsPlainTextSerializer.cpp:1599:7
#5 0x7f6d66778e95 in nsPlainTextSerializer::AppendText(nsIContent*, int, int) /gecko/dom/serializers/nsPlainTextSerializer.cpp:458:7
#6 0x7f6d66764724 in nsDocumentEncoder::NodeSerializer::SerializeNodeStart(nsINode&, int, int, nsINode*) const /gecko/dom/serializers/nsDocumentEncoder.cpp
#7 0x7f6d66764cf3 in nsDocumentEncoder::NodeSerializer::SerializeToStringIterative(nsINode*) const /gecko/dom/serializers/nsDocumentEncoder.cpp:981:10
#8 0x7f6d66762005 in nsDocumentEncoder::SerializeDependingOnScope(unsigned int) /gecko/dom/serializers/nsDocumentEncoder.cpp:569:10
#9 0x7f6d66767a85 in nsDocumentEncoder::EncodeToStringWithMaxLength(unsigned int, nsTSubstring<char16_t>&) /gecko/dom/serializers/nsDocumentEncoder.cpp:1397:8
#10 0x7f6d66c77501 in mozilla::EditorBase::ComputeValueInternal(nsTSubstring<char16_t> const&, unsigned int, nsTSubstring<char16_t>&) const /gecko/editor/libeditor/EditorBase.cpp:1489:17
#11 0x7f6d64adcaef in mozilla::TextEditor::ComputeTextValue(unsigned int, nsTSubstring<char16_t>&) const /builds/worker/workspace/obj-build/dist/include/mozilla/TextEditor.h:186:19
#12 0x7f6d64aabb13 in mozilla::TextControlState::GetValue(nsTSubstring<char16_t>&, bool) const /gecko/dom/html/TextControlState.cpp:2576:45
#13 0x7f6d64ab3df0 in mozilla::TextControlState::SetRangeText(nsTSubstring<char16_t> const&, unsigned int, unsigned int, mozilla::dom::SelectionMode, mozilla::ErrorResult&, mozilla::Maybe<unsigned int> const&, mozilla::Maybe<unsigned int> const&) /gecko/dom/html/TextControlState.cpp:2308:21
#14 0x7f6d64ab386e in mozilla::TextControlState::SetRangeText(nsTSubstring<char16_t> const&, mozilla::ErrorResult&) /gecko/dom/html/TextControlState.cpp:2289:3
#15 0x7f6d63e2cb32 in mozilla::dom::HTMLTextAreaElement_Binding::setRangeText(JSContext*, JS::Handle<JSObject*>, void*, JSJitMethodCallArgs const&) /builds/worker/workspace/obj-build/dom/bindings/HTMLTextAreaElementBinding.cpp:1878:28
#16 0x7f6d63e86d6d in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::NormalThisPolicy, mozilla::dom::binding_detail::ThrowExceptions>(JSContext*, unsigned int, JS::Value*) /gecko/dom/bindings/BindingUtils.cpp:3306:13
#17 0x7f6d6b9bc624 in CallJSNative /gecko/js/src/vm/Interpreter.cpp:388:13
#18 0x7f6d6b9bc624 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:475:12
#19 0x7f6d6b9a8aee in CallFromStack /gecko/js/src/vm/Interpreter.cpp:539:10
#20 0x7f6d6b9a8aee in Interpret(JSContext*, js::RunState&) /gecko/js/src/vm/Interpreter.cpp:3243:16
#21 0x7f6d6b98d8f1 in js::RunScript(JSContext*, js::RunState&) /gecko/js/src/vm/Interpreter.cpp:357:13
#22 0x7f6d6b9bc75f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:507:13
#23 0x7f6d6b9be8ab in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:552:8
#24 0x7f6d6bc3c94d in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /gecko/js/src/vm/CallAndConstruct.cpp:117:10
#25 0x7f6d63aa302f in mozilla::dom::EventHandlerNonNull::Call(mozilla::dom::BindingCallContext&, JS::Handle<JS::Value>, mozilla::dom::Event&, JS::MutableHandle<JS::Value>, mozilla::ErrorResult&) /builds/worker/workspace/obj-build/dom/bindings/EventHandlerBinding.cpp:283:37
#26 0x7f6d64791e03 in void mozilla::dom::EventHandlerNonNull::Call<nsCOMPtr<mozilla::dom::EventTarget> >(nsCOMPtr<mozilla::dom::EventTarget> const&, mozilla::dom::Event&, JS::MutableHandle<JS::Value>, mozilla::ErrorResult&, char const*, mozilla::dom::CallbackObject::ExceptionHandling, JS::Realm*) /builds/worker/workspace/obj-build/dist/include/mozilla/dom/EventHandlerBinding.h:365:12
#27 0x7f6d64790334 in mozilla::JSEventHandler::HandleEvent(mozilla::dom::Event*) /gecko/dom/events/JSEventHandler.cpp:201:12
#28 0x7f6d64757588 in mozilla::EventListenerManager::HandleEventSubType(mozilla::EventListenerManager::Listener*, mozilla::dom::Event*, mozilla::dom::EventTarget*) /gecko/dom/events/EventListenerManager.cpp:1309:22
#29 0x7f6d64758b9c in mozilla::EventListenerManager::HandleEventInternal(nsPresContext*, mozilla::WidgetEvent*, mozilla::dom::Event**, mozilla::dom::EventTarget*, nsEventStatus*, bool) /gecko/dom/events/EventListenerManager.cpp:1500:17
#30 0x7f6d64746c6e in mozilla::EventTargetChainItem::HandleEvent(mozilla::EventChainPostVisitor&, mozilla::ELMCreationDetector&) /gecko/dom/events/EventDispatcher.cpp:348:17
#31 0x7f6d647456f2 in mozilla::EventTargetChainItem::HandleEventTargetChain(nsTArray<mozilla::EventTargetChainItem>&, mozilla::EventChainPostVisitor&, mozilla::EventDispatchingCallback*, mozilla::ELMCreationDetector&) /gecko/dom/events/EventDispatcher.cpp:586:14
#32 0x7f6d647496f5 in mozilla::EventDispatcher::Dispatch(nsISupports*, nsPresContext*, mozilla::WidgetEvent*, mozilla::dom::Event*, nsEventStatus*, mozilla::EventDispatchingCallback*, nsTArray<mozilla::dom::EventTarget*>*) /gecko/dom/events/EventDispatcher.cpp:1085:11
#33 0x7f6d6474ee59 in mozilla::EventDispatcher::DispatchDOMEvent(nsISupports*, mozilla::WidgetEvent*, mozilla::dom::Event*, nsPresContext*, nsEventStatus*) /gecko/dom/events/EventDispatcher.cpp
#34 0x7f6d61ce12e7 in nsContentUtils::DispatchEvent(mozilla::dom::Document*, nsISupports*, mozilla::WidgetEvent&, mozilla::EventMessage, mozilla::CanBubble, mozilla::Cancelable, mozilla::Trusted, bool*, mozilla::ChromeOnlyDispatch) /gecko/dom/base/nsContentUtils.cpp:4341:17
#35 0x7f6d646d7de6 in DispatchTrustedEvent<mozilla::WidgetEvent> /builds/worker/workspace/obj-build/dist/include/nsContentUtils.h:1505:12
#36 0x7f6d646d7de6 in mozilla::AsyncEventDispatcher::Run() /gecko/dom/events/AsyncEventDispatcher.cpp:52:12
#37 0x7f6d5e79295f in mozilla::SchedulerGroup::Runnable::Run() /gecko/xpcom/threads/SchedulerGroup.cpp:144:20
#38 0x7f6d5e7df7d2 in mozilla::RunnableTask::Run() /gecko/xpcom/threads/TaskController.cpp:468:16
#39 0x7f6d5e7a4a1d in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /gecko/xpcom/threads/TaskController.cpp:771:26
#40 0x7f6d5e7a1f78 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /gecko/xpcom/threads/TaskController.cpp:607:15
#41 0x7f6d5e7a2689 in mozilla::TaskController::ProcessPendingMTTask(bool) /gecko/xpcom/threads/TaskController.cpp:391:36
#42 0x7f6d5e7e9161 in operator() /gecko/xpcom/threads/TaskController.cpp:124:37
#43 0x7f6d5e7e9161 in mozilla::detail::RunnableFunction<mozilla::TaskController::InitializeInternal()::$_0>::Run() /gecko/xpcom/threads/nsThreadUtils.h:531:5
#44 0x7f6d5e7c4f47 in nsThread::ProcessNextEvent(bool, bool*) /gecko/xpcom/threads/nsThread.cpp:1183:16
#45 0x7f6d5e7d05ac in NS_ProcessNextEvent(nsIThread*, bool) /gecko/xpcom/threads/nsThreadUtils.cpp:467:10
#46 0x7f6d5fce1a3f in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /gecko/ipc/glue/MessagePump.cpp:85:21
#47 0x7f6d5fb60e51 in RunInternal /gecko/ipc/chromium/src/base/message_loop.cc:331:10
#48 0x7f6d5fb60e51 in RunHandler /gecko/ipc/chromium/src/base/message_loop.cc:324:3
#49 0x7f6d5fb60e51 in MessageLoop::Run() /gecko/ipc/chromium/src/base/message_loop.cc:306:3
#50 0x7f6d66a6d3f7 in nsBaseAppShell::Run() /gecko/widget/nsBaseAppShell.cpp:137:27
#51 0x7f6d6b6da1cf in XRE_RunAppShell() /gecko/toolkit/xre/nsEmbedFunctions.cpp:864:20
#52 0x7f6d5fb60e51 in RunInternal /gecko/ipc/chromium/src/base/message_loop.cc:331:10
#53 0x7f6d5fb60e51 in RunHandler /gecko/ipc/chromium/src/base/message_loop.cc:324:3
#54 0x7f6d5fb60e51 in MessageLoop::Run() /gecko/ipc/chromium/src/base/message_loop.cc:306:3
#55 0x7f6d6b6d9402 in XRE_InitChildProcess(int, char**, XREChildData const*) /gecko/toolkit/xre/nsEmbedFunctions.cpp:701:34
#56 0x55633f6d40ed in content_process_main(mozilla::Bootstrap*, int, char**) /gecko/browser/app/../../ipc/contentproc/plugin-container.cpp:57:28
#57 0x55633f6d4518 in main /gecko/browser/app/nsBrowserApp.cpp:327:18
#58 0x7f6d829680b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16
#59 0x55633f6231b9 in _start (/home/worker/builds/m-c-20211219092930-fuzzing-asan-opt/firefox+0x5d1b9)
Flags: in-testsuite?

A Pernosco session is available here: https://pernos.co/debug/lTp57tNgM5xwHkwBhM62aw/index.html

Bugmon Analysis
Verified bug as reproducible on mozilla-central 20211221214151-f16661bf49d3.
The bug appears to have been introduced in the following build range:

Start: 86a7c7ce13bc3a43dc355c8b96358d4f042ce797 (20211008131044)
End: 061991db30de2511a5162b366222c63e9e042f27 (20211008142705)
Pushlog: https://hg.mozilla.org/integration/autoland/pushloghtml?fromchange=86a7c7ce13bc3a43dc355c8b96358d4f042ce797&tochange=061991db30de2511a5162b366222c63e9e042f27

Whiteboard: [bugmon:bisected,confirmed]

Given the regression range, I'm guessing that this might be a regression from bug 1310559. Can you take a look, Jonathan? Thanks.

Flags: needinfo?(jfkthame)
Keywords: regression
Regressed by: 1310559
Has Regression Range: --- → yes

This is a bounds check, but it is a release assert, so hopefully this isn't security sensitive.

I couldn't find any crashes on crash-stats with this in the crash reason where the stack contained "Serializer", so hopefully people aren't experiencing this crash frequently.

Unhiding since this is caught by a release assert.

Group: dom-core-security

Set release status flags based on info from the regressing bug 1310559

This is a trivial off-by-one error when checking for a surrogate pair, leading to an out-of-bounds access (safely caught by the release-assert) when we encounter a lone high surrogate in the testcase. So it wouldn't affect any well-formed content, but can be triggered by JS that puts arbitrary code units (including lone surrogates) into the DOM.

Flags: needinfo?(jfkthame)
Assignee: nobody → jfkthame
Status: NEW → ASSIGNED
Attachment #9256722 - Attachment description: Bug 1747114 - Test correectly for end-of-span before attempting to decode surrogate pair. r=m_kato → Bug 1747114 - Test correctly for end-of-span before attempting to decode surrogate pair. r=m_kato
Pushed by jkew@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/aaf128433782
Test correctly for end-of-span before attempting to decode surrogate pair. r=m_kato
Status: ASSIGNED → RESOLVED
Closed: 2 years ago
Resolution: --- → FIXED
Target Milestone: --- → 97 Branch

Bugmon Analysis
Verified bug as fixed on rev mozilla-central 20211224215233-818c851d0aeb.
Removing bugmon keyword as no further action possible. Please review the bug and re-add the keyword for further analysis.

Status: RESOLVED → VERIFIED
Keywords: bugmon

The patch landed in nightly and beta is affected.
:jfkthame, is this bug important enough to require an uplift?
If not please set status_beta to wontfix.

For more information, please visit auto_nag documentation.

Flags: needinfo?(jfkthame)

Comment on attachment 9256722 [details]
Bug 1747114 - Test correctly for end-of-span before attempting to decode surrogate pair. r=m_kato

Beta/Release Uplift Approval Request

  • User impact if declined: Possible crash if script inserts broken (unpaired) surrogate codes into DOM content.
  • Is this code covered by automated tests?: Yes
  • Has the fix been verified in Nightly?: Yes
  • 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): Trivial fix for erroneous length-check.
  • String changes made/needed:
Flags: needinfo?(jfkthame)
Attachment #9256722 - Flags: approval-mozilla-beta?

Comment on attachment 9256722 [details]
Bug 1747114 - Test correctly for end-of-span before attempting to decode surrogate pair. r=m_kato

Approved for 96.0b10

Attachment #9256722 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: