X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Fsfm-read.c;h=fef4eb5cf5d0f79a002b0c8d9a274df1b8ad535f;hb=a1c8f6fe2935432af4dbe30aef2434c6ad437a56;hp=f0f9923d886097d6a81d788bedb3a46ad3abaa00;hpb=66f7c229748ba9f8bbcb6255caacb0689790a0da;p=pspp diff --git a/src/sfm-read.c b/src/sfm-read.c index f0f9923d88..fef4eb5cf5 100644 --- a/src/sfm-read.c +++ b/src/sfm-read.c @@ -59,7 +59,6 @@ struct sfm_reader /* Variables. */ struct sfm_var *vars; /* Variables. */ - size_t var_cnt; /* Number of variables. */ /* File's special constants. */ flt64 sysmis; @@ -221,7 +220,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 +242,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 +342,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 +350,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 +421,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 +749,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 +756,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 +767,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 +790,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 +810,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 +874,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. */ @@ -962,15 +985,9 @@ read_variables (struct sfm_reader *r, || !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 +1001,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 +1073,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 +1353,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 +1407,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 +1458,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 +1470,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 +1498,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 +1507,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));