readfile: report SDNA decoding errors on file read

This was printed to the stdout, however the error case wasn't checked or well supported.
Also, errors decoding SDNA would sometimes call exit(1).
This commit is contained in:
Campbell Barton 2016-07-12 12:23:48 +10:00
parent 0b3183d13c
commit 4db1db327a
5 changed files with 72 additions and 29 deletions

@ -909,7 +909,10 @@ static void decode_blender_header(FileData *fd)
}
}
static int read_file_dna(FileData *fd)
/**
* \return Success if the file is read correctly, else set \a r_error_message.
*/
static bool read_file_dna(FileData *fd, const char **r_error_message)
{
BHead *bhead;
@ -917,20 +920,25 @@ static int read_file_dna(FileData *fd)
if (bhead->code == DNA1) {
const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
fd->filesdna = DNA_sdna_from_data(&bhead[1], bhead->len, do_endian_swap, true);
fd->filesdna = DNA_sdna_from_data(&bhead[1], bhead->len, do_endian_swap, true, r_error_message);
if (fd->filesdna) {
fd->compflags = DNA_struct_get_compareflags(fd->filesdna, fd->memsdna);
/* used to retrieve ID names from (bhead+1) */
fd->id_name_offs = DNA_elem_offset(fd->filesdna, "ID", "char", "name[]");
return true;
}
else {
return false;
}
return 1;
}
else if (bhead->code == ENDB)
break;
}
return 0;
*r_error_message = "Missing DNA block";
return false;
}
static int *read_file_thumbnail(FileData *fd)
@ -1077,7 +1085,7 @@ static FileData *filedata_new(void)
* but it keeps us re-entrant, remove once we have
* a lib that provides a nice lock. - zr
*/
fd->memsdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false);
fd->memsdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, NULL);
fd->datamap = oldnewmap_new();
fd->globmap = oldnewmap_new();
@ -1091,8 +1099,11 @@ static FileData *blo_decode_and_check(FileData *fd, ReportList *reports)
decode_blender_header(fd);
if (fd->flags & FD_FLAGS_FILE_OK) {
if (!read_file_dna(fd)) {
BKE_reportf(reports, RPT_ERROR, "Failed to read blend file '%s', incomplete", fd->relabase);
const char *error_message = NULL;
if (read_file_dna(fd, &error_message) == false) {
BKE_reportf(reports, RPT_ERROR,
"Failed to read blend file '%s': %s",
fd->relabase, error_message);
blo_freefiledata(fd);
fd = NULL;
}

@ -325,7 +325,7 @@ static WriteData *writedata_new(WriteWrap *ww)
{
WriteData *wd = MEM_callocN(sizeof(*wd), "writedata");
wd->sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false);
wd->sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, NULL);
wd->ww = ww;

@ -76,7 +76,8 @@ enum eSDNA_StructCompare {
struct SDNA *DNA_sdna_from_data(
const void *data, const int datalen,
bool do_endian_swap, bool data_alloc);
bool do_endian_swap, bool data_alloc,
const char **r_error_message);
void DNA_sdna_free(struct SDNA *sdna);
int DNA_struct_find_nr_ex(const struct SDNA *sdna, const char *str, unsigned int *index_last);

@ -341,7 +341,9 @@ int DNA_struct_find_nr(const SDNA *sdna, const char *str)
/**
* In sdna->data the data, now we convert that to something understandable
*/
static void init_structDNA(SDNA *sdna, bool do_endian_swap)
static bool init_structDNA(
SDNA *sdna, bool do_endian_swap,
const char **r_error_message)
{
int *data, *verg, gravity_fix = -1;
short *sp;
@ -350,10 +352,18 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
verg = (int *)str;
data = (int *)sdna->data;
/* clear pointers incase of error */
sdna->names = NULL;
sdna->types = NULL;
sdna->structs = NULL;
#ifdef WITH_DNA_GHASH
sdna->structs_map = NULL;
#endif
strcpy(str, "SDNA");
if (*data != *verg) {
printf("SDNA error in SDNA file\n");
return;
*r_error_message = "SDNA error in SDNA file";
return false;
}
else {
intptr_t nr;
@ -373,8 +383,8 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
sdna->names = MEM_callocN(sizeof(void *) * sdna->nr_names, "sdnanames");
}
else {
printf("NAME error in SDNA file\n");
return;
*r_error_message = "NAME error in SDNA file";
return false;
}
nr = 0;
@ -413,8 +423,8 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
sdna->types = MEM_callocN(sizeof(void *) * sdna->nr_types, "sdnatypes");
}
else {
printf("TYPE error in SDNA file\n");
return;
*r_error_message = "TYPE error in SDNA file";
return false;
}
nr = 0;
@ -459,8 +469,8 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
sp += sdna->nr_types;
}
else {
printf("TLEN error in SDNA file\n");
return;
*r_error_message = "TLEN error in SDNA file";
return false;
}
if (sdna->nr_types & 1) sp++; /* prevent BUS error */
@ -477,8 +487,8 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
sdna->structs = MEM_callocN(sizeof(void *) * sdna->nr_structs, "sdnastrcs");
}
else {
printf("STRC error in SDNA file\n");
return;
*r_error_message = "STRC error in SDNA file";
return false;
}
nr = 0;
@ -537,8 +547,8 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
/* should never happen, only with corrupt file for example */
if (UNLIKELY(nr == -1)) {
printf("ListBase struct error! Not found.\n");
exit(1);
*r_error_message = "ListBase struct error! Not found.";
return false;
}
/* finally pointerlen: use struct ListBase to test it, never change the size of it! */
@ -548,11 +558,13 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
sdna->pointerlen = sdna->typelens[sp[0]] / 2;
if (sp[1] != 2 || (sdna->pointerlen != 4 && sdna->pointerlen != 8)) {
printf("ListBase struct error! Needs it to calculate pointerize.\n");
exit(1);
*r_error_message = "ListBase struct error! Needs it to calculate pointerize.";
/* well, at least sizeof(ListBase) is error proof! (ton) */
return false;
}
}
return true;
}
/**
@ -560,9 +572,11 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
*/
SDNA *DNA_sdna_from_data(
const void *data, const int datalen,
bool do_endian_swap, bool data_alloc)
bool do_endian_swap, bool data_alloc,
const char **r_error_message)
{
SDNA *sdna = MEM_mallocN(sizeof(*sdna), "sdna");
const char *error_message = NULL;
sdna->datalen = datalen;
if (data_alloc) {
@ -575,9 +589,20 @@ SDNA *DNA_sdna_from_data(
}
sdna->data_alloc = data_alloc;
init_structDNA(sdna, do_endian_swap);
return sdna;
if (init_structDNA(sdna, do_endian_swap, &error_message)) {
return sdna;
}
else {
if (r_error_message == NULL) {
fprintf(stderr, "Error decoding blend file SDNA: %s\n", error_message);
}
else {
*r_error_message = error_message;
}
DNA_sdna_free(sdna);
return NULL;
}
}
/* ******************** END READ DNA ********************** */

@ -531,12 +531,18 @@ BlenderRNA *RNA_create(void)
BlenderRNA *brna;
brna = MEM_callocN(sizeof(BlenderRNA), "BlenderRNA");
const char *error_message = NULL;
DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false);
BLI_listbase_clear(&DefRNA.structs);
DefRNA.error = 0;
DefRNA.preprocess = 1;
DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, &error_message);
if (DefRNA.sdna == NULL) {
fprintf(stderr, "Error decoding SDNA: %s\n", error_message);
DefRNA.error = 1;
}
return brna;
}