Skip to content
Open
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
27 changes: 22 additions & 5 deletions src/sas/readstat_sas.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ unsigned char sas7bdat_magic_number[32] = {
0x09, 0xc7, 0x31, 0x8c, 0x18, 0x1f, 0x10, 0x11
};

unsigned char sas7bdat_magic_number_alt[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x10, 0x11
};

unsigned char sas7bcat_magic_number[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc2, 0xea, 0x81, 0x63,
Expand Down Expand Up @@ -171,6 +178,7 @@ readstat_error_t sas_read_header(readstat_io_t *io, sas_header_info_t *hinfo,
goto cleanup;
}
if (memcmp(header_start.magic, sas7bdat_magic_number, sizeof(sas7bdat_magic_number)) != 0 &&
memcmp(header_start.magic, sas7bdat_magic_number_alt, sizeof(sas7bdat_magic_number_alt)) != 0 &&
memcmp(header_start.magic, sas7bcat_magic_number, sizeof(sas7bcat_magic_number)) != 0) {
retval = READSTAT_ERROR_PARSE;
goto cleanup;
Expand Down Expand Up @@ -309,9 +317,9 @@ readstat_error_t sas_read_header(readstat_io_t *io, sas_header_info_t *hinfo,
retval = READSTAT_ERROR_READ;
goto cleanup;
}
char major, revision_tag;
int minor, revision;
if (sscanf(header_end.release, "%c.%04d%c%1d", &major, &minor, &revision_tag, &revision) != 4) {
char major, revision_tag, revision;
int minor;
if (sscanf(header_end.release, "%c.%04d%c%c", &major, &minor, &revision_tag, &revision) != 4) {
retval = READSTAT_ERROR_PARSE;
goto cleanup;
}
Expand All @@ -327,12 +335,21 @@ readstat_error_t sas_read_header(readstat_io_t *io, sas_header_info_t *hinfo,
goto cleanup;
}
// revision_tag is usually M, but J has been observed in the wild (not created with SAS?)
if (revision_tag != 'M' && revision_tag != 'J') {
// files have also been observed with TK in place of the revision details.
if (revision_tag != 'M' && revision_tag != 'J' && revision_tag != 'T') {
retval = READSTAT_ERROR_PARSE;
goto cleanup;
}
hinfo->minor_version = minor;
hinfo->revision = revision;
if (revision >= '0' && revision <= '9') {
hinfo->revision = revision - '0';
} else if (revision_tag == 'T' && revision == 'K') {
// files have been observed with TK in place of the revision details.
hinfo->revision = 0;
} else {
retval = READSTAT_ERROR_PARSE;
goto cleanup;
}

if ((major == '8' || major == '9') && minor == 0 && revision == 0) {
/* A bit of a hack, but most SAS installations are running a minor update */
Expand Down
1 change: 1 addition & 0 deletions src/sas/readstat_sas.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ typedef struct sas_text_ref_s {
#define SAS_DEFAULT_FILE_VERSION 9

extern unsigned char sas7bdat_magic_number[32];
extern unsigned char sas7bdat_magic_number_alt[32];
extern unsigned char sas7bcat_magic_number[32];

uint64_t sas_read8(const char *data, int bswap);
Expand Down
Loading