Closed Bug 1214970 Opened 6 years ago Closed 6 years ago

Assertion failure: map.count() == inlCount, at js/src/ds/InlineMap.h:70 Crash [@ js::HeapPtr<JSAtom*>::init(JSAtom*)] with heap-buffer-overflow

Categories

(Core :: JavaScript Engine, defect)

x86
Linux
defect
Not set
critical

Tracking

()

VERIFIED FIXED
mozilla44
Tracking Status
firefox43 --- unaffected
firefox44 --- verified
firefox-esr38 --- unaffected

People

(Reporter: decoder, Assigned: efaust)

References

Details

(5 keywords, Whiteboard: [fuzzblocker] [jsbugmon:update,ignore])

Crash Data

Attachments

(1 file)

The following testcase crashes on mozilla-central revision 11ff0ccb7d59 (build with --enable-optimize --enable-posix-nspr-emulation --enable-valgrind --enable-gczeal --target=i686-pc-linux-gnu --disable-tests --enable-debug, run with --fuzzing-safe --no-threads --disable-oom-functions):

var NonEscapeCharacter = ["\a", "\c", "\d", "\e", "\g", "\h", "\i", idx, "\k", "\l", "\m", "\o", "\p", "\q", "\s", "\w", "\y", "\z"];
new class {} ('#' + NonEscapeCharacter[index] + ' ');



