From 2129a6cfa377b775a4de544d633240707e0e0a49 Mon Sep 17 00:00:00 2001 From: Aaran McGuire Date: Tue, 5 May 2026 19:56:09 +0100 Subject: [PATCH] Fix out-of-bounds array write in POR missing-value reader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bounds check on missing_double_values[3] was performed after the write, not before. When n_missing_values == 3, the code wrote to missing_double_values[3] — one element past the end of the array — before detecting the error. The struct layout (spss/readstat_spss.h): double missing_double_values[3]; /* bytes 0-23 */ char missing_string_values[3][9]; /* bytes 24-50 */ So the fourth write (8 bytes at offset 24) overwrites the first 8 bytes of missing_string_values[0], corrupting string-missing storage. Trigger: a POR file with a variable declaring 4 discrete missing values (malformed, but trivially crafted; any fuzzer finds this immediately). Fix: move the n_missing_values >= 3 check before the array write. --- src/spss/readstat_por_read.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/spss/readstat_por_read.c b/src/spss/readstat_por_read.c index 44dc0f48..8657bbcf 100644 --- a/src/spss/readstat_por_read.c +++ b/src/spss/readstat_por_read.c @@ -372,6 +372,10 @@ static readstat_error_t read_missing_value_record(por_ctx_t *ctx) { } varinfo = &ctx->varinfo[ctx->var_offset]; + if (varinfo->n_missing_values >= 3) { + retval = READSTAT_ERROR_PARSE; + goto cleanup; + } if (varinfo->type == READSTAT_TYPE_DOUBLE) { if ((retval = read_double(ctx, &varinfo->missing_double_values[varinfo->n_missing_values])) != READSTAT_OK) { goto cleanup; @@ -382,10 +386,6 @@ static readstat_error_t read_missing_value_record(por_ctx_t *ctx) { goto cleanup; } } - if (varinfo->n_missing_values > 2) { - retval = READSTAT_ERROR_PARSE; - goto cleanup; - } varinfo->n_missing_values++; cleanup: