Crash [@ js::Shape::getObjectClass] with use-after-free

RESOLVED DUPLICATE of bug 756851

Status

()

Core
JavaScript Engine
--
critical
RESOLVED DUPLICATE of bug 756851
6 years ago
5 years ago

People

(Reporter: decoder, Unassigned)

Tracking

(Blocks: 1 bug, {crash, sec-critical, testcase})

Trunk
x86
Linux
crash, sec-critical, testcase
Points:
---
Bug Flags:
in-testsuite -

Firefox Tracking Flags

(Not tracked)

Details

(Whiteboard: js-triage-needed [sg:dupe 756851], crash signature)

(Reporter)

Description

6 years ago
The following test crashes on mozilla-central revision d55df2c9c037 (options -m -n -a):


var lfcode = new Array();
lfcode.push("const libdir = \"/srv/repos/mozilla-central/js/src/jit-test/lib/\";");
lfcode.push("");
lfcode.push("gczeal(2); printStatus ();");
lfcode.push("jsTestDriverEnd();");
lfcode.push("const libdir = \"/srv/repos/mozilla-central/js/src/jit-test/lib/\";");
lfcode.push("schedulegc = function() { }; gcslice = function() { }; selectforgc = function() { };");
lfcode.push("jsTestDriverEnd();");
lfcode.push("}");
lfcode.push("const libdir = \"/srv/repos/mozilla-central/js/src/jit-test/lib/\";");
lfcode.push("var appendToActual = function(s) {");
lfcode.push("\
function isNaN () { function toJSON() {} }\
a ? f(this.abstract, 3) : a;\
");
lfcode.push("jsTestDriverEnd();");
var lfRunTypeId = -1;
while (true) {
        var file = lfcode.shift(); if (file == undefined) { break; }
        if (file == "evaluate") {
        } else {
                loadFile(file);
        }
}
function loadFile(lfVarx) {
        try {
                if (lfVarx.substr(-3) == ".js") {
                        switch (lfRunTypeId) {
                                case 4: eval("(function() { " + read(lfVarx) + " })();"); break;
                        }
                } else if (!isNaN(lfVarx)) {
                        lfRunTypeId = lfVarx;
                } else {
                        switch (lfRunTypeId) {
                                default: evaluate(lfVarx);
                        }
                }
        } catch (lfVare) {
                print(lfVare);
        }
}


Valgrind log:


==42745== Invalid read of size 4
==42745==    at 0x804D2A5: js::Shape::getObjectClass() const (jsscope.h:609)
==42745==    by 0x804E37E: js::ObjectImpl::getClass() const (ObjectImpl-inl.h:245)
==42745==    by 0x804E392: js::ObjectImpl::hasClass(js::Class const*) const (ObjectImpl-inl.h:257)
==42745==    by 0x804E7F4: JSObject::isFunction() const (jsobjinlines.h:808)
==42745==    by 0x839EF97: js::mjit::Compiler::inlineNativeFunction(unsigned int, bool) (FastBuiltins.cpp:916)
==42745==    by 0x834E620: js::mjit::Compiler::generateMethod() (Compiler.cpp:2617)
==42745==    by 0x83445E2: js::mjit::Compiler::performCompilation() (Compiler.cpp:549)
==42745==    by 0x8343325: js::mjit::Compiler::compile() (Compiler.cpp:146)
==42745==    by 0x83463D4: js::mjit::CanMethodJIT(JSContext*, JSScript*, unsigned char*, bool, js::mjit::CompileRequest) (Compiler.cpp:1000)
==42745==    by 0x83E60B4: UncachedInlineCall(js::VMFrame&, js::InitialFrameFlags, void**, bool*, unsigned int) (InvokeHelpers.cpp:308)
==42745==    by 0x83E685B: js::mjit::stubs::UncachedCallHelper(js::VMFrame&, unsigned int, bool, js::mjit::stubs::UncachedCallResult*) (InvokeHelpers.cpp:459)
==42745==    by 0x83CAE4B: js::mjit::CallCompiler::update() (MonoIC.cpp:961)
==42745==  Address 0xdadadada is not stack'd, malloc'd or (recently) free'd


The test is quite fragile, removing the print() statement at the end renders it useless already. Assuming sec-critical due to use-after-free as indicated in Valgrind trace.
(Reporter)

Comment 1

6 years ago
autoBisect shows this is probably related to the following changeset:

The first bad revision is:
changeset:   94413:f45eec2bd4c7
user:        Luke Wagner
date:        Tue Dec 20 17:42:45 2011 -0800
summary:     Bug 690135 - create scope objects eagerly or not at all (r=jimb)

Comment 2

6 years ago
Does this only repro on x86 Linux?  I tried on OSX 10.6 but wasn't able to hit anything.

Also, did you reduce the test-case using the crash or the valgrind error?
(Reporter)

Comment 3

6 years ago
(In reply to Luke Wagner [:luke] from comment #2)
> Does this only repro on x86 Linux?  I tried on OSX 10.6 but wasn't able to
> hit anything.
> 
> Also, did you reduce the test-case using the crash or the valgrind error?

I only tried this on x86 Linux and reduced it with the crash, not with Valgrind. If you cannot repro at all even on Linux, then you can of course debug it on the fuzzer machine itself :)

Comment 4

6 years ago
Do you suppose you could auto-reduce it using Valgrind?  I suspect that would allow reducing these tests that otherwise are so flaky.
(Reporter)

Comment 5

6 years ago
(In reply to Luke Wagner [:luke] from comment #4)
> Do you suppose you could auto-reduce it using Valgrind?  I suspect that
> would allow reducing these tests that otherwise are so flaky.

When I remove the "print" statement at the end, the test does not show any invalid reads/writes at all under Valgrind either. It does show

==33316== Conditional jump or move depends on uninitialised value(s)
==33316==    at 0x8050EE7: Evaluate(JSContext*, unsigned int, JS::Value*) (js.cpp:912)

but I'm not sure if that is related. I can reduce based on that criteria but I did not do so on purpose so far.

Comment 6

6 years ago
I saw that conditional jump in Evaluate, it is a pretty simple bug in Evaluate (trivial fix) and unrelated.

Comment 7

6 years ago
This is fixed on tip and I bisected the fix to
  https://hg.mozilla.org/mozilla-central/rev/fb3036d9b9e6
Bill says it is safe to dup so dup I will.
Status: NEW → RESOLVED
Last Resolved: 6 years ago
Resolution: --- → DUPLICATE
Duplicate of bug: 756851
Group: core-security
Whiteboard: js-triage-needed → js-triage-needed [sg:dupe 756851]
(Reporter)

Comment 8

5 years ago
Adding the test in bug 756851.
Flags: in-testsuite-
You need to log in before you can comment on or make changes to this bug.