Skip to content

Commit 75b5230

Browse files
author
Fabrice Bellard
committed
Fix use-after-free in ArrayBuffer.prototype.transfer (bnoordhuis) (#450) - use js_array_buffer_update_typed_arrays() in JS_DetachArrayBuffer()
1 parent baa186f commit 75b5230

File tree

2 files changed

+49
-41
lines changed

2 files changed

+49
-41
lines changed

quickjs.c

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -55344,10 +55344,47 @@ static JSValue js_array_buffer_get_resizable(JSContext *ctx,
5534455344
return JS_NewBool(ctx, array_buffer_is_resizable(abuf));
5534555345
}
5534655346

55347+
static void js_array_buffer_update_typed_arrays(JSArrayBuffer *abuf)
55348+
{
55349+
uint32_t size_log2, size_elem;
55350+
struct list_head *el;
55351+
JSTypedArray *ta;
55352+
JSObject *p;
55353+
uint8_t *data;
55354+
int64_t len;
55355+
55356+
len = abuf->byte_length;
55357+
data = abuf->data;
55358+
// update lengths of all typed arrays backed by this array buffer
55359+
list_for_each(el, &abuf->array_list) {
55360+
ta = list_entry(el, JSTypedArray, link);
55361+
p = ta->obj;
55362+
if (p->class_id == JS_CLASS_DATAVIEW) {
55363+
continue;
55364+
} else {
55365+
p->u.array.count = 0;
55366+
p->u.array.u.ptr = NULL;
55367+
size_log2 = typed_array_size_log2(p->class_id);
55368+
size_elem = 1 << size_log2;
55369+
if (ta->track_rab) {
55370+
if (len >= (int64_t)ta->offset + size_elem) {
55371+
p->u.array.count = (len - ta->offset) >> size_log2;
55372+
p->u.array.u.ptr = &data[ta->offset];
55373+
}
55374+
} else {
55375+
if (len >= (int64_t)ta->offset + ta->length) {
55376+
p->u.array.count = ta->length >> size_log2;
55377+
p->u.array.u.ptr = &data[ta->offset];
55378+
}
55379+
}
55380+
}
55381+
}
55382+
55383+
}
55384+
5534755385
void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj)
5534855386
{
5534955387
JSArrayBuffer *abuf = JS_GetOpaque(obj, JS_CLASS_ARRAY_BUFFER);
55350-
struct list_head *el;
5535155388

5535255389
if (!abuf || abuf->detached)
5535355390
return;
@@ -55356,19 +55393,7 @@ void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj)
5535655393
abuf->data = NULL;
5535755394
abuf->byte_length = 0;
5535855395
abuf->detached = TRUE;
55359-
55360-
list_for_each(el, &abuf->array_list) {
55361-
JSTypedArray *ta;
55362-
JSObject *p;
55363-
55364-
ta = list_entry(el, JSTypedArray, link);
55365-
p = ta->obj;
55366-
/* Note: the typed array length and offset fields are not modified */
55367-
if (p->class_id != JS_CLASS_DATAVIEW) {
55368-
p->u.array.count = 0;
55369-
p->u.array.u.ptr = NULL;
55370-
}
55371-
}
55396+
js_array_buffer_update_typed_arrays(abuf);
5537255397
}
5537355398

5537455399
/* get an ArrayBuffer or SharedArrayBuffer */
@@ -55483,6 +55508,7 @@ static JSValue js_array_buffer_transfer(JSContext *ctx,
5548355508
abuf->data = NULL;
5548455509
abuf->byte_length = 0;
5548555510
abuf->detached = TRUE;
55511+
js_array_buffer_update_typed_arrays(abuf);
5548655512
return js_array_buffer_constructor3(ctx, JS_UNDEFINED, new_len, pmax_len,
5548755513
JS_CLASS_ARRAY_BUFFER,
5548855514
bs, free_func,
@@ -55493,11 +55519,7 @@ static JSValue js_array_buffer_transfer(JSContext *ctx,
5549355519
static JSValue js_array_buffer_resize(JSContext *ctx, JSValueConst this_val,
5549455520
int argc, JSValueConst *argv, int class_id)
5549555521
{
55496-
uint32_t size_log2, size_elem;
55497-
struct list_head *el;
5549855522
JSArrayBuffer *abuf;
55499-
JSTypedArray *ta;
55500-
JSObject *p;
5550155523
uint8_t *data;
5550255524
int64_t len;
5550355525

@@ -55540,29 +55562,7 @@ static JSValue js_array_buffer_resize(JSContext *ctx, JSValueConst this_val,
5554055562
abuf->byte_length = len;
5554155563
abuf->data = data;
5554255564
}
55543-
data = abuf->data;
55544-
// update lengths of all typed arrays backed by this array buffer
55545-
list_for_each(el, &abuf->array_list) {
55546-
ta = list_entry(el, JSTypedArray, link);
55547-
p = ta->obj;
55548-
if (p->class_id == JS_CLASS_DATAVIEW)
55549-
continue;
55550-
p->u.array.count = 0;
55551-
p->u.array.u.ptr = NULL;
55552-
size_log2 = typed_array_size_log2(p->class_id);
55553-
size_elem = 1 << size_log2;
55554-
if (ta->track_rab) {
55555-
if (len >= (int64_t)ta->offset + size_elem) {
55556-
p->u.array.count = (len - ta->offset) >> size_log2;
55557-
p->u.array.u.ptr = &data[ta->offset];
55558-
}
55559-
} else {
55560-
if (len >= (int64_t)ta->offset + ta->length) {
55561-
p->u.array.count = ta->length >> size_log2;
55562-
p->u.array.u.ptr = &data[ta->offset];
55563-
}
55564-
}
55565-
}
55565+
js_array_buffer_update_typed_arrays(abuf);
5556655566
return JS_UNDEFINED;
5556755567
}
5556855568

tests/test_builtin.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,14 @@ function test_typed_array()
511511
assert(a.toString(), "1,2,3,4");
512512
a.set([10, 11], 2);
513513
assert(a.toString(), "1,2,10,11");
514+
515+
// https://github.com/quickjs-ng/quickjs/issues/1208
516+
buffer = new ArrayBuffer(16);
517+
a = new Uint8Array(buffer);
518+
a.fill(42);
519+
assert(a[0], 42);
520+
buffer.transfer();
521+
assert(a[0], undefined);
514522
}
515523

516524
/* return [s, line_num, col_num] where line_num and col_num are the

0 commit comments

Comments
 (0)