Browse Source

Merge pull request #36095 from timothyqiu/corrupted-resource

Fixes crash when resource file is corrupted
Rémi Verschelde 5 years ago
parent
commit
948d95897c
2 changed files with 33 additions and 16 deletions
  1. 5 3
      core/io/file_access_compressed.cpp
  2. 28 13
      core/io/resource_format_binary.cpp

+ 5 - 3
core/io/file_access_compressed.cpp

@@ -63,6 +63,10 @@ Error FileAccessCompressed::open_after_magic(FileAccess *p_base) {
 	f = p_base;
 	f = p_base;
 	cmode = (Compression::Mode)f->get_32();
 	cmode = (Compression::Mode)f->get_32();
 	block_size = f->get_32();
 	block_size = f->get_32();
+	if (block_size == 0) {
+		f = NULL; // Let the caller to handle the FileAccess object if failed to open as compressed file.
+		ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Can't open compressed file '" + p_base->get_path() + "' with block size 0, it is corrupted.");
+	}
 	read_total = f->get_32();
 	read_total = f->get_32();
 	int bc = (read_total / block_size) + 1;
 	int bc = (read_total / block_size) + 1;
 	int acc_ofs = f->get_position() + bc * 4;
 	int acc_ofs = f->get_position() + bc * 4;
@@ -125,13 +129,11 @@ Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) {
 		char rmagic[5];
 		char rmagic[5];
 		f->get_buffer((uint8_t *)rmagic, 4);
 		f->get_buffer((uint8_t *)rmagic, 4);
 		rmagic[4] = 0;
 		rmagic[4] = 0;
-		if (magic != rmagic) {
+		if (magic != rmagic || open_after_magic(f) != OK) {
 			memdelete(f);
 			memdelete(f);
 			f = NULL;
 			f = NULL;
 			return ERR_FILE_UNRECOGNIZED;
 			return ERR_FILE_UNRECOGNIZED;
 		}
 		}
-
-		open_after_magic(f);
 	}
 	}
 
 
 	return OK;
 	return OK;

+ 28 - 13
core/io/resource_format_binary.cpp

@@ -836,15 +836,20 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
 	uint8_t header[4];
 	uint8_t header[4];
 	f->get_buffer(header, 4);
 	f->get_buffer(header, 4);
 	if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') {
 	if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') {
-		//compressed
+		// Compressed.
 		FileAccessCompressed *fac = memnew(FileAccessCompressed);
 		FileAccessCompressed *fac = memnew(FileAccessCompressed);
-		fac->open_after_magic(f);
+		error = fac->open_after_magic(f);
+		if (error != OK) {
+			memdelete(fac);
+			f->close();
+			ERR_FAIL_MSG("Failed to open binary resource file: " + local_path + ".");
+		}
 		f = fac;
 		f = fac;
 
 
 	} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
 	} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
-		//not normal
-
+		// Not normal.
 		error = ERR_FILE_UNRECOGNIZED;
 		error = ERR_FILE_UNRECOGNIZED;
+		f->close();
 		ERR_FAIL_MSG("Unrecognized binary resource file: " + local_path + ".");
 		ERR_FAIL_MSG("Unrecognized binary resource file: " + local_path + ".");
 	}
 	}
 
 
@@ -919,6 +924,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
 	if (f->eof_reached()) {
 	if (f->eof_reached()) {
 
 
 		error = ERR_FILE_CORRUPT;
 		error = ERR_FILE_CORRUPT;
+		f->close();
 		ERR_FAIL_MSG("Premature end of file (EOF): " + local_path + ".");
 		ERR_FAIL_MSG("Premature end of file (EOF): " + local_path + ".");
 	}
 	}
 }
 }
@@ -931,14 +937,20 @@ String ResourceInteractiveLoaderBinary::recognize(FileAccess *p_f) {
 	uint8_t header[4];
 	uint8_t header[4];
 	f->get_buffer(header, 4);
 	f->get_buffer(header, 4);
 	if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') {
 	if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') {
-		//compressed
+		// Compressed.
 		FileAccessCompressed *fac = memnew(FileAccessCompressed);
 		FileAccessCompressed *fac = memnew(FileAccessCompressed);
-		fac->open_after_magic(f);
+		error = fac->open_after_magic(f);
+		if (error != OK) {
+			memdelete(fac);
+			f->close();
+			return "";
+		}
 		f = fac;
 		f = fac;
 
 
 	} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
 	} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
-		//not normal
+		// Not normal.
 		error = ERR_FILE_UNRECOGNIZED;
 		error = ERR_FILE_UNRECOGNIZED;
+		f->close();
 		return "";
 		return "";
 	}
 	}
 
 
@@ -1055,14 +1067,19 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
 	uint8_t header[4];
 	uint8_t header[4];
 	f->get_buffer(header, 4);
 	f->get_buffer(header, 4);
 	if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') {
 	if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') {
-		//compressed
+		// Compressed.
 		FileAccessCompressed *fac = memnew(FileAccessCompressed);
 		FileAccessCompressed *fac = memnew(FileAccessCompressed);
-		fac->open_after_magic(f);
+		Error err = fac->open_after_magic(f);
+		if (err != OK) {
+			memdelete(fac);
+			memdelete(f);
+			ERR_FAIL_V_MSG(err, "Cannot open file '" + p_path + "'.");
+		}
 		f = fac;
 		f = fac;
 
 
 		FileAccessCompressed *facw = memnew(FileAccessCompressed);
 		FileAccessCompressed *facw = memnew(FileAccessCompressed);
 		facw->configure("RSCC");
 		facw->configure("RSCC");
-		Error err = facw->_open(p_path + ".depren", FileAccess::WRITE);
+		err = facw->_open(p_path + ".depren", FileAccess::WRITE);
 		if (err) {
 		if (err) {
 			memdelete(fac);
 			memdelete(fac);
 			memdelete(facw);
 			memdelete(facw);
@@ -1072,9 +1089,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
 		fw = facw;
 		fw = facw;
 
 
 	} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
 	} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
-		//not normal
-
-		//error=ERR_FILE_UNRECOGNIZED;
+		// Not normal.
 		memdelete(f);
 		memdelete(f);
 		ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unrecognized binary resource file '" + local_path + "'.");
 		ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unrecognized binary resource file '" + local_path + "'.");
 	} else {
 	} else {