From 1346997b5613a3268a3bda70c69d21b5e96b958a Mon Sep 17 00:00:00 2001 From: Evan Miller Date: Sun, 13 Sep 2026 14:50:58 -0400 Subject: [PATCH] Validate SAV missing-value count before abs() OSS-Fuzz 471515730 (fuzz_format_sav): readstat_parse_sav reported a signed integer overflow in sav_skip_variable_record. The variable record's n_missing_values field is attacker-controlled, and abs(n_missing_values) * sizeof(double) is undefined when n_missing_values is INT_MIN (negating -2147483648 overflows int). Apply the same -3..3 bound that sav_read_variable_missing_values already enforces before taking the absolute value, rejecting the record as a parse error otherwise. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01VbdjJ6i4dby3R6KM6m4Rpi --- src/spss/readstat_sav_read.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/spss/readstat_sav_read.c b/src/spss/readstat_sav_read.c index 5810f1ff..29559f1d 100644 --- a/src/spss/readstat_sav_read.c +++ b/src/spss/readstat_sav_read.c @@ -216,6 +216,10 @@ static readstat_error_t sav_skip_variable_record(sav_ctx_t *ctx) { } if (variable.n_missing_values) { int n_missing_values = ctx->bswap ? byteswap4(variable.n_missing_values) : variable.n_missing_values; + if (n_missing_values > 3 || n_missing_values < -3) { + retval = READSTAT_ERROR_PARSE; + goto cleanup; + } if (io->seek(abs(n_missing_values) * sizeof(double), READSTAT_SEEK_CUR, io->io_ctx) == -1) { retval = READSTAT_ERROR_SEEK; goto cleanup;