[Bf-blender-cvs] [4db1db3] master: readfile: report SDNA decoding errors on file read

Campbell Barton noreply at git.blender.org
Tue Jul 12 05:00:27 CEST 2016


Commit: 4db1db327a0613abee950ffe12b013afdec2c111
Author: Campbell Barton
Date:   Tue Jul 12 12:23:48 2016 +1000
Branches: master
https://developer.blender.org/rB4db1db327a0613abee950ffe12b013afdec2c111

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).

===================================================================

M	source/blender/blenloader/intern/readfile.c
M	source/blender/blenloader/intern/writefile.c
M	source/blender/makesdna/DNA_genfile.h
M	source/blender/makesdna/intern/dna_genfile.c
M	source/blender/makesrna/intern/rna_define.c

===================================================================

diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 27a119a..eeb8a5d 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -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;
 		}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index bd19f2a..f898eea 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -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;
 
diff --git a/source/blender/makesdna/DNA_genfile.h b/source/blender/makesdna/DNA_genfile.h
index 1b558b1..27a3ff8 100644
--- a/source/blender/makesdna/DNA_genfile.h
+++ b/source/blender/makesdna/DNA_genfile.h
@@ -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);
diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c
index 1d9e971..f1d48c0 100644
--- a/source/blender/makesdna/intern/dna_genfile.c
+++ b/source/blender/makesdna/intern/dna_genfile.c
@@ -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 ********************** */
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index bf2b091..7ff4eae 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -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;
 }




More information about the Bf-blender-cvs mailing list