Fix use-after-free and memory leaks when realloc returns NULL#373
Open
aaranmcguire wants to merge 1 commit intoWizardMac:devfrom
Open
Fix use-after-free and memory leaks when realloc returns NULL#373aaranmcguire wants to merge 1 commit intoWizardMac:devfrom
aaranmcguire wants to merge 1 commit intoWizardMac:devfrom
Conversation
Five locations call realloc and assign the result directly back to the original pointer. When realloc fails it returns NULL without freeing the old pointer — the old allocation is leaked and the NULL is immediately dereferenced. - spss/readstat_por_read.c: string buffer growth in maybe_read_string() — realloc result written to ctx->string_buffer, then memset crashes - spss/readstat_por_read.c: variable label in read_variable_label_record() — realloc result written to varinfo->label, then readstat_convert crashes - sas/readstat_xport_read.c: xport_read_labels_v8() — name and label pointers overwritten with NULL, then read_bytes crashes - sas/readstat_xport_read.c: xport_read_labels_v9() — name, label, format, informat all overwritten with NULL - stata/readstat_dta_read.c: utf8_buffer in dta_handle_value_labels() — uses raw realloc instead of readstat_realloc, bypassing the 16 MiB safety cap; a crafted DTA with a large value-label table can allocate 4x the intended limit - readstat_writer.c: six capacity-doubling realloc calls (value_labels, label_sets, variables, string_refs, notes, label_set->variables) all replace the pointer before checking for NULL
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.
PR 2: Fix use-after-free and memory leaks when
reallocreturns NULLSummary
Five locations call
reallocand assign the result directly back to theoriginal pointer without checking whether
reallocreturned NULL. Whenreallocfails it returns NULL but does not free the old allocation.Each site below therefore:
These are all in hot paths triggered by normal, well-formed files.
1.
spss/readstat_por_read.c—maybe_read_string(string buffer growth)Vulnerable code
Why it triggers
string_buffer_lenis set from a length field in the POR file(bounded by
MAX_STRING_LENGTH = 20000). The buffer grows whenever a longerstring is encountered. On any memory-constrained system, the
realloccanfail; the old
ctx->string_bufferpointer is leaked andmemsetcrashes.Reproduction
Fix
2.
spss/readstat_por_read.c—read_variable_label_recordVulnerable code
Why it triggers
strlen(string)can be up toMAX_STRING_LENGTH(20000), making theallocation ~80 KB. On failure,
varinfo->labelbecomes NULL andreadstat_convertwrites through the NULL pointer.Fix
3.
sas/readstat_xport_read.c—xport_read_labels_v8andxport_read_labels_v9Vulnerable code (
v8, two pointers;v9, four pointers)Why it triggers
name_lenandlabel_lenare 16-bit values read directly from the XPORTfile, so up to 65535 bytes each.
format_lenandinformat_lenare alsofile-controlled. If any
reallocfails, the corresponding pointer becomesNULL and
read_bytesimmediately tries to write through it.Reproduction
Fix
Apply the temp-pointer pattern to all four realloc calls:
(Same pattern for
formatandinformatinxport_read_labels_v9.)4.
stata/readstat_dta_read.c—dta_handle_value_labelsbypasses 16 MiB safety capVulnerable code
Why it matters
readstat_mallocandreadstat_reallocenforce a 16 MiB hard cap(
MAX_MALLOC_SIZE = 0x1000000).utf8_buffer_len = 4 * txtlen + 1wheretxtlencan approach 16 MB (limited by a priorreadstat_reallocontable_buffer). Soutf8_buffer_lencan reach ~64 MB. Because rawreallocis used instead ofreadstat_realloc, a crafted DTA file with alarge value-label table can allocate four times the intended cap.
Fix
5.
readstat_writer.c— six capacity-doublingrealloccallsVulnerable code (pattern, repeated six times)
Why it triggers
These arrays double in capacity when full (starting at 16 entries). Any
write-heavy application — e.g. writing a dataset with thousands of variables
or thousands of value labels — will trigger multiple resizes. Under memory
pressure, any
realloccan return NULL.Fix (same pattern applied to all six sites)