fix(wasm): realloc should handle smaller new size

This commit is contained in:
Trim21 2026-01-15 05:06:01 +08:00
parent 6c05cdfb0c
commit e6ad0683ca
2 changed files with 1201 additions and 1154 deletions

View file

@ -14,6 +14,7 @@ extern void tree_sitter_debug_message(const char *, size_t);
#define PAGESIZE 0x10000
#define MAX_HEAP_SIZE (4 * 1024 * 1024)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
typedef struct {
size_t size;
@ -118,18 +119,41 @@ void *realloc(void *ptr, size_t new_size) {
return malloc(new_size);
}
// Per the C standard, realloc(ptr, 0) acts like free(ptr) and returns NULL.
if (new_size == 0) {
free(ptr);
return NULL;
}
Region *region = region_for_ptr(ptr);
Region *region_end = region_after(region, region->size);
// When reallocating the last allocated region, return
// the same pointer, and skip copying the data.
if (region_end == next) {
next = region;
return malloc(new_size);
// grow the heap and update last region's size so we do not need to copy data
Region *new_region_end = region_after(region, new_size);
if (new_region_end > heap_end) {
if ((char *)new_region_end - (char *)heap_start > MAX_HEAP_SIZE) {
return NULL;
}
if (!grow_heap(new_size)) return NULL;
heap_end = get_heap_end();
}
region->size = new_size;
next = new_region_end;
return ptr;
}
void *result = malloc(new_size);
memcpy(result, &region->data, region->size);
if (result == NULL) {
return NULL;
}
size_t copy_size = MIN(region->size, new_size);
memcpy(result, &region->data, copy_size);
free(ptr);
return result;
}

File diff suppressed because it is too large Load diff