X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fsfm-read.c;h=bd8800bb9f9e09b698a5b756b93753a8e592753a;hb=28d7aaf2db476de5d62eb90787fef50fec444287;hp=f0f9923d886097d6a81d788bedb3a46ad3abaa00;hpb=66f7c229748ba9f8bbcb6255caacb0689790a0da;p=pspp diff --git a/src/sfm-read.c b/src/sfm-read.c index f0f9923d88..bd8800bb9f 100644 --- a/src/sfm-read.c +++ b/src/sfm-read.c @@ -33,7 +33,7 @@ #include "file-handle.h" #include "filename.h" #include "format.h" -#include "getline.h" +#include "getl.h" #include "hash.h" #include "magic.h" #include "misc.h" @@ -41,6 +41,9 @@ #include "str.h" #include "var.h" +#include "gettext.h" +#define _(msgid) gettext (msgid) + #include "debug-print.h" /* System file reader. */ @@ -59,7 +62,6 @@ struct sfm_reader /* Variables. */ struct sfm_var *vars; /* Variables. */ - size_t var_cnt; /* Number of variables. */ /* File's special constants. */ flt64 sysmis; @@ -94,7 +96,7 @@ bswap (unsigned char *a, unsigned char *b) *b = t; } -/* bswap_int32(): Reverse the byte order of 32-bit integer *X. */ +/* Reverse the byte order of 32-bit integer *X. */ static inline void bswap_int32 (int32 *x_) { @@ -221,7 +223,6 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict, r->weight_idx = -1; r->vars = NULL; - r->var_cnt = 0; r->sysmis = -FLT64_MAX; r->highest = FLT64_MAX; @@ -244,6 +245,7 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict, if (!read_header (r, *dict, info) || !read_variables (r, *dict, &var_by_idx)) goto error; + /* Handle weighting. */ if (r->weight_idx != -1) { @@ -343,7 +345,7 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict, { const int n_vars = data.count / 3 ; int i; - if ( data.count % 3 ) + if ( data.count % 3 || n_vars > dict_get_var_cnt(*dict) ) { msg (MW, _("%s: Invalid subrecord length. " "Record: 7; Subrecord: 11"), @@ -351,7 +353,7 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict, skip = 1; } - for ( i = 0 ; i < n_vars ; ++i ) + for ( i = 0 ; i < min(n_vars, dict_get_var_cnt(*dict)) ; ++i ) { struct { @@ -422,6 +424,16 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict, break; } + /* Identify any duplicates. */ + if ( compare_var_names(short_name, long_name, 0) && + NULL != dict_lookup_var (*dict, long_name)) + { + lose ((ME, _("%s: Duplicate long variable name `%s' " + "within system file."), + handle_get_filename (r->fh), long_name)); + break; + } + /* Set long name. Renaming a variable may clear the short name, but we want to retain it, so @@ -740,7 +752,6 @@ read_variables (struct sfm_reader *r, int long_string_count = 0; /* # of long string continuation records still expected. */ int next_value = 0; /* Index to next `value' structure. */ - size_t var_cap = 0; assert(r); @@ -748,7 +759,10 @@ read_variables (struct sfm_reader *r, /* Pre-allocate variables. */ if ( r->value_cnt != -1 ) - *var_by_idx = xmalloc(r->value_cnt * sizeof (**var_by_idx)); + { + *var_by_idx = xmalloc(r->value_cnt * sizeof (**var_by_idx)); + r->vars = xmalloc( r->value_cnt * sizeof (*r->vars) ); + } /* Read in the entry for each variable and use the info to @@ -756,7 +770,7 @@ read_variables (struct sfm_reader *r, for (i = 0; ; ++i) { struct variable *vv; - char name[9]; + char name[SHORT_NAME_LEN + 1]; int nv; int j; @@ -779,11 +793,15 @@ read_variables (struct sfm_reader *r, if (sv.rec_type != 2) { buf_unread(r, sizeof sv); + r->value_cnt = i; break; } if ( -1 == r->value_cnt ) - *var_by_idx = xrealloc (*var_by_idx, sizeof **var_by_idx * (i+1) ); + { + *var_by_idx = xrealloc (*var_by_idx, sizeof **var_by_idx * (i + 1)); + r->vars = xrealloc(r->vars, (i + 1) * sizeof (*r->vars) ); + } /* If there was a long string previously, make sure that the continuations are present; otherwise make sure there aren't @@ -795,6 +813,8 @@ read_variables (struct sfm_reader *r, "proper number of continuation records."), handle_get_filename (r->fh), i)); + + r->vars[i].width = -1; (*var_by_idx)[i] = NULL; long_string_count--; continue; @@ -857,11 +877,17 @@ read_variables (struct sfm_reader *r, } name[j] = 0; + if ( ! var_is_valid_name(name, false) ) + lose ((ME, _("%s: Invalid variable name `%s' within system file."), + handle_get_filename (r->fh), name)); + /* Create variable. */ + vv = (*var_by_idx)[i] = dict_create_var (dict, name, sv.type); if (vv == NULL) lose ((ME, _("%s: Duplicate variable name `%s' within system file."), handle_get_filename (r->fh), name)); + var_set_short_name (vv, vv->name); /* Case reading data. */ @@ -900,77 +926,53 @@ read_variables (struct sfm_reader *r, if (sv.n_missing_values != 0) { flt64 mv[3]; + int mv_cnt = abs (sv.n_missing_values); if (vv->width > MAX_SHORT_STRING) lose ((ME, _("%s: Long string variable %s may not have missing " "values."), handle_get_filename (r->fh), vv->name)); - assertive_buf_read (r, mv, sizeof *mv * abs (sv.n_missing_values), 0); + assertive_buf_read (r, mv, sizeof *mv * mv_cnt, 0); if (r->reverse_endian && vv->type == NUMERIC) - for (j = 0; j < abs (sv.n_missing_values); j++) + for (j = 0; j < mv_cnt; j++) bswap_flt64 (&mv[j]); if (sv.n_missing_values > 0) { - vv->miss_type = sv.n_missing_values; - if (vv->type == NUMERIC) - for (j = 0; j < sv.n_missing_values; j++) - vv->missing[j].f = mv[j]; - else - for (j = 0; j < sv.n_missing_values; j++) - memcpy (vv->missing[j].s, &mv[j], vv->width); + for (j = 0; j < sv.n_missing_values; j++) + if (vv->type == NUMERIC) + mv_add_num (&vv->miss, mv[j]); + else + mv_add_str (&vv->miss, (unsigned char *) &mv[j]); } else { - int x = 0; - if (vv->type == ALPHA) lose ((ME, _("%s: String variable %s may not have missing " "values specified as a range."), handle_get_filename (r->fh), vv->name)); if (mv[0] == r->lowest) - { - vv->miss_type = MISSING_LOW; - vv->missing[x++].f = mv[1]; - } + mv_add_num_range (&vv->miss, LOWEST, mv[1]); else if (mv[1] == r->highest) - { - vv->miss_type = MISSING_HIGH; - vv->missing[x++].f = mv[0]; - } + mv_add_num_range (&vv->miss, mv[0], HIGHEST); else - { - vv->miss_type = MISSING_RANGE; - vv->missing[x++].f = mv[0]; - vv->missing[x++].f = mv[1]; - } + mv_add_num_range (&vv->miss, mv[0], mv[1]); if (sv.n_missing_values == -3) - { - vv->miss_type += 3; - vv->missing[x++].f = mv[2]; - } + mv_add_num (&vv->miss, mv[2]); } } - else - vv->miss_type = MISSING_NONE; if (!parse_format_spec (r, sv.print, &vv->print, vv) || !parse_format_spec (r, sv.write, &vv->write, vv)) goto error; - /* Add variable to list. */ - if (var_cap >= r->var_cnt) - { - var_cap = 2 + r->var_cnt * 2; - r->vars = xrealloc (r->vars, var_cap * sizeof *r->vars); - } - r->vars[r->var_cnt].width = vv->width; - r->vars[r->var_cnt].fv = vv->fv; - r->var_cnt++; + r->vars[i].width = vv->width; + r->vars[i].fv = vv->fv; + } /* Some consistency checks. */ @@ -984,6 +986,7 @@ read_variables (struct sfm_reader *r, "%d were read from file."), handle_get_filename (r->fh), r->value_cnt, next_value); + return 1; error: @@ -1055,8 +1058,15 @@ read_value_labels (struct sfm_reader *r, if (r->reverse_endian) bswap_int32 (&n_labels); + if ( n_labels >= ((int32) ~0) / sizeof *labels) + { + corrupt_msg(MW, _("%s: Invalid number of labels: %d. Ignoring labels."), + handle_get_filename (r->fh), n_labels); + n_labels = 0; + } + /* Allocate memory. */ - labels = xmalloc (n_labels * sizeof *labels); + labels = xcalloc (n_labels , sizeof *labels); for (i = 0; i < n_labels; i++) labels[i].label = NULL; @@ -1328,7 +1338,7 @@ read_compressed_data (struct sfm_reader *r, flt64 *buf) for (;;) { - for (; p < p_end; p++) + for (; p < p_end; p++){ switch (*p) { case 0: @@ -1382,7 +1392,7 @@ read_compressed_data (struct sfm_reader *r, flt64 *buf) goto success; break; } - + } /* We have reached the end of this instruction octet. Read another. */ if (r->ptr == NULL || r->ptr >= r->end) @@ -1433,7 +1443,7 @@ sfm_read_case (struct sfm_reader *r, struct ccase *c) { int i; - for (i = 0; i < r->var_cnt; i++) + for (i = 0; i < r->value_cnt; i++) if (r->vars[i].width == 0) bswap_flt64 (&case_data_rw (c, r->vars[i].fv)->f); } @@ -1445,7 +1455,7 @@ sfm_read_case (struct sfm_reader *r, struct ccase *c) { int i; - for (i = 0; i < r->var_cnt; i++) + for (i = 0; i < r->value_cnt; i++) if (r->vars[i].width == 0 && case_num (c, i) == r->sysmis) case_data_rw (c, r->vars[i].fv)->f = SYSMIS; } @@ -1473,7 +1483,7 @@ sfm_read_case (struct sfm_reader *r, struct ccase *c) return 0; } - for (i = 0; i < r->var_cnt; i++) + for (i = 0; i < r->value_cnt; i++) { struct sfm_var *v = &r->vars[i]; @@ -1482,9 +1492,9 @@ sfm_read_case (struct sfm_reader *r, struct ccase *c) flt64 f = *bounce_cur++; if (r->reverse_endian) bswap_flt64 (&f); - case_data_rw (c, i)->f = f == r->sysmis ? SYSMIS : f; + case_data_rw (c, v->fv)->f = f == r->sysmis ? SYSMIS : f; } - else + else if (v->width != -1) { memcpy (case_data_rw (c, v->fv)->s, bounce_cur, v->width); bounce_cur += DIV_RND_UP (v->width, sizeof (flt64));