diff options
-rw-r--r-- | tests/custom/03_bugs/26_invalid_sparse_array_set | 49 | ||||
-rw-r--r-- | types.c | 10 |
2 files changed, 57 insertions, 2 deletions
diff --git a/tests/custom/03_bugs/26_invalid_sparse_array_set b/tests/custom/03_bugs/26_invalid_sparse_array_set new file mode 100644 index 0000000..4c47039 --- /dev/null +++ b/tests/custom/03_bugs/26_invalid_sparse_array_set @@ -0,0 +1,49 @@ +When setting an array index which is beyond the end of the last currently +preallocated chunk and not evenly divisible by the chunk size, the array +entries list was not properly reallocated resulting in invalid memory +writes. + +-- Testcase -- +{% + for (i = 0; i < 32; i++) { + a = []; + a[i] = true; + print(length(a), "\n"); + } +%} +-- End -- + +-- Expect stdout -- +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +-- End -- @@ -701,15 +701,21 @@ bool ucv_array_set(uc_value_t *uv, size_t index, uc_value_t *item) { uc_array_t *array = (uc_array_t *)uv; - size_t old_count; + size_t old_count, new_count; if (ucv_type(uv) != UC_ARRAY) return false; if (index >= array->count) { old_count = array->count; + new_count = (index + 1) & ~(UC_VECTOR_CHUNK_SIZE - 1); + + if (new_count > old_count) { + array->count = new_count; + uc_vector_grow(array); + } + array->count = index + 1; - uc_vector_grow(array); while (old_count < array->count) array->entries[old_count++] = NULL; |