You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Out of bounds memory write via child_process.spawn #15622
In process wrap, the length of the array is not checked for potential overflows before it is passed to new.
With a very long array, argc + 1 would overflow to zero, causing a null value to be written &options.args[0xffffffffffffffff], despite the fact that we called new [0]
Test JS function:
function test() {x = []; x.length = 4294967294;x[1]=x[4294967296]='test';require('child_process').spawn('echo', x);}
while(true) test(); // eventually you'll crash with bad memory access or a malloc free error
Using this test code, eax (array length) ends up being set to 0xFFFFFF and rolls over to 0 before calling new:
frame #0: 0x0000000100ac0557 node`node::(anonymous namespace)::ProcessWrap::Spawn(v8::FunctionCallbackInfo<v8::Value> const&) + 755
node`node::(anonymous namespace)::ProcessWrap::Spawn:
-> 0x100ac0557 <+755>: callq 0x100c80d58 ; symbol stub for: operator new[](unsigned long)
0x100ac055c <+760>: movq %rax, -0xcb0(%rbp)
0x100ac0563 <+767>: testl %r15d, %r15d
0x100ac0566 <+770>: jle 0x100ac05f6 ; <+914>
(lldb) reg read rdi
rdi = 0x0000000000000000 < --- argc (0xFFFFFF) + 1 = 0
..snip ...
(lldb) reg read rax
rax = 0x0000000102507920 <-- pointer to args
...snip...after loop which seems to get skipped for some reason....
node`node::(anonymous namespace)::ProcessWrap::Spawn:
-> 0x100ac05f9 <+917>: movq $0x0, (%rax,%r15,8) <-- we write to args[0xffffffffffffffff] which is way out of bounds of what we allocated with new
0x100ac0601 <+925>: movq 0x8(%r12), %rax
0x100ac0606 <+930>: movq 0xc8(%rax), %rsi
0x100ac060d <+937>: movq %r13, %rdi
(lldb) reg read rax r15
rax = 0x0000000102507920
r15 = 0xffffffffffffffff
On older versions of Node, this seems to reliably cause the following error as well:
node(80054,0x7fff9bd0c3c0) malloc: *** error for object 0x102034cd8: pointer being freed was not allocated
On newer versions, it seems like it only crashes like this after the optimizer runs (from what I can tell, always seems to crash after the third time you call the function)
Activity
tarqd commentedon Sep 26, 2017
On older versions of Node, this seems to reliably cause the following error as well:
On newer versions, it seems like it only crashes like this after the optimizer runs (from what I can tell, always seems to crash after the third time you call the function)
tarqd commentedon Sep 28, 2017
Added screenshot of problem from xdebug (argc = -1)
src: CHECK() for argument overflow in Spawn()
src: CHECK() for argument overflow in Spawn()
src: CHECK() for argument overflow in Spawn()
src: CHECK() for argument overflow in Spawn()
src: CHECK() for argument overflow in Spawn()
src: CHECK() for argument overflow in Spawn()