WizardMac/ReadStat

Non-deterministic result of readstat_get_file_label in a DTA file

Closed this issue · 1 comments

When trying to get the file label from a DTA file I get a non-deterministic result.

The code is as follows:

#include "readstat.h"

struct Context {
	const char* label = nullptr;
};

int handle_metadata(readstat_metadata_t *metadata, void *ctx) {
    Context* context = (Context*)ctx;

    context->label = readstat_get_file_label(metadata);

    return READSTAT_HANDLER_OK;
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        printf("Usage: %s <filename>\n", argv[0]);
        return 1;
    }

    Context context{};
    readstat_error_t error = READSTAT_OK;
    readstat_parser_t *parser = readstat_parser_init();
    readstat_set_metadata_handler(parser, handle_metadata);

    error = readstat_parse_dta(parser, argv[1], &context);

    readstat_parser_free(parser);

    if (error != READSTAT_OK) {
        printf("Error processing %s: %d\n", argv[1], error);
        return 1;
    }
    printf("Address: %d\n", context.label);
    if (context.label) {
    	printf("Contents: %s\n", context.label);
    }
    return 0;
}

I compile the file with g++ and link against readstat, then execute the following:

➜  readstat ./a.out citytemp.dta
Address: 3506272
Contents: City Temperature Data

➜  readstat ./a.out citytemp.dta
Address: 36733216
Contents:  �D�l

➜  readstat ./a.out citytemp.dta
Address: 16302176
Contents: City Temperature Data

➜  readstat ./a.out citytemp.dta
Address: 672032
Contents:  A˻fr

As you can see, the contents of the string are different each time. I'm attaching the problematic file, although I have observed this behaviour with multiple files. Tested with Readstat 1.1.8.

citytemp.dta.zip

Hi, you need to copy the string inside handle_metadata. Try something like

struct Context {
	char label[1024];
};

int handle_metadata(readstat_metadata_t *metadata, void *ctx) {
    Context* context = (Context*)ctx;

    snprintf(context->label, sizeof(context->label), "%s",  readstat_get_file_label(metadata));

    return READSTAT_HANDLER_OK;
}