From abd1f816ca3b4f382bddf4564ad092aa934f0ccc Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 1 Jan 2019 08:36:05 -0800 Subject: [PATCH] pspp-dump-sav: Issue error message for too-large extension records. CVE-2018-20230. --- NEWS | 2 ++ utilities/pspp-dump-sav.c | 30 ++++++++++++++++++------------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index 3263062cac..191a9804b4 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,8 @@ Changes since 1.2.0: * Plain text output is no longer divided into pages, since it is now rarely printed on paper. + * Bug fix for CVE-2018-20230. + Changes from 1.0.1 to 1.2.0: * New experimental command SAVE DATA COLLECTION to save MDD files. diff --git a/utilities/pspp-dump-sav.c b/utilities/pspp-dump-sav.c index aeb6486650..b0001ac61f 100644 --- a/utilities/pspp-dump-sav.c +++ b/utilities/pspp-dump-sav.c @@ -37,6 +37,7 @@ #include "gl/progname.h" #include "gl/version-etc.h" #include "gl/xalloc.h" +#include "gl/xsize.h" #define ID_MAX_LEN 64 @@ -99,7 +100,7 @@ static void read_simple_compressed_data (struct sfm_reader *, int max_cases); static void read_zlib_compressed_data (struct sfm_reader *); static struct text_record *open_text_record ( - struct sfm_reader *, size_t size); + struct sfm_reader *, size_t size, size_t count); static void close_text_record (struct text_record *); static bool read_variable_to_value_pair (struct text_record *, char **key, char **value); @@ -735,7 +736,7 @@ read_extra_product_info (struct sfm_reader *r, const char *s; printf ("%08llx: extra product info\n", (long long int) ftello (r->file)); - text = open_text_record (r, size * count); + text = open_text_record (r, size, count); s = text_get_all (text); print_string (s, strlen (s)); close_text_record (text); @@ -749,7 +750,7 @@ read_mrsets (struct sfm_reader *r, size_t size, size_t count) printf ("%08llx: multiple response sets\n", (long long int) ftello (r->file)); - text = open_text_record (r, size * count); + text = open_text_record (r, size, count); for (;;) { const char *name; @@ -909,7 +910,7 @@ read_long_var_name_map (struct sfm_reader *r, size_t size, size_t count) printf ("%08llx: long variable names (short => long)\n", (long long int) ftello (r->file)); - text = open_text_record (r, size * count); + text = open_text_record (r, size, count); while (read_variable_to_value_pair (text, &var, &long_name)) printf ("\t%s => %s\n", var, long_name); close_text_record (text); @@ -926,7 +927,7 @@ read_long_string_map (struct sfm_reader *r, size_t size, size_t count) printf ("%08llx: very long strings (variable => length)\n", (long long int) ftello (r->file)); - text = open_text_record (r, size * count); + text = open_text_record (r, size, count); while (read_variable_to_value_pair (text, &var, &length_s)) printf ("\t%s => %d\n", var, atoi (length_s)); close_text_record (text); @@ -1004,7 +1005,7 @@ read_datafile_attributes (struct sfm_reader *r, size_t size, size_t count) struct text_record *text; printf ("%08llx: datafile attributes\n", (long long int) ftello (r->file)); - text = open_text_record (r, size * count); + text = open_text_record (r, size, count); read_attributes (r, text, "datafile"); close_text_record (text); } @@ -1196,7 +1197,7 @@ read_variable_attributes (struct sfm_reader *r, size_t size, size_t count) struct text_record *text; printf ("%08llx: variable attributes\n", (long long int) ftello (r->file)); - text = open_text_record (r, size * count); + text = open_text_record (r, size, count); for (;;) { const char *variable = text_tokenize (text, ':'); @@ -1389,18 +1390,23 @@ struct text_record size_t pos; /* Current position in buffer. */ }; -/* Reads SIZE bytes into a text record for R, +/* Reads SIZE * COUNT bytes into a text record for R, and returns the new text record. */ static struct text_record * -open_text_record (struct sfm_reader *r, size_t size) +open_text_record (struct sfm_reader *r, size_t size, size_t count) { struct text_record *text = xmalloc (sizeof *text); - char *buffer = xmalloc (size + 1); - read_bytes (r, buffer, size); + + if (size_overflow_p (xsum (1, xtimes (size, count)))) + sys_error (r, "Extension record too large."); + + size_t n_bytes = size * count; + char *buffer = xmalloc (n_bytes + 1); + read_bytes (r, buffer, n_bytes); buffer[size] = '\0'; text->reader = r; text->buffer = buffer; - text->size = size; + text->size = n_bytes; text->pos = 0; return text; } -- 2.30.2