mirror of
https://github.com/bellard/quickjs.git
synced 2026-03-31 12:18:01 +00:00
fixed TypedArray sort semantics by copying the array before calling the comparison function. Fixed buffer overflow when the array is resized (#477)
This commit is contained in:
parent
4c722cea4e
commit
0989d4cb4a
2
TODO
2
TODO
@ -63,4 +63,4 @@ Test262o: 0/11262 errors, 463 excluded
|
||||
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
|
||||
|
||||
Test262:
|
||||
Result: 66/83341 errors, 2567 excluded, 5767 skipped
|
||||
Result: 64/83341 errors, 2567 excluded, 5767 skipped
|
||||
|
||||
100
quickjs.c
100
quickjs.c
@ -57676,7 +57676,7 @@ static JSValue js_TA_get_float64(JSContext *ctx, const void *a) {
|
||||
struct TA_sort_context {
|
||||
JSContext *ctx;
|
||||
int exception; /* 1 = exception, 2 = detached typed array */
|
||||
JSValueConst arr;
|
||||
uint8_t *array;
|
||||
JSValueConst cmp;
|
||||
JSValue (*getfun)(JSContext *ctx, const void *a);
|
||||
int elt_size;
|
||||
@ -57689,7 +57689,6 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) {
|
||||
JSValueConst argv[2];
|
||||
JSValue res;
|
||||
int cmp;
|
||||
JSObject *p;
|
||||
|
||||
cmp = 0;
|
||||
if (!psc->exception) {
|
||||
@ -57697,15 +57696,9 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) {
|
||||
error */
|
||||
a_idx = *(uint32_t *)a;
|
||||
b_idx = *(uint32_t *)b;
|
||||
p = JS_VALUE_GET_PTR(psc->arr);
|
||||
if (a_idx >= p->u.array.count || b_idx >= p->u.array.count) {
|
||||
/* OOB case */
|
||||
psc->exception = 2;
|
||||
return 0;
|
||||
}
|
||||
argv[0] = psc->getfun(ctx, p->u.array.u.uint8_ptr +
|
||||
argv[0] = psc->getfun(ctx, psc->array +
|
||||
a_idx * (size_t)psc->elt_size);
|
||||
argv[1] = psc->getfun(ctx, p->u.array.u.uint8_ptr +
|
||||
argv[1] = psc->getfun(ctx, psc->array +
|
||||
b_idx * (size_t)(psc->elt_size));
|
||||
res = JS_Call(ctx, psc->cmp, JS_UNDEFINED, 2, argv);
|
||||
if (JS_IsException(res)) {
|
||||
@ -57746,7 +57739,6 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
|
||||
|
||||
tsc.ctx = ctx;
|
||||
tsc.exception = 0;
|
||||
tsc.arr = this_val;
|
||||
tsc.cmp = argv[0];
|
||||
|
||||
if (!JS_IsUndefined(tsc.cmp) && check_function(ctx, tsc.cmp))
|
||||
@ -57809,65 +57801,69 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
|
||||
elt_size = 1 << typed_array_size_log2(p->class_id);
|
||||
if (!JS_IsUndefined(tsc.cmp)) {
|
||||
uint32_t *array_idx;
|
||||
void *array_tmp;
|
||||
void *array;
|
||||
size_t i, j;
|
||||
|
||||
/* XXX: a stable sort would use less memory */
|
||||
array_idx = js_malloc(ctx, len * sizeof(array_idx[0]));
|
||||
if (!array_idx)
|
||||
/* the array must be copied because the comparison
|
||||
function may modify it */
|
||||
array = js_malloc(ctx, len * elt_size);
|
||||
if (!array)
|
||||
return JS_EXCEPTION;
|
||||
memcpy(array, p->u.array.u.ptr, len * elt_size);
|
||||
|
||||
/* array_idx is needed to have a stable sort */
|
||||
array_idx = js_malloc(ctx, len * sizeof(array_idx[0]));
|
||||
if (!array_idx) {
|
||||
js_free(ctx, array);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
for(i = 0; i < len; i++)
|
||||
array_idx[i] = i;
|
||||
tsc.elt_size = elt_size;
|
||||
tsc.array = array;
|
||||
rqsort(array_idx, len, sizeof(array_idx[0]),
|
||||
js_TA_cmp_generic, &tsc);
|
||||
if (tsc.exception) {
|
||||
if (tsc.exception == 1)
|
||||
goto fail;
|
||||
if (tsc.exception == 1) {
|
||||
js_free(ctx, array_idx);
|
||||
js_free(ctx, array);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
/* detached typed array during the sort: no error */
|
||||
} else {
|
||||
void *array_ptr = p->u.array.u.ptr;
|
||||
len = min_int(len, p->u.array.count);
|
||||
if (len != 0) {
|
||||
array_tmp = js_malloc(ctx, len * elt_size);
|
||||
if (!array_tmp) {
|
||||
fail:
|
||||
js_free(ctx, array_idx);
|
||||
return JS_EXCEPTION;
|
||||
switch(elt_size) {
|
||||
case 1:
|
||||
for(i = 0; i < len; i++) {
|
||||
j = array_idx[i];
|
||||
((uint8_t *)array_ptr)[i] = ((uint8_t *)array)[j];
|
||||
}
|
||||
memcpy(array_tmp, array_ptr, len * elt_size);
|
||||
switch(elt_size) {
|
||||
case 1:
|
||||
for(i = 0; i < len; i++) {
|
||||
j = array_idx[i];
|
||||
((uint8_t *)array_ptr)[i] = ((uint8_t *)array_tmp)[j];
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for(i = 0; i < len; i++) {
|
||||
j = array_idx[i];
|
||||
((uint16_t *)array_ptr)[i] = ((uint16_t *)array_tmp)[j];
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for(i = 0; i < len; i++) {
|
||||
j = array_idx[i];
|
||||
((uint32_t *)array_ptr)[i] = ((uint32_t *)array_tmp)[j];
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
for(i = 0; i < len; i++) {
|
||||
j = array_idx[i];
|
||||
((uint64_t *)array_ptr)[i] = ((uint64_t *)array_tmp)[j];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
break;
|
||||
case 2:
|
||||
for(i = 0; i < len; i++) {
|
||||
j = array_idx[i];
|
||||
((uint16_t *)array_ptr)[i] = ((uint16_t *)array)[j];
|
||||
}
|
||||
js_free(ctx, array_tmp);
|
||||
break;
|
||||
case 4:
|
||||
for(i = 0; i < len; i++) {
|
||||
j = array_idx[i];
|
||||
((uint32_t *)array_ptr)[i] = ((uint32_t *)array)[j];
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
for(i = 0; i < len; i++) {
|
||||
j = array_idx[i];
|
||||
((uint64_t *)array_ptr)[i] = ((uint64_t *)array)[j];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
js_free(ctx, array_idx);
|
||||
js_free(ctx, array);
|
||||
} else {
|
||||
rqsort(p->u.array.u.ptr, len, elt_size, cmpfun, &tsc);
|
||||
if (tsc.exception)
|
||||
|
||||
@ -37,8 +37,6 @@ test262/test/staging/sm/TypedArray/constructor-buffer-sequence.js:29: Test262Err
|
||||
test262/test/staging/sm/TypedArray/constructor-buffer-sequence.js:29: strict mode: Test262Error: Expected a ExpectedError but got a Error
|
||||
test262/test/staging/sm/TypedArray/prototype-constructor-identity.js:17: Test262Error: Expected SameValue(«2», «6») to be true
|
||||
test262/test/staging/sm/TypedArray/prototype-constructor-identity.js:17: strict mode: Test262Error: Expected SameValue(«2», «6») to be true
|
||||
test262/test/staging/sm/TypedArray/sort_modifications.js:9: Test262Error: Int8Array at index 0 for size 4 Expected SameValue(«0», «1») to be true
|
||||
test262/test/staging/sm/TypedArray/sort_modifications.js:9: strict mode: Test262Error: Int8Array at index 0 for size 4 Expected SameValue(«0», «1») to be true
|
||||
test262/test/staging/sm/async-functions/async-contains-unicode-escape.js:11: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/staging/sm/async-functions/async-contains-unicode-escape.js:11: strict mode: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
test262/test/staging/sm/async-functions/await-in-arrow-parameters.js:10: Test262Error: AsyncFunction:(a = (b = await/r/g) => {}) => {} Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||
|
||||
Loading…
Reference in New Issue
Block a user