Backtrace:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x087fdb21 in js::InlineMap<JSAtom*, unsigned int, 24u>::switchToMap (this=this@entry=0xf72af040) at js/src/ds/InlineMap.h:70
#1  0x087fdb9f in js::InlineMap<JSAtom*, unsigned int, 24u>::switchAndAdd (this=this@entry=0xf72af040, key=@0xff809014: 0xf5d00210, value=@0xff808fa0: 24) at js/src/ds/InlineMap.h:77
#2  0x087fe40f in add (value=@0xff808fa0: 24, key=@0xff809014: 0xf5d00210, p=..., this=0xf72af040) at js/src/ds/InlineMap.h:253
#3  js::frontend::BytecodeEmitter::makeAtomIndex (this=this@entry=0xff80a1e4, atom=atom@entry=0xf5d00210, indexp=indexp@entry=0xff809020) at js/src/frontend/BytecodeEmitter.h:258
#4  0x087e5f82 in js::frontend::BytecodeEmitter::emitAtomOp (this=0xff80a1e4, atom=0xf5d00210, op=JSOP_STRING) at js/src/frontend/BytecodeEmitter.cpp:1049
#5  0x087ea148 in js::frontend::BytecodeEmitter::emitTree (this=this@entry=0xff80a1e4, pn=pn@entry=0xf727cc70) at js/src/frontend/BytecodeEmitter.cpp:8010
#6  0x087e9f5c in js::frontend::BytecodeEmitter::emitTree (this=this@entry=0xff80a1e4, pn=pn@entry=0xf727cc48) at js/src/frontend/BytecodeEmitter.cpp:7799
#7  0x087f5b1f in js::frontend::BytecodeEmitter::emitCallOrNew (this=0xff80a1e4, pn=0xf727cb30) at js/src/frontend/BytecodeEmitter.cpp:6766
#8  0x087ea0f1 in js::frontend::BytecodeEmitter::emitTree (this=this@entry=0xff80a1e4, pn=pn@entry=0xf727cb30) at js/src/frontend/BytecodeEmitter.cpp:7886
#9  0x087f3bcb in js::frontend::BytecodeEmitter::emitStatement (this=this@entry=0xff80a1e4, pn=pn@entry=0xf727cc98) at js/src/frontend/BytecodeEmitter.cpp:6424
#10 0x087ea4cf in js::frontend::BytecodeEmitter::emitTree (this=this@entry=0xff80a1e4, pn=pn@entry=0xf727cc98) at js/src/frontend/BytecodeEmitter.cpp:7723
#11 0x087f3ab3 in js::frontend::BytecodeEmitter::emitStatementList (this=this@entry=0xff80a1e4, pn=pn@entry=0xf727cae0, top=top@entry=251) at js/src/frontend/BytecodeEmitter.cpp:6368
#12 0x087ea228 in js::frontend::BytecodeEmitter::emitTree (this=this@entry=0xff80a1e4, pn=0xf727cae0) at js/src/frontend/BytecodeEmitter.cpp:7719
#13 0x087eea50 in js::frontend::BytecodeEmitter::emitIf (this=this@entry=0xff80a1e4, pn=pn@entry=0xf727ccc0) at js/src/frontend/BytecodeEmitter.cpp:5118
#14 0x087e9b11 in js::frontend::BytecodeEmitter::emitTree (this=this@entry=0xff80a1e4, pn=pn@entry=0xf727ccc0) at js/src/frontend/BytecodeEmitter.cpp:7655
#15 0x087f3ab3 in js::frontend::BytecodeEmitter::emitStatementList (this=this@entry=0xff80a1e4, pn=pn@entry=0xf727c900, top=top@entry=212) at js/src/frontend/BytecodeEmitter.cpp:6368
#16 0x087ea228 in js::frontend::BytecodeEmitter::emitTree (this=this@entry=0xff80a1e4, pn=pn@entry=0xf727c900) at js/src/frontend/BytecodeEmitter.cpp:7719
#17 0x087f226d in js::frontend::BytecodeEmitter::emitNormalFor (this=0xff80a1e4, pn=0xf727cce8, top=211) at js/src/frontend/BytecodeEmitter.cpp:5660
#18 0x087f270b in js::frontend::BytecodeEmitter::emitFor (this=<optimized out>, this@entry=0xff80a1e4, pn=<optimized out>, pn@entry=0xf727cce8, top=<optimized out>, top@entry=200) at js/src/frontend/BytecodeEmitter.cpp:5759
#19 0x087e9b5d in js::frontend::BytecodeEmitter::emitTree (this=this@entry=0xff80a1e4, pn=pn@entry=0xf727cce8) at js/src/frontend/BytecodeEmitter.cpp:7671
#20 0x087f3ab3 in js::frontend::BytecodeEmitter::emitStatementList (this=this@entry=0xff80a1e4, pn=pn@entry=0xf727c0b8, top=top@entry=0) at js/src/frontend/BytecodeEmitter.cpp:6368
#21 0x087ea228 in js::frontend::BytecodeEmitter::emitTree (this=this@entry=0xff80a1e4, pn=pn@entry=0xf727c0b8) at js/src/frontend/BytecodeEmitter.cpp:7719
#22 0x087ea8ba in js::frontend::BytecodeEmitter::emitTree (this=this@entry=0xff80a1e4, pn=0xf727c038) at js/src/frontend/BytecodeEmitter.cpp:7650
#23 0x087eca87 in js::frontend::BytecodeEmitter::emitFunctionScript (this=0xff80a1e4, body=0xf727c038) at js/src/frontend/BytecodeEmitter.cpp:3442
#24 0x08683e18 in BytecodeCompiler::compileFunctionBody (this=this@entry=0xff80984c, fun=fun@entry=..., formals=formals@entry=..., generatorKind=generatorKind@entry=js::NotGenerator) at js/src/frontend/BytecodeCompiler.cpp:771
#25 0x08683fab in CompileFunctionBody (cx=<optimized out>, fun=..., options=..., formals=..., srcBuf=..., enclosingStaticScope=..., generatorKind=js::NotGenerator) at js/src/frontend/BytecodeCompiler.cpp:964
#26 0x08684116 in js::frontend::CompileFunctionBody (cx=0xf7270020, fun=..., options=..., formals=..., srcBuf=...) at js/src/frontend/BytecodeCompiler.cpp:983
#27 0x08545d4e in FunctionConstructor (cx=<optimized out>, argc=<optimized out>, vp=0xff80aa40, generatorKind=js::NotGenerator) at js/src/jsfun.cpp:1931
#28 0xf77666b6 in ?? ()
[...]
#45 main (argc=6, argv=0xff80b974, envp=0xff80b990) at js/src/shell/js.cpp:6677
eax	0x0	0
ebx	0x97ff434	159380532
ecx	0xf75bb88c	-144983924
edx	0x0	0
esi	0x3c087810	1007187984
edi	0x17	23
ebp	0xff808f18	4286615320
esp	0xff808ee0	4286615264
eip	0x87fdb21 <js::InlineMap<JSAtom*, unsigned int, 24u>::switchToMap()+1089>
=> 0x87fdb21 <js::InlineMap<JSAtom*, unsigned int, 24u>::switchToMap()+1089>:	movl   $0x46,0x0
   0x87fdb2b <js::InlineMap<JSAtom*, unsigned int, 24u>::switchToMap()+1099>:	call   0x8101f10 <abort()>


