fix: wrong buffer resize in strbuf replace

This commit is contained in:
overflowerror 2024-05-18 18:00:13 +02:00
parent acf8c7a2d0
commit cd18d88b83
2 changed files with 21 additions and 5 deletions

View file

@ -27,12 +27,14 @@ strbuf_t _strbuf_replace(strbuf_t buffer, char* needle, char* replace) {
if (replace_length == needle_length) {
memcpy(result, replace, replace_length);
} else if (replace_length > needle_length) {
list_ensure_space(buffer, 1, replace_length - needle_length);
memmove(result + replace_length, result + needle_length, strlen(buffer) - offset - needle_length + 1);
memcpy(result, replace, replace_length);
buffer = list_ensure_space(buffer, 1, replace_length - needle_length);
memmove(buffer + offset + replace_length, buffer + offset + needle_length, strlen(buffer) - offset - needle_length + 1);
memcpy(buffer + offset, replace, replace_length);
list_header(buffer)->length += (replace_length - needle_length);
} else {
memcpy(result, replace, replace_length);
memmove(result + replace_length, result + needle_length, strlen(buffer) - offset - needle_length + 1);
list_header(buffer)->length -= (needle_length - replace_length);
}
}

View file

@ -100,7 +100,7 @@ void test_strbuf_replace_shorter_length(void) {
assert_streq("hello ba world ba !", buffer, "buffer doesn't match");
printf("%lu, %zu\n", strlen(buffer), list_size(buffer));
assert_equals(strlen(buffer) + 1 + 2, list_size(buffer), "allocation doesn't match");
assert_equals(strlen(buffer) + 1, list_size(buffer), "allocation doesn't match");
strbuf_free(buffer);
}
@ -113,7 +113,20 @@ void test_strbuf_replace_greater_length(void) {
assert_streq("hello barr world barr !", buffer, "buffer doesn't match");
printf("%lu, %zu\n", strlen(buffer), list_size(buffer));
assert_equals(strlen(buffer) - 1, list_size(buffer), "allocation doesn't match");
assert_equals(strlen(buffer) + 1, list_size(buffer), "allocation doesn't match");
strbuf_free(buffer);
}
void test_strbuf_replace_bug_realloc_moves(void) {
strbuf_t buffer = strbuf_new();
strbuf_append(buffer, "hello foo world foo !");
strbuf_replace(buffer, "foo", "a very long string that will cause the region to be too small");
assert_streq("hello a very long string that will cause the region to be too small world a very long string that will cause the region to be too small !", buffer, "buffer doesn't match");
printf("%lu, %zu\n", strlen(buffer), list_size(buffer));
assert_equals(strlen(buffer) + 1, list_size(buffer), "allocation doesn't match");
strbuf_free(buffer);
}
@ -130,6 +143,7 @@ int main(void) {
test_run(test_strbuf_replace_equal_length);
test_run(test_strbuf_replace_shorter_length);
test_run(test_strbuf_replace_greater_length);
test_run(test_strbuf_replace_bug_realloc_moves);
if (test_results()) {
return 0;