Skip to content
Open
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
33 changes: 25 additions & 8 deletions src/spss/readstat_sav_read.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,10 @@ static readstat_error_t sav_skip_variable_record(sav_ctx_t *ctx) {
}
if (variable.n_missing_values) {
int n_missing_values = ctx->bswap ? byteswap4(variable.n_missing_values) : variable.n_missing_values;
if (io->seek(abs(n_missing_values) * sizeof(double), READSTAT_SEEK_CUR, io->io_ctx) == -1) {
retval = READSTAT_ERROR_SEEK;
int n_mv_abs = (n_missing_values < 0) ? -n_missing_values : n_missing_values;
if (n_mv_abs > 3) { retval = READSTAT_ERROR_PARSE; goto cleanup; }
if (io->seek((off_t)n_mv_abs * sizeof(double), READSTAT_SEEK_CUR, io->io_ctx) == -1) {
retval = READSTAT_ERROR_READ;
goto cleanup;
}
}
Expand All @@ -212,6 +214,11 @@ static readstat_error_t sav_read_variable_label(spss_varinfo_t *info, sav_ctx_t
if (label_len == 0)
goto cleanup;

if (label_len > 0xFFFF) {
retval = READSTAT_ERROR_PARSE;
goto cleanup;
}

label_capacity = (label_len + 3) / 4 * 4;
if ((label_buf = readstat_malloc(label_capacity)) == NULL) {
retval = READSTAT_ERROR_MALLOC;
Expand Down Expand Up @@ -622,9 +629,9 @@ static readstat_error_t sav_skip_document_record(sav_ctx_t *ctx) {
}
if (ctx->bswap)
n_lines = byteswap4(n_lines);
if (io->seek(n_lines * SPSS_DOC_LINE_SIZE, READSTAT_SEEK_CUR, io->io_ctx) == -1) {
retval = READSTAT_ERROR_SEEK;
goto cleanup;
if (n_lines > 0x3FFFFFF) { retval = READSTAT_ERROR_PARSE; goto cleanup; }
if (io->seek((off_t)n_lines * SPSS_DOC_LINE_SIZE, READSTAT_SEEK_CUR, io->io_ctx) == -1) {
retval = READSTAT_ERROR_READ; goto cleanup;
}

cleanup:
Expand Down Expand Up @@ -1113,7 +1120,7 @@ static readstat_error_t sav_parse_long_string_value_labels_record(const void *da

for (i=0; i<label_count; i++) {
uint32_t value_len = 0, label_len = 0;
uint32_t value_buffer_len = 0, label_buffer_len = 0;
size_t value_buffer_len = 0, label_buffer_len = 0;

if (data_ptr + sizeof(uint32_t) > data_end) {
retval = READSTAT_ERROR_PARSE;
Expand All @@ -1126,7 +1133,8 @@ static readstat_error_t sav_parse_long_string_value_labels_record(const void *da

data_ptr += sizeof(uint32_t);

value_buffer_len = value_len*4+1;
if (value_len > 0xFFFFFF) { retval = READSTAT_ERROR_PARSE; goto cleanup; }
value_buffer_len = (size_t)value_len*4+1;
value_buffer = readstat_realloc(value_buffer, value_buffer_len);
if (value_buffer == NULL) {
retval = READSTAT_ERROR_MALLOC;
Expand Down Expand Up @@ -1155,7 +1163,8 @@ static readstat_error_t sav_parse_long_string_value_labels_record(const void *da

data_ptr += sizeof(uint32_t);

label_buffer_len = label_len*4+1;
if (label_len > 0xFFFFFF) { retval = READSTAT_ERROR_PARSE; goto cleanup; }
label_buffer_len = (size_t)label_len*4+1;
label_buffer = readstat_realloc(label_buffer, label_buffer_len);
if (label_buffer == NULL) {
retval = READSTAT_ERROR_MALLOC;
Expand Down Expand Up @@ -1322,6 +1331,10 @@ static readstat_error_t sav_parse_records_pass1(sav_ctx_t *ctx) {
uint32_t subtype = extra_info[0];
size_t size = extra_info[1];
size_t count = extra_info[2];
if (size > 0 && count > 0x7FFFFFFF / size) {
retval = READSTAT_ERROR_PARSE;
goto cleanup;
}
data_len = size * count;
if (subtype == SAV_RECORD_SUBTYPE_INTEGER_INFO) {
if (data_len > sizeof(data_buf)) {
Expand Down Expand Up @@ -1410,6 +1423,10 @@ static readstat_error_t sav_parse_records_pass2(sav_ctx_t *ctx) {
uint32_t subtype = extra_info[0];
size_t size = extra_info[1];
size_t count = extra_info[2];
if (size > 0 && count > 0x7FFFFFFF / size) {
retval = READSTAT_ERROR_PARSE;
goto cleanup;
}
data_len = size * count;
if (data_buf_capacity < data_len) {
if ((data_buf = readstat_realloc(data_buf, data_buf_capacity = data_len)) == NULL) {
Expand Down