This is a frequent fuzzblocker, please try fixing it in time to help fuzzing.
Whiteboard: [jsbugmon:update,bisect][fuzzblocker] → [fuzzblocker] [jsbugmon:update]
JSBugMon: Bisection requested, result:
=== Treeherder Build Bisection Results by autoBisect ===

The "good" changeset has the timestamp "20151009082747" and the hash "9d24051f444950cf6ea524989df43307647ac264".
The "bad" changeset has the timestamp "20151009093836" and the hash "a67bbdf269fd2661280ab7421e9b601cab409422".

Likely regression window: https://hg.mozilla.org/integration/mozilla-inbound/pushloghtml?fromchange=9d24051f444950cf6ea524989df43307647ac264&tochange=a67bbdf269fd2661280ab7421e9b601cab409422
Needinfo based on previous comment
Flags: needinfo?(efaustbmo)
Group: core-security
Group: javascript-core-security
This is an automated crash issue comment:

Summary: Crash [@ js::HeapPtr<JSAtom*>::init(JSAtom*)]
Build version: mozilla-central revision 4f4615ffec6a
Build flags: --enable-gczeal --enable-optimize="-O2 -g" --enable-address-sanitizer --enable-posix-nspr-emulation --disable-jemalloc --disable-tests --disable-debug
Runtime options: --fuzzing-safe --thread-count=2 --ion-extra-checks

Testcase:

  $ERROR('#1: x = "1"; x ^= 1; x === 0. Actual: ' + (x));
  $ERROR('#2: x = 1; x ^= "1"; x === 0. Actual: ' + (x));
  $ERROR('#3: x = new String("1"); x ^= 1; x === 0. Actual: ' + (x));
  x ^= new String("1");
  $ERROR('#4: x = 1; x ^= new String("1"); x === 0. Actual: ' + (x));
  x ^= new Number(1);
  $ERROR('#5: x = "1"; x ^= new Number(1); x === 0. Actual: ' + (x));
  x = new class {}(1);
  $ERROR('#6: x = new Number(1); x ^= "1"; x === 0. Actual: ' + (x));
  $ERROR('#7: x = new String("1"); x ^= new Number(1); x === 0. Actual: ' + (x));
  $ERROR('#8: x = new Number(1); x ^= new String("1"); x === 0. Actual: ' + (x));
  this.s & 0x80, String('123 456 789'.tempObj(new RegExp('(\\d+)', 'g'))), i;
  $ERROR('#9: x = "x"; x ^= 1; x === 1. Actual: ' + (x));
  $ERROR('#10: x = 1; x ^= "x"; x === 1. Actual: ' + (x));

Backtrace:

