Skip to content

Commit 23f2770

Browse files
committed
Fix use-after-free in ArrayBuffer.prototype.transfer
Fixes: #1208
1 parent e1713ea commit 23f2770

File tree

2 files changed

+48
-31
lines changed

2 files changed

+48
-31
lines changed

quickjs.c

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -54133,6 +54133,43 @@ static bool array_buffer_is_resizable(const JSArrayBuffer *abuf)
5413354133
return abuf->max_byte_length >= 0;
5413454134
}
5413554135

54136+
static void js_array_buffer_update_typed_arrays(JSArrayBuffer *abuf)
54137+
{
54138+
uint32_t size_log2, size_elem;
54139+
struct list_head *el;
54140+
JSTypedArray *ta;
54141+
JSObject *p;
54142+
uint8_t *data;
54143+
int64_t len;
54144+
54145+
len = abuf->byte_length;
54146+
data = abuf->data;
54147+
list_for_each(el, &abuf->array_list) {
54148+
ta = list_entry(el, JSTypedArray, link);
54149+
p = ta->obj;
54150+
if (p->class_id == JS_CLASS_DATAVIEW) {
54151+
if (ta->track_rab && ta->offset < len)
54152+
ta->length = len - ta->offset;
54153+
continue;
54154+
}
54155+
p->u.array.count = 0;
54156+
p->u.array.u.ptr = NULL;
54157+
size_log2 = typed_array_size_log2(p->class_id);
54158+
size_elem = 1 << size_log2;
54159+
if (ta->track_rab) {
54160+
if (len >= (int64_t)ta->offset + size_elem) {
54161+
p->u.array.count = (len - ta->offset) >> size_log2;
54162+
p->u.array.u.ptr = &data[ta->offset];
54163+
}
54164+
} else {
54165+
if (len >= (int64_t)ta->offset + ta->length) {
54166+
p->u.array.count = ta->length >> size_log2;
54167+
p->u.array.u.ptr = &data[ta->offset];
54168+
}
54169+
}
54170+
}
54171+
}
54172+
5413654173
// ES #sec-arraybuffer.prototype.transfer
5413754174
static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val,
5413854175
int argc, JSValueConst *argv, int magic)
@@ -54185,6 +54222,7 @@ static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val,
5418554222
abuf->data = NULL;
5418654223
abuf->byte_length = 0;
5418754224
abuf->detached = true;
54225+
js_array_buffer_update_typed_arrays(abuf);
5418854226
return js_array_buffer_constructor3(ctx, JS_UNDEFINED, new_len, pmax_len,
5418954227
JS_CLASS_ARRAY_BUFFER,
5419054228
bs, abuf->free_func,
@@ -54194,11 +54232,7 @@ static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val,
5419454232
static JSValue js_array_buffer_resize(JSContext *ctx, JSValueConst this_val,
5419554233
int argc, JSValueConst *argv, int class_id)
5419654234
{
54197-
uint32_t size_log2, size_elem;
54198-
struct list_head *el;
5419954235
JSArrayBuffer *abuf;
54200-
JSTypedArray *ta;
54201-
JSObject *p;
5420254236
uint8_t *data;
5420354237
int64_t len;
5420454238

@@ -54241,33 +54275,7 @@ static JSValue js_array_buffer_resize(JSContext *ctx, JSValueConst this_val,
5424154275
abuf->byte_length = len;
5424254276
abuf->data = data;
5424354277
}
54244-
data = abuf->data;
54245-
// update lengths of all typed arrays backed by this array buffer
54246-
list_for_each(el, &abuf->array_list) {
54247-
ta = list_entry(el, JSTypedArray, link);
54248-
p = ta->obj;
54249-
if (p->class_id == JS_CLASS_DATAVIEW) {
54250-
if (ta->track_rab && ta->offset < len)
54251-
ta->length = len - ta->offset;
54252-
54253-
continue;
54254-
}
54255-
p->u.array.count = 0;
54256-
p->u.array.u.ptr = NULL;
54257-
size_log2 = typed_array_size_log2(p->class_id);
54258-
size_elem = 1 << size_log2;
54259-
if (ta->track_rab) {
54260-
if (len >= (int64_t)ta->offset + size_elem) {
54261-
p->u.array.count = (len - ta->offset) >> size_log2;
54262-
p->u.array.u.ptr = &data[ta->offset];
54263-
}
54264-
} else {
54265-
if (len >= (int64_t)ta->offset + ta->length) {
54266-
p->u.array.count = ta->length >> size_log2;
54267-
p->u.array.u.ptr = &data[ta->offset];
54268-
}
54269-
}
54270-
}
54278+
js_array_buffer_update_typed_arrays(abuf);
5427154279
return JS_UNDEFINED;
5427254280
}
5427354281

tests/test_builtin.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,15 @@ function test_typed_array()
590590
caught = true;
591591
}
592592
assert(caught);
593+
594+
// https://github.com/quickjs-ng/quickjs/issues/1208
595+
buffer = new ArrayBuffer(16);
596+
a = new Uint8Array(buffer);
597+
a.fill(42);
598+
assert(a[0], 42);
599+
buffer.transfer();
600+
assert(a[0], undefined);
601+
593602
}
594603

595604
function test_json()

0 commit comments

Comments
 (0)