Closed
Bug 907118
Opened 11 years ago
Closed 11 years ago
Crash in [@ JSRope::getCharsNonDestructiveInternal(js::ThreadSafeContext*, js::ScopedJSFreePtr<wchar_t>&, bool) ]
Categories
(Core :: JavaScript Engine, defect)
Tracking
()
RESOLVED
FIXED
mozilla26
People
(Reporter: over68, Assigned: luke)
References
Details
(Keywords: regression)
Crash Data
Attachments
(1 file)
2.98 KB,
patch
|
bhackett1024
:
review+
|
Details | Diff | Splinter Review |
User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0 (Beta/Release)
Build ID: 20130819030205
Steps to reproduce:
1- Go to http://dl.dropboxusercontent.com/u/95157096/85f61cf7/45gjzZVc.html
2- Go to "about:memory" then press "Measure".
Actual results:
Browser crash.
Crash Report: bp-f6efbca7-9666-4c43-aeec-d69c52130820
This happen since the version 26.0a1 (2013-08-06).
http://hg.mozilla.org/mozilla-central/rev/a0dd80f800e2
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0
Build ID: 20130806030203
Summary: Crash [@ JSRope::getCharsNonDestructiveInternal(js::ThreadSafeContext*, js::ScopedJSFreePtr<wchar_t>&, bool) ] → Crash in [@ JSRope::getCharsNonDestructiveInternal(js::ThreadSafeContext*, js::ScopedJSFreePtr<wchar_t>&, bool) ]
![]() |
||
Updated•11 years ago
|
tracking-firefox26:
--- → ?
Keywords: regression,
regressionwindow-wanted
![]() |
||
Updated•11 years ago
|
Crash Signature: [@ JSRope::getCharsNonDestructiveInternal(js::ThreadSafeContext*, js::ScopedJSFreePtr<wchar_t>&, bool)]
![]() |
||
Updated•11 years ago
|
Keywords: regressionwindow-wanted
![]() |
||
Updated•11 years ago
|
Component: General → about:memory
Product: Core → Toolkit
![]() |
||
Updated•11 years ago
|
Status: UNCONFIRMED → NEW
Ever confirmed: true
s-s per jlebar's request
Group: core-security
Comment 3•11 years ago
|
||
Here's the valgrind trace.
Looks like we're writing past the end of a malloc'ed string.
> Invalid write of size 2
> at 0x7F35FD3: JSRope::getCharsNonDestructiveInternal(js::ThreadSafeContext*, js::ScopedJSFreePtr<unsigned short>&, bool) const (PodOperations.h:78)
> by 0x7F35E87: JSRope::getCharsNonDestructive(js::ThreadSafeContext*, js::ScopedJSFreePtr<unsigned short>&) const (String.cpp:170)
> by 0x7FF3D50: js::detail::HashTable<js::HashMapEntry<JSString*, JS::StringInfo>, js::HashMap<JSString*, JS::StringInfo, js::StringHashPolicy, js::SystemAllocPolicy>::MapHashPolicy, js::SystemAllocPolicy>::prepareHash(JSString* const&) (String.h:1083)
> by 0x7FF20B1: StatsCellCallback(JSRuntime*, void*, void*, JSGCTraceKind, unsigned long) (HashTable.h:1373)
> by 0x7EFFA91: js::IterateZonesCompartmentsArenasCells(JSRuntime*, void*, void (*)(JSRuntime*, void*, JS::Zone*), void (*)(JSRuntime*, void*, JSCompartment*), void (*)(JSRuntime*, void*, js::gc::Arena*, JSGCTraceKind, unsigned long), void (*)(JSRuntime*, void*, void*, JSGCTraceKind, unsigned long)) (Iteration.cpp:52)
> by 0x7FF1A2F: JS::CollectRuntimeStats(JSRuntime*, JS::RuntimeStats*, JS::ObjectPrivateVisitor*) (jsmemorymetrics.cpp:473)
> by 0x72BD826: xpc::JSMemoryMultiReporter::CollectReports(nsDataHashtable<nsUint64HashKey, nsCString>*, nsDataHashtable<nsUint64HashKey, nsCString>*, nsIMemoryMultiReporterCallback*, nsISupports*) (XPCJSRuntime.cpp:2576)
> by 0x703C248: nsWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback*, nsISupports*) (nsWindowMemoryReporter.cpp:359)
> by 0x799A1C5: NS_InvokeByIndex (xptcinvoke_x86_64_unix.cpp:162)
> by 0x72D3752: XPCWrappedNative::CallMethod(XPCCallContext&, XPCWrappedNative::CallMode) (XPCWrappedNative.cpp:2808)
> by 0x72D7EB9: XPC_WN_CallMethod(JSContext*, unsigned int, JS::Value*) (XPCWrappedNativeJSOps.cpp:1315)
> by 0x7EF850B: js::Invoke(JSContext*, JS::CallArgs, js::MaybeConstruct) (jscntxtinlines.h:218)
>
> Address 0x1f273e32 is 0 bytes after a block of size 146 alloc'd
> at 0x402D954: malloc (vg_replace_malloc.c:291)
> by 0x7F35F04: JSRope::getCharsNonDestructiveInternal(js::ThreadSafeContext*, js::ScopedJSFreePtr<unsigned short>&, bool) const (Utility.h:141)
> by 0x7F35E87: JSRope::getCharsNonDestructive(js::ThreadSafeContext*, js::ScopedJSFreePtr<unsigned short>&) const (String.cpp:170)
> by 0x7FF3D50: js::detail::HashTable<js::HashMapEntry<JSString*, JS::StringInfo>, js::HashMap<JSString*, JS::StringInfo, js::StringHashPolicy, js::SystemAllocPolicy>::MapHashPolicy, js::SystemAllocPolicy>::prepareHash(JSString* const&) (String.h:1083)
> by 0x7FF20B1: StatsCellCallback(JSRuntime*, void*, void*, JSGCTraceKind, unsigned long) (HashTable.h:1373)
> by 0x7EFFA91: js::IterateZonesCompartmentsArenasCells(JSRuntime*, void*, void (*)(JSRuntime*, void*, JS::Zone*), void (*)(JSRuntime*, void*, JSCompartment*), void (*)(JSRuntime*, void*, js::gc::Arena*, JSGCTraceKind, unsigned long), void (*)(JSRuntime*, void*, void*, JSGCTraceKind, unsigned long)) (Iteration.cpp:52)
> by 0x7FF1A2F: JS::CollectRuntimeStats(JSRuntime*, JS::RuntimeStats*, JS::ObjectPrivateVisitor*) (jsmemorymetrics.cpp:473)
> by 0x72BD826: xpc::JSMemoryMultiReporter::CollectReports(nsDataHashtable<nsUint64HashKey, nsCString>*, nsDataHashtable<nsUint64HashKey, nsCString>*, nsIMemoryMultiReporterCallback*, nsISupports*) (XPCJSRuntime.cpp:2576)
> by 0x703C248: nsWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback*, nsISupports*) (nsWindowMemoryReporter.cpp:359)
> by 0x799A1C5: NS_InvokeByIndex (xptcinvoke_x86_64_unix.cpp:162)
> by 0x72D3752: XPCWrappedNative::CallMethod(XPCCallContext&, XPCWrappedNative::CallMode) (XPCWrappedNative.cpp:2808)
> by 0x72D7EB9: XPC_WN_CallMethod(JSContext*, unsigned int, JS::Value*) (XPCWrappedNativeJSOps.cpp:1315)
Comment 4•11 years ago
|
||
Given that it's complaining about PodOperations.h, it seems that it's the PodCopy here that's problematic:
> size_t len = node->length();
> PodCopy(pos, node->asLinear().chars(), len);
> pos += len;
Comment 5•11 years ago
|
||
Yeah, this patch hits its MOZ_CRASH(), so somehow this rope has more chars than its length().
>diff --git a/js/src/vm/String.cpp b/js/src/vm/String.cpp
>index 141db69..23ab415 100644
>--- a/js/src/vm/String.cpp
>+++ b/js/src/vm/String.cpp
>@@ -181,16 +181,17 @@ JSRope::getCharsNonDestructiveInternal(ThreadSafeContext *cx, ScopedJSFreePtr<js
> bool nullTerminate) const
> {
> /*
> * Perform non-destructive post-order traversal of the rope, splatting
> * each node's characters into a contiguous buffer.
> */
>
> size_t n = length();
>+ size_t observedLength = 0;
> jschar *s;
> if (cx)
> s = cx->pod_malloc<jschar>(n + 1);
> else
> s = js_pod_malloc<jschar>(n + 1);
>
> if (!s)
> return false;
>@@ -228,16 +229,21 @@ JSRope::getCharsNonDestructiveInternal(ThreadSafeContext *cx, ScopedJSFreePtr<js
> * stack. Non-leaf nodes in the rope contain no value to be
> * consumed.
> */
> nodeStack.popBack();
> }
> } else {
> /* For leaf nodes, copy the characters into the buffer. */
> size_t len = node->length();
>+ observedLength += len;
>+ if (observedLength >= n) {
>+ MOZ_CRASH();
>+ }
>+
> PodCopy(pos, node->asLinear().chars(), len);
> pos += len;
>
> nodeStack.popBack();
> }
>
> prev = node;
> }
Updated•11 years ago
|
Assignee: nobody → general
Group: core-security
Component: about:memory → JavaScript Engine
Product: Toolkit → Core
Comment 6•11 years ago
|
||
o/~ You do the hokey pokey and you hide the bug again o/~
Group: core-security
Comment 7•11 years ago
|
||
(In reply to Jeff Walden [:Waldo] (remove +bmo to email) from comment #6)
> o/~ You do the hokey pokey and you hide the bug again o/~
Yeah, what the heck?
Anyway, this looks like a bug in JS; I don't think I'm the right person to investigate this further.
Comment 8•11 years ago
|
||
Brian, could you take a look? Shu is on PTO this week.
Flags: needinfo?(bhackett1024)
Comment 9•11 years ago
|
||
If that crash is hitting then it seems like a bug in the string code or a misunderstood invariant about how ropes are structured. I don't know the string code or what could cause that crash to trigger.
Flags: needinfo?(bhackett1024) → needinfo?(luke)
![]() |
Assignee | |
Comment 10•11 years ago
|
||
Ropes are dags and this traversal assumes they are trees (using rope->leftChild() == prev to detect "am I coming from the left child" means an iloop when rope->rightChild() == rope->leftChild()).
I'll take the bug; this algorithm should be rewritten not to do any of this 'prev' funny business. I'm also going to rename this function to something more befitting of the massive performance hazard it entails.
Assignee: general → luke
Flags: needinfo?(luke)
![]() |
Assignee | |
Comment 11•11 years ago
|
||
and it leaks on OOM
![]() |
Assignee | |
Comment 12•11 years ago
|
||
I'm pretty sure this isn't s-s since, afaics, this is only called from the memory reporter and when we are off the main thread and use ScopedThreadSafeStringInspector (which is only off-main-thread browser startup script parsing, which obviously isn't hitting this case, probably b/c it only operates on atoms, and PJS, which is not enabled).
Attachment #794048 -
Flags: review?(bhackett1024)
Comment 13•11 years ago
|
||
I can't speak to the other use, but there's no way for a page to trigger a memory report except by asking the user to open about:memory and click "measure", so I'm OK saying that's not s-s.
Updated•11 years ago
|
Attachment #794048 -
Flags: review?(bhackett1024) → review+
![]() |
Assignee | |
Comment 14•11 years ago
|
||
Updated•11 years ago
|
Group: core-security
Comment 15•11 years ago
|
||
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla26
Updated•11 years ago
|
tracking-firefox26:
? → ---
You need to log in
before you can comment on or make changes to this bug.
Description
•