==10682==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61a000055170 at pc 0x1625f36 bp 0x7fffb2da39a0 sp 0x7fffb2da3998
WRITE of size 8 at 0x61a000055170 thread T0
    #0 0x1625f35 in js::HeapPtr<JSAtom*>::init(JSAtom*) js/src/gc/Barrier.h:448
    #1 0x1625f35 in js::frontend::InitAtomMap(js::InlineMap<JSAtom*, unsigned long, 24ul>*, js::HeapPtr<JSAtom*>*) js/src/frontend/ParseMaps.cpp:122
    #2 0x104f8d7 in JSScript::fullyInitFromEmitter(js::ExclusiveContext*, JS::Handle<JSScript*>, js::frontend::BytecodeEmitter*) js/src/jsscript.cpp:2849
    #3 0x15e2537 in js::frontend::BytecodeEmitter::emitFunctionScript(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:3497
    #4 0x15fff8c in js::frontend::BytecodeEmitter::emitFunction(js::frontend::ParseNode*, bool) js/src/frontend/BytecodeEmitter.cpp:5835
    #5 0x15d0894 in js::frontend::BytecodeEmitter::emitTree(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:7562
    #6 0x160e279 in js::frontend::BytecodeEmitter::emitCallOrNew(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:6727
    #7 0x15cfe6c in js::frontend::BytecodeEmitter::emitTree(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:7886
    #8 0x160bf27 in js::frontend::BytecodeEmitter::emitStatement(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:6424
    #9 0x15d009d in js::frontend::BytecodeEmitter::emitTree(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:7723
    #10 0x15d06e7 in js::frontend::BytecodeEmitter::emitStatementList(js::frontend::ParseNode*, long) js/src/frontend/BytecodeEmitter.cpp:6368
    #11 0x15d06e7 in js::frontend::BytecodeEmitter::emitTree(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:7719
    #12 0x15f5da9 in js::frontend::BytecodeEmitter::emitLexicalScope(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:5210
    #13 0x15d13aa in js::frontend::BytecodeEmitter::emitTree(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:7890
    #14 0x12f862d in BytecodeCompiler::prepareAndEmitTree(js::frontend::ParseNode**, js::frontend::ParseContext<js::frontend::FullParseHandler>&) js/src/frontend/BytecodeCompiler.cpp:399
    #15 0x12f862d in BytecodeCompiler::compileScript(JS::Handle<JSObject*>, JS::Handle<JSScript*>) js/src/frontend/BytecodeCompiler.cpp:609
    #16 0x12fad08 in js::frontend::CompileScript(js::ExclusiveContext*, js::LifoAlloc*, JS::Handle<JSObject*>, JS::Handle<js::ScopeObject*>, JS::Handle<JSScript*>, JS::ReadOnlyCompileOptions const&, JS::SourceBufferHolder&, JSString*, js::SourceCompressionTask*, js::ScriptSourceObject**) js/src/frontend/BytecodeCompiler.cpp:849
    #17 0x737999 in js::DirectEvalStringFromIon(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSScript*>, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::Handle<JSString*>, unsigned char*, JS::MutableHandle<JS::Value>) js/src/builtin/Eval.cpp:422

0x61a000055170 is located 0 bytes to the right of 1264-byte region [0x61a000054c80,0x61a000055170)
allocated by thread T0 here:
    #0 0x4b0367 in __interceptor_malloc /srv/repos/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:74
    #1 0x10cfb18 in js_malloc(unsigned long) js/src/opt64asan/js/src/../../dist/include/js/Utility.h:221
    #2 0x10cfb18 in _ZL13js_pod_mallocIhEPT_m js/src/opt64asan/js/src/../../dist/include/js/Utility.h:407
    #3 0x10cfb18 in unsigned char* js::MallocProvider<JS::Zone>::maybe_pod_malloc<unsigned char>(unsigned long) js/src/vm/MallocProvider.h:55
    #4 0x10cfb18 in unsigned char* js::MallocProvider<JS::Zone>::pod_malloc<unsigned char>(unsigned long) js/src/vm/MallocProvider.h:88
    #5 0x1042301 in js::SharedScriptData::new_(js::ExclusiveContext*, unsigned int, unsigned int, unsigned int) js/src/jsscript.cpp:2330
    #6 0x104f2b9 in JSScript::fullyInitFromEmitter(js::ExclusiveContext*, JS::Handle<JSScript*>, js::frontend::BytecodeEmitter*) js/src/jsscript.cpp:2841
    #7 0x15e2537 in js::frontend::BytecodeEmitter::emitFunctionScript(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:3497
    #8 0x15fff8c in js::frontend::BytecodeEmitter::emitFunction(js::frontend::ParseNode*, bool) js/src/frontend/BytecodeEmitter.cpp:5835
    #9 0x15d0894 in js::frontend::BytecodeEmitter::emitTree(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:7562
    #10 0x160e279 in js::frontend::BytecodeEmitter::emitCallOrNew(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:6727
    #11 0x15cfe6c in js::frontend::BytecodeEmitter::emitTree(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:7886
    #12 0x160bf27 in js::frontend::BytecodeEmitter::emitStatement(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:6424
    #13 0x15d009d in js::frontend::BytecodeEmitter::emitTree(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:7723
    #14 0x15d06e7 in js::frontend::BytecodeEmitter::emitStatementList(js::frontend::ParseNode*, long) js/src/frontend/BytecodeEmitter.cpp:6368
    #15 0x15d06e7 in js::frontend::BytecodeEmitter::emitTree(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:7719
    #16 0x15f5da9 in js::frontend::BytecodeEmitter::emitLexicalScope(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:5210
    #17 0x15d13aa in js::frontend::BytecodeEmitter::emitTree(js::frontend::ParseNode*) js/src/frontend/BytecodeEmitter.cpp:7890
    #18 0x12f862d in BytecodeCompiler::prepareAndEmitTree(js::frontend::ParseNode**, js::frontend::ParseContext<js::frontend::FullParseHandler>&) js/src/frontend/BytecodeCompiler.cpp:399
    #19 0x12f862d in BytecodeCompiler::compileScript(JS::Handle<JSObject*>, JS::Handle<JSScript*>) js/src/frontend/BytecodeCompiler.cpp:609
    #20 0x12fad08 in js::frontend::CompileScript(js::ExclusiveContext*, js::LifoAlloc*, JS::Handle<JSObject*>, JS::Handle<js::ScopeObject*>, JS::Handle<JSScript*>, JS::ReadOnlyCompileOptions const&, JS::SourceBufferHolder&, JSString*, js::SourceCompressionTask*, js::ScriptSourceObject**) js/src/frontend/BytecodeCompiler.cpp:849
    #21 0x737999 in js::DirectEvalStringFromIon(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSScript*>, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::Handle<JSString*>, unsigned char*, JS::MutableHandle<JS::Value>) js/src/builtin/Eval.cpp:422

