Closed Bug 1763076 Opened 4 years ago Closed 4 years ago

Crash in [@ OOM | large | NS_ABORT_OOM | nsTArray_base<T>::EnsureCapacity<T> | nsTArray_Impl<T>::AppendElementsInternal<T> | nsHtml5Highlighter::AppendCharacters]

Categories

(Core :: DOM: HTML Parser, defect)

defect

Tracking

()

RESOLVED FIXED
101 Branch
Tracking Status
firefox-esr91 --- wontfix
firefox99 --- wontfix
firefox100 --- wontfix
firefox101 --- fixed

People

(Reporter: manuel, Assigned: hsivonen)

Details

(Keywords: crash)

Crash Data

Attachments

(1 file)

Maybe Fission related. (DOMFissionEnabled=1)

Steps to reproduce:

  1. download large html file (77MB): curl https://searchfox.org/mozilla-central/source/__GENERATED__/xpcom/reflect/xptinfo/xptdata.cpp#163247 > 123.html
  2. open that file with view source, e.g. open view-source:file:///home/user/123.html
  3. wait some time (for me 15 seconds) viewing a blank page until the crash happens

Edit: Instead of 1. and 2. opening view-source:https://searchfox.org/mozilla-central/source/__GENERATED__/xpcom/reflect/xptinfo/xptdata.cpp#163247 is also enough for me.

Crash report: https://crash-stats.mozilla.org/report/index/d5f90505-a204-440e-a505-9f6690220405

MOZ_CRASH Reason: MOZ_CRASH(OOM)

Top 10 frames of crashing thread:

0 libxul.so NS_ABORT_OOM /build/firefox/src/firefox-98.0.2/xpcom/base/nsDebugImpl.cpp:616
1 libxul.so nsTArrayInfallibleAllocator::ResultTypeProxy nsTArray_base<nsTArrayInfallibleAllocator, nsTArray_RelocateUsingMemutils>::EnsureCapacity<nsTArrayInfallibleAllocator> /build/firefox/src/firefox-98.0.2/xpcom/ds/nsTArray-inl.h:167
2 libxul.so nsHtml5TreeOperation* nsTArray_Impl<nsHtml5TreeOperation, nsTArrayInfallibleAllocator>::AppendElementsInternal<nsTArrayInfallibleAllocator> /build/firefox/src/firefox-98.0.2/xpcom/ds/nsTArray.h:1779
3 libxul.so nsHtml5Highlighter::AppendCharacters /build/firefox/src/firefox-98.0.2/parser/html/nsHtml5Highlighter.cpp:703
4 libxul.so nsHtml5Highlighter::FlushChars /build/firefox/src/firefox-98.0.2/parser/html/nsHtml5Highlighter.cpp:610
5 libxul.so nsHtml5Highlighter::EndSpanOrA /build/firefox/src/firefox-98.0.2/parser/html/nsHtml5Highlighter.cpp:532
6 libxul.so nsHtml5Highlighter::Transition /build/firefox/src/firefox-98.0.2/parser/html/nsHtml5Highlighter.cpp:366
7 libxul.so int nsHtml5Tokenizer::stateLoop<nsHtml5ViewSourcePolicy> /build/firefox/src/firefox-98.0.2/parser/html/nsHtml5Tokenizer.cpp:618
8 libxul.so nsHtml5Tokenizer::tokenizeBuffer /build/firefox/src/firefox-98.0.2/parser/html/nsHtml5Tokenizer.cpp:442
9 libxul.so nsHtml5StreamParser::ParseAvailableData /build/firefox/src/firefox-98.0.2/parser/html/nsHtml5StreamParser.cpp:2362

The input here has a massive amount of markup. The view source highlighter splits each tag into multiple highlighed parts, so the number of tree operations generated is considerably larger than in the non-view source mode.

View Source mode doesn't really bother with incremental rendering: In buffers tree ops until a huge flush on EOF. In this case, the queue tries to grow larger than nsTArray allows.

I can move the OOM crash away from the reported point by checking the queue length at the end of each Necko buffer and flushing if the length exceeds some arbitrary threshold.

However, in that case, I see a similar nsTArray-too-large OOM crash on the main thread if the main thread doesn't manage to drain its operation queue fast enough. There's is also an intermediate step where an nsTArray might grow too large if not moved to the next stage soon enough.

It's probably worthwhile to make the parser thread flush the ops more often. However, considering that this is a case of rare huge input causing denial-of-service OOM in the Web content process and nothing worse than that, I think it's probably not a good use of engineering time to build a mechanism for the main thread to cause the parser thread to refrain from producing more operations before the main thread has caught up with the processing the previous ones.

In any case: The root cause doesn't look Fission-related, but Fission mitigates the severity (by OOMing just one of the many content processes). Notably, the OOM doesn't come from actual allocator OOM but from a max size check in nsTArray. I think this should be lower than S2.

(No test case, because testing unsuited for CI both in terms of space and time.)

I'm not particularly happy about the amount of code relative to the probability of the OOM crash, but the patch should at least avoid a crash. Given how unusual the situation is, I think it's not worthwhile to create a mechanism for the main thread to ask the parser thread to slow down with the generation of operations.

Try run to see that I didn't break something obvious by typo or something:
https://treeherder.mozilla.org/#/jobs?repo=try&revision=07cb1f417e059f838c8f4f8a0e15ca2148e7e089

Assignee: nobody → hsivonen
Status: NEW → ASSIGNED
Pushed by hsivonen@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/aa30bc1b369b Avoid OOM crashes when there's a massive number of tree operations. r=edgar

Backed out changeset aa30bc1b369b (bug 1763076) for causing assertion failure in parser/html/nsHtml5TreeOpExecutor.cpp

Backout link: https://hg.mozilla.org/integration/autoland/rev/a30fcbc9cfae7633618db2e04218d103b372b708

Push with failures

Failure log

Flags: needinfo?(hsivonen)

Looks like an upgrade from NS_ASSERTION to MOZ_ASSERT was premature. I'll downgrade.

In any case, I'm setting the severity to S3, because this is an issue of huge input causing a non-exploitable crash in a feature that's not part of regular browsing (that is, this requires viewing source).

Severity: S2 → S3
Pushed by hsivonen@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/fc69d1c91df3 Avoid OOM crashes when there's a massive number of tree operations. r=edgar
Status: ASSIGNED → RESOLVED
Closed: 4 years ago
Resolution: --- → FIXED
Target Milestone: --- → 101 Branch
Flags: needinfo?(hsivonen)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: