Repository navigation
Check realloc results before using the grown buffer - #430
Open
bmryggdrasil wants to merge 1 commit into
Open
bmryggdrasil wants to merge 1 commit into
bmryggdrasil wants to merge 1 commit into
Conversation
Four places still assign realloc's result straight back to the only pointer to the old block, so a failed realloc leaks the old block and the code then writes through NULL: - ck_str_n_hash_insert doubles keys_capacity and then copies the new key to table->keys + keys_used. Since keys_used is the size of all earlier keys, the write lands at an offset from NULL rather than at NULL itself. count was also bumped before the copy. - txt_getdelim doubles value_buffer_len inside the realloc call and keeps reading into value_buffer[i], again at an offset from NULL. - sas7bcat_parse_value_labels passes the NULL label buffer to readstat_convert. - sav_emit_long_string_value_labels_record memsets the NULL space_buffer. Keep the old pointer until realloc succeeds and return READSTAT_ERROR_MALLOC (or 0 from the hash insert, which callers already treat as failure) so the existing cleanup paths free it. txt_getdelim returns -2 for allocation failure so txt_parse_delimited can tell it apart from a read error. The key-buffer growth in the hash table also refuses to double past SIZE_MAX. This continues WizardMac#373, which fixed the same pattern in other readers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Four places still assign
realloc's result straight back to the only pointer to the old block. Whenreallocfails it returns NULL without freeing the old block, so each site leaks it and then writes through NULL. This continues #373, which fixed the same pattern in the por, dta, xport and writer code.CKHashTable.cck_str_n_hash_insertmemcpytotable->keys + keys_used, an offset from NULL (keys_usedis the size of all earlier keys);countwas already incrementedtxt/readstat_txt_read.ctxt_getdelimvalue_buffer[i], an offset from NULL;value_buffer_lenwas already doubledsas/readstat_sas7bcat_read.csas7bcat_parse_value_labelslabeltoreadstat_convertspss/readstat_sav_write.csav_emit_long_string_value_labels_recordmemseton the NULLspace_bufferChanges
reallocsucceeds, then returnREADSTAT_ERROR_MALLOCso the existing cleanup paths free it.ck_str_n_hash_insertreturns 0 (callers already treat this as failure) and only updateskeys,keys_capacityandcountafter the growth succeeds. The doubling loop also refuses to go pastSIZE_MAX.txt_getdelimreturns -2 for an allocation failure, sotxt_parse_delimitedcan reportREADSTAT_ERROR_MALLOCinstead ofREADSTAT_ERROR_READ. It leaves*linep/*linecapppointing at the old, still-valid buffer, which the caller frees.Testing
test_readstatpasses before and after the change (clang viazig cc,-std=c99 -Wall -Werror -pedantic-errors, zlib enabled; Windows x86_64).reallocis made to return NULL during the growth step.ck_str_hash_insertwith a key larger than the key buffer: before, segfault; after, returns 0, the table is unchanged and a later insert and lookup work.txt_getdelimon a line longer than its buffer: before, segfault; after, returns -2 and keeps the original buffer and capacity.Not included
readstat_schema_find_or_create_entryand the entry array in the Stata dictionary reader have the same pattern, but their callers are Ragel actions insrc/txt/*.rlthat dereference the result, so fixing them means regenerating the.cfiles. I left those for a separate change. The same pattern also appears insrc/bin/tools (extract_metadata.c,read_csv.c).🤖 Generated with Claude Code