X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=utilities%2Fpspp-dump-sav.c;h=4a44e490574aa7427a4c0fb3eff95d358926184d;hb=25e92a9025f146d5880059f7e863d9c7944fafe6;hp=e58bc254ec1d1f7696a4099ae8d679bb8229b2e0;hpb=8bb2c7ac0120743561e3a483d3b1dd0e96ba447a;p=pspp diff --git a/utilities/pspp-dump-sav.c b/utilities/pspp-dump-sav.c index e58bc254ec..4a44e49057 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); @@ -193,7 +194,7 @@ main (int argc, char *argv[]) if (argc - optind > 1) printf ("Reading \"%s\":\n", r.file_name); - + read_header (&r); while ((rec_type = read_int (&r)) != 999) { @@ -235,9 +236,11 @@ main (int argc, char *argv[]) else if (r.compression == COMP_ZLIB) read_zlib_compressed_data (&r); + free (r.var_widths); + fclose (r.file); } - + return 0; } @@ -379,6 +382,8 @@ format_name (int format) case 37: return "CCE"; case 38: return "EDATE"; case 39: return "SDATE"; + case 40: return "MTIME"; + case 41: return "YMDHMS"; default: return "invalid"; } } @@ -398,7 +403,7 @@ read_variable_record (struct sfm_reader *r) char name[9]; printf ("%08llx: variable record #%d\n", - (long long int) ftello (r->file), r->n_variable_records++); + (long long int) ftello (r->file), ++r->n_variable_records); width = read_int (r); has_variable_label = read_int (r); @@ -444,18 +449,14 @@ read_variable_record (struct sfm_reader *r) if (has_variable_label == 1) { long long int offset = ftello (r->file); - size_t len, read_len; - char label[255 + 1]; - - len = read_int (r); + enum { MAX_LABEL_LEN = 65536 }; - /* Read up to 255 bytes of label. */ - read_len = MIN (sizeof label - 1, len); + size_t len = read_int (r); + size_t read_len = MIN (MAX_LABEL_LEN, len); + char *label = xmalloc (read_len + 1); read_string (r, label, read_len + 1); printf("\t%08llx Variable label: \"%s\"\n", offset, label); - - /* Skip unread label bytes. */ - skip_bytes (r, len - read_len); + free (label); /* Skip label padding up to multiple of 4 bytes. */ skip_bytes (r, ROUND_UP (len, 4) - len); @@ -737,7 +738,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); @@ -751,7 +752,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; @@ -799,7 +800,11 @@ read_mrsets (struct sfm_reader *r, size_t size, size_t count) } number = text_tokenize (text, ' '); - if (!strcmp (number, "11")) + if (!number) + sys_warn (r, "Missing label source value " + "following `E' at offset %zu in MRSETS record", + text_pos (text)); + else if (!strcmp (number, "11")) label_from_var_label = true; else if (strcmp (number, "1")) sys_warn (r, "Unexpected label source value `%s' " @@ -907,7 +912,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); @@ -924,7 +929,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); @@ -937,17 +942,17 @@ read_attributes (struct sfm_reader *r, struct text_record *text, const char *key; int index; - for (;;) + for (;;) { key = text_tokenize (text, '('); if (key == NULL) return true; - + for (index = 1; ; index++) { /* Parse the value. */ const char *value = text_tokenize (text, '\n'); - if (value == NULL) + if (value == NULL) { sys_warn (r, "%s: Error parsing attribute value %s[%d]", variable, key, index); @@ -967,7 +972,7 @@ read_attributes (struct sfm_reader *r, struct text_record *text, } if (text_match (text, '/')) - return true; + return true; } } @@ -997,12 +1002,12 @@ read_ncases64 (struct sfm_reader *r, size_t size, size_t count) } static void -read_datafile_attributes (struct sfm_reader *r, size_t size, size_t count) +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); } @@ -1015,6 +1020,8 @@ read_character_encoding (struct sfm_reader *r, size_t size, size_t count) read_string (r, encoding, count + 1); printf ("%08llx: Character Encoding: %s\n", posn, encoding); + + free (encoding); } static void @@ -1189,17 +1196,17 @@ read_unknown_extension (struct sfm_reader *r, size_t size, size_t count) } static void -read_variable_attributes (struct sfm_reader *r, size_t size, size_t count) +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); - for (;;) + text = open_text_record (r, size, count); + for (;;) { const char *variable = text_tokenize (text, ':'); if (variable == NULL || !read_attributes (r, text, variable)) - break; + break; } close_text_record (text); } @@ -1224,7 +1231,7 @@ read_simple_compressed_data (struct sfm_reader *r, int max_cases) { printf ("%08llx: case %d's uncompressible data begins\n", (long long int) ftello (r->file), case_num); - for (i = 0; i < r->n_var_widths; ) + for (i = 0; i < r->n_var_widths;) { int width = r->var_widths[i]; char raw_value[8]; @@ -1387,18 +1394,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); - buffer[size] = '\0'; + + 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[n_bytes] = '\0'; text->reader = r; text->buffer = buffer; - text->size = size; + text->size = n_bytes; text->pos = 0; return text; } @@ -1428,9 +1440,9 @@ text_tokenize (struct text_record *text, int delimiter) } static bool -text_match (struct text_record *text, int c) +text_match (struct text_record *text, int c) { - if (text->pos < text->size && text->buffer[text->pos] == c) + if (text->pos < text->size && text->buffer[text->pos] == c) { text->pos++; return true;