Skip to content

Commit a57275f

Browse files
committed
Add support for alternative magic number and "TK" SAS versions
1 parent 22f28ed commit a57275f

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

src/sas/readstat_sas.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ unsigned char sas7bdat_magic_number[32] = {
2626
0x09, 0xc7, 0x31, 0x8c, 0x18, 0x1f, 0x10, 0x11
2727
};
2828

29+
unsigned char sas7bdat_magic_number_alt[32] = {
30+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33+
0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x10, 0x11
34+
};
35+
2936
unsigned char sas7bcat_magic_number[32] = {
3037
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3138
0x00, 0x00, 0x00, 0x00, 0xc2, 0xea, 0x81, 0x63,
@@ -171,6 +178,7 @@ readstat_error_t sas_read_header(readstat_io_t *io, sas_header_info_t *hinfo,
171178
goto cleanup;
172179
}
173180
if (memcmp(header_start.magic, sas7bdat_magic_number, sizeof(sas7bdat_magic_number)) != 0 &&
181+
memcmp(header_start.magic, sas7bdat_magic_number_alt, sizeof(sas7bdat_magic_number_alt)) != 0 &&
174182
memcmp(header_start.magic, sas7bcat_magic_number, sizeof(sas7bcat_magic_number)) != 0) {
175183
retval = READSTAT_ERROR_PARSE;
176184
goto cleanup;
@@ -309,9 +317,9 @@ readstat_error_t sas_read_header(readstat_io_t *io, sas_header_info_t *hinfo,
309317
retval = READSTAT_ERROR_READ;
310318
goto cleanup;
311319
}
312-
char major, revision_tag;
313-
int minor, revision;
314-
if (sscanf(header_end.release, "%c.%04d%c%1d", &major, &minor, &revision_tag, &revision) != 4) {
320+
char major, revision_tag, revision;
321+
int minor;
322+
if (sscanf(header_end.release, "%c.%04d%c%c", &major, &minor, &revision_tag, &revision) != 4) {
315323
retval = READSTAT_ERROR_PARSE;
316324
goto cleanup;
317325
}
@@ -327,12 +335,21 @@ readstat_error_t sas_read_header(readstat_io_t *io, sas_header_info_t *hinfo,
327335
goto cleanup;
328336
}
329337
// revision_tag is usually M, but J has been observed in the wild (not created with SAS?)
330-
if (revision_tag != 'M' && revision_tag != 'J') {
338+
// files have also been observed with TK in place of the revision details.
339+
if (revision_tag != 'M' && revision_tag != 'J' && revision_tag != 'T') {
331340
retval = READSTAT_ERROR_PARSE;
332341
goto cleanup;
333342
}
334343
hinfo->minor_version = minor;
335-
hinfo->revision = revision;
344+
if (revision >= '0' && revision <= '9') {
345+
hinfo->revision = revision - '0';
346+
} else if (revision_tag == 'T' && revision == 'K') {
347+
// files have been observed with TK in place of the revision details.
348+
hinfo->revision = 0;
349+
} else {
350+
retval = READSTAT_ERROR_PARSE;
351+
goto cleanup;
352+
}
336353

337354
if ((major == '8' || major == '9') && minor == 0 && revision == 0) {
338355
/* A bit of a hack, but most SAS installations are running a minor update */

src/sas/readstat_sas.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ typedef struct sas_text_ref_s {
114114
#define SAS_DEFAULT_FILE_VERSION 9
115115

116116
extern unsigned char sas7bdat_magic_number[32];
117+
extern unsigned char sas7bdat_magic_number_alt[32];
117118
extern unsigned char sas7bcat_magic_number[32];
118119

119120
uint64_t sas_read8(const char *data, int bswap);

0 commit comments

Comments
 (0)