diff --git a/src/spss/readstat_sav_write.c b/src/spss/readstat_sav_write.c index 4355a7a..0e16a92 100644 --- a/src/spss/readstat_sav_write.c +++ b/src/spss/readstat_sav_write.c @@ -913,6 +913,7 @@ static readstat_error_t sav_emit_long_string_value_labels_record(readstat_writer for (k=0; kname); + int32_t user_width = r_variable->user_width; int32_t storage_width = readstat_variable_get_storage_width(r_variable); if (storage_width <= 8) continue; @@ -928,8 +929,13 @@ static readstat_error_t sav_emit_long_string_value_labels_record(readstat_writer if (label_len > MAX_VALUE_LABEL_SIZE) label_len = MAX_VALUE_LABEL_SIZE; + if (r_value_label->string_key_len > user_width) { + retval = READSTAT_ERROR_STRING_VALUE_IS_TOO_LONG; + goto cleanup; + } + info_header.count += sizeof(int32_t); // value length - info_header.count += storage_width; + info_header.count += user_width; info_header.count += sizeof(int32_t); // label length info_header.count += label_len; } @@ -954,12 +960,13 @@ static readstat_error_t sav_emit_long_string_value_labels_record(readstat_writer for (k=0; kname); + int32_t user_width = r_variable->user_width; int32_t storage_width = readstat_variable_get_storage_width(r_variable); if (storage_width <= 8) continue; - space_buffer = realloc(space_buffer, storage_width); - memset(space_buffer, ' ', storage_width); + space_buffer = realloc(space_buffer, user_width); + memset(space_buffer, ' ', user_width); retval = readstat_write_bytes(writer, &name_len, sizeof(int32_t)); if (retval != READSTAT_OK) @@ -969,7 +976,7 @@ static readstat_error_t sav_emit_long_string_value_labels_record(readstat_writer if (retval != READSTAT_OK) goto cleanup; - retval = readstat_write_bytes(writer, &storage_width, sizeof(int32_t)); + retval = readstat_write_bytes(writer, &user_width, sizeof(int32_t)); if (retval != READSTAT_OK) goto cleanup; @@ -984,7 +991,7 @@ static readstat_error_t sav_emit_long_string_value_labels_record(readstat_writer if (label_len > MAX_VALUE_LABEL_SIZE) label_len = MAX_VALUE_LABEL_SIZE; - retval = readstat_write_bytes(writer, &storage_width, sizeof(int32_t)); + retval = readstat_write_bytes(writer, &user_width, sizeof(int32_t)); if (retval != READSTAT_OK) goto cleanup; @@ -992,8 +999,8 @@ static readstat_error_t sav_emit_long_string_value_labels_record(readstat_writer if (retval != READSTAT_OK) goto cleanup; - if (value_len < storage_width) { - retval = readstat_write_bytes(writer, space_buffer, storage_width - value_len); + if (value_len < user_width) { + retval = readstat_write_bytes(writer, space_buffer, user_width - value_len); if (retval != READSTAT_OK) goto cleanup; } diff --git a/src/test/test_list.h b/src/test/test_list.h index 90f4f6d..61dca89 100644 --- a/src/test/test_list.h +++ b/src/test/test_list.h @@ -1737,6 +1737,34 @@ static rt_test_group_t _test_groups[] = { .label_set = "labels0" } } + }, + + { + .label = "SAV long string value label key too long", + .write_error = READSTAT_ERROR_STRING_VALUE_IS_TOO_LONG, + .test_formats = RT_FORMAT_SAV, + .label_sets_count = 1, + .label_sets = { + { + .name = "labels0", + .type = READSTAT_TYPE_STRING, + .value_labels_count = 1, + .value_labels = { + { + .value = { .type = READSTAT_TYPE_STRING, .v = { .string_value = "0123456789ABCDEFG" } }, + .label = "Too long key" + } + } + } + }, + .columns = { + { + .name = "VAR1", + .type = READSTAT_TYPE_STRING, + .user_width = 9, + .label_set = "labels0" + } + } } } }, diff --git a/src/test/test_types.h b/src/test/test_types.h index c0d762d..f0a55e0 100644 --- a/src/test/test_types.h +++ b/src/test/test_types.h @@ -28,6 +28,7 @@ typedef struct rt_column_s { char label[RT_MAX_STRING]; char format[RT_MAX_STRING]; int display_width; + int user_width; readstat_alignment_t alignment; readstat_measure_t measure; readstat_type_t type; diff --git a/src/test/test_write.c b/src/test/test_write.c index 8d68997..89f337b 100644 --- a/src/test/test_write.c +++ b/src/test/test_write.c @@ -89,19 +89,23 @@ readstat_error_t write_file_to_buffer(rt_test_file_t *file, rt_buffer_t *buffer, size_t max_len = 0; if (column->type == READSTAT_TYPE_STRING) { - max_len = 8; - for (i=0; irows; i++) { - const char *value = readstat_string_value(column->values[i]); - if (value) { - size_t len = strlen(value); - if (len > max_len) - max_len = len; + if (column->user_width > 0) { + max_len = column->user_width; + } else { + max_len = 8; + for (i=0; irows; i++) { + const char *value = readstat_string_value(column->values[i]); + if (value) { + size_t len = strlen(value); + if (len > max_len) + max_len = len; + } } - } - if (label_set) { - for (i=0; ivalue_labels_count; i++) { - if (label_set->value_labels[i].string_key_len > max_len) - max_len = label_set->value_labels[i].string_key_len; + if (label_set) { + for (i=0; ivalue_labels_count; i++) { + if (label_set->value_labels[i].string_key_len > max_len) + max_len = label_set->value_labels[i].string_key_len; + } } } }