Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions src/spss/readstat_sav_write.c
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,7 @@ static readstat_error_t sav_emit_long_string_value_labels_record(readstat_writer
for (k=0; k<var_count; k++) {
readstat_variable_t *r_variable = readstat_get_label_set_variable(r_label_set, k);
int32_t name_len = strlen(r_variable->name);
int32_t user_width = r_variable->user_width;
int32_t storage_width = readstat_variable_get_storage_width(r_variable);
if (storage_width <= 8)
continue;
Expand All @@ -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;
}
Expand All @@ -954,12 +960,13 @@ static readstat_error_t sav_emit_long_string_value_labels_record(readstat_writer
for (k=0; k<var_count; k++) {
readstat_variable_t *r_variable = readstat_get_label_set_variable(r_label_set, k);
int32_t name_len = strlen(r_variable->name);
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)
Expand All @@ -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;

Expand All @@ -984,16 +991,16 @@ 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;

retval = readstat_write_bytes(writer, r_value_label->string_key, value_len);
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;
}
Expand Down
28 changes: 28 additions & 0 deletions src/test/test_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
}
}
},
Expand Down
1 change: 1 addition & 0 deletions src/test/test_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
28 changes: 16 additions & 12 deletions src/test/test_write.c
Original file line number Diff line number Diff line change
Expand Up @@ -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; i<file->rows; 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; i<file->rows; 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; i<label_set->value_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; i<label_set->value_labels_count; i++) {
if (label_set->value_labels[i].string_key_len > max_len)
max_len = label_set->value_labels[i].string_key_len;
}
}
}
}
Expand Down
Loading