SUMMARY: AddressSanitizer: heap-buffer-overflow js/src/gc/Barrier.h:448 js::HeapPtr<JSAtom*>::init(JSAtom*)
Shadow bytes around the buggy address:
  0x0c34800029d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c34800029e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c34800029f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3480002a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3480002a10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c3480002a20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00[fa]fa
  0x0c3480002a30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3480002a40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3480002a50: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3480002a60: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3480002a70: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Contiguous container OOB:fc
  ASan internal:           fe
==10682==ABORTING
Looks like an out-of-bounds write issue, marking s-s and sec-critical.
Crash Signature: [@ js::HeapPtr<JSAtom*>::init]
Summary: Assertion failure: map.count() == inlCount, at js/src/ds/InlineMap.h:70 → Assertion failure: map.count() == inlCount, at js/src/ds/InlineMap.h:70 Crash [@ js::HeapPtr<JSAtom*>::init(JSAtom*)] with heap-buffer-overflow
Whiteboard: [fuzzblocker] [jsbugmon:update] → [fuzzblocker] [jsbugmon:update,ignore]
JSBugMon: The testcase found in this bug no longer reproduces (tried revision d374d16cbb25).
Flags: needinfo?(efaustbmo)
OK to add test. Failure is nightly only.

Please don't add nullptr to a data structure that uses 0 as a tombstone.

Maybe we should also consider to add asserts on |key| to InlineMap::{add, lookup{,forAdd}}
Assignee: nobody → efaustbmo
Status: NEW → ASSIGNED
Attachment #8675114 - Flags: review?(jwalden+bmo)
Comment on attachment 8675114 [details] [diff] [review]
fixDefaultExprs.patch

Review of attachment 8675114 [details] [diff] [review]:
-----------------------------------------------------------------

::: js/src/frontend/BytecodeEmitter.cpp
@@ +7490,5 @@
>              if (!emit2(JSOP_INITHOMEOBJECT, 0))
>                  return false;
>          }
>      } else {
> +        JSAtom *name = names ? names->innerBinding()->pn_atom : cx->names().empty;

Followup to do the right thing for unnamed classes, to not have a name property at all, unless there's a static name property on the class, and all those other special cases.  Fairly easy fix in fun_resolve to return true for such.
Attachment #8675114 - Flags: review?(jwalden+bmo) → review+
https://hg.mozilla.org/mozilla-central/rev/a2c909d966ad
Status: ASSIGNED → RESOLVED
Closed: 6 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla44
Status: RESOLVED → VERIFIED
JSBugMon: This bug has been automatically verified fixed.
Group: core-security, javascript-core-security → core-security-release
Duplicate of this bug: 1215753
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.