[Scummvm-cvs-logs] scummvm master -> 57cc59356c14d516c128797e5a17b322ad90820c

lordhoto lordhoto at gmail.com
Sat Jul 13 00:34:09 CEST 2013


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
e9bb9ddcf5 GRAPHICS: Be more robust with broken/unsupported thumbnail headers.
57cc59356c Merge pull request #355 from lordhoto/skip-thumbnail


Commit: e9bb9ddcf5cf2a4aa87ae9705e7ec2d69600becd
    https://github.com/scummvm/scummvm/commit/e9bb9ddcf5cf2a4aa87ae9705e7ec2d69600becd
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2013-07-12T13:54:53-07:00

Commit Message:
GRAPHICS: Be more robust with broken/unsupported thumbnail headers.

This fixes future issues like bug #3614654:
"ALL: ScummVM 1.5.0 can't read newer saved games".

There are a few behavior changes introduced with this commit:

- checkThumbnailHeader will now also report the presence of
  unsupported/broken (but skippable) headers.

- skipThumbnail will also try to skip the data for broken/unsupported
  thumbnail data.

- loadThumbnail will skip over broken/unsupported thumbnail data but still
  return 0 in this case.

Changed paths:
    graphics/thumbnail.cpp



diff --git a/graphics/thumbnail.cpp b/graphics/thumbnail.cpp
index d04c218..e3f368d 100644
--- a/graphics/thumbnail.cpp
+++ b/graphics/thumbnail.cpp
@@ -43,7 +43,16 @@ struct ThumbnailHeader {
 
 #define ThumbnailHeaderSize (4+4+1+2+2+(1+4+4))
 
-bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool outputWarnings) {
+enum HeaderState {
+	/// There is no header present
+	kHeaderNone,
+	/// The header present only has reliable values for version and size
+	kHeaderUnsupported,
+	/// The header is present and the version is supported
+	kHeaderPresent
+};
+
+HeaderState loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool outputWarnings) {
 	header.type = in.readUint32BE();
 	// We also accept the bad 'BMHT' header here, for the sake of compatibility
 	// with some older savegames which were written incorrectly due to a bug in
@@ -51,16 +60,28 @@ bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool ou
 	if (header.type != MKTAG('T','H','M','B') && header.type != MKTAG('B','M','H','T')) {
 		if (outputWarnings)
 			warning("couldn't find thumbnail header type");
-		return false;
+		return kHeaderNone;
 	}
 
 	header.size = in.readUint32BE();
 	header.version = in.readByte();
 
+	// Do a check whether any read errors had occured. If so we cannot use the
+	// values obtained for size and version because they might be bad.
+	if (in.err() || in.eos()) {
+		// TODO: We fake that there is no header. This is actually not quite
+		// correct since we found the start of the header and then things
+		// started to break. Right no we leave detection of this to the client.
+		// Since this case is caused by broken files, the client code should
+		// catch it anyway... If there is a nicer solution here, we should
+		// implement it.
+		return kHeaderNone;
+	}
+
 	if (header.version > THMB_VERSION) {
 		if (outputWarnings)
 			warning("trying to load a newer thumbnail version: %d instead of %d", header.version, THMB_VERSION);
-		return false;
+		return kHeaderUnsupported;
 	}
 
 	header.width = in.readUint16BE();
@@ -82,7 +103,15 @@ bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool ou
 		header.format = createPixelFormat<565>();
 	}
 
-	return true;
+	if (in.err() || in.eos()) {
+		// When we reached this point we know that at least the size and
+		// version field was loaded successfully, thus we tell this header
+		// is not supported and silently hope that the client code is
+		// prepared to handle read errors.
+		return kHeaderUnsupported;
+	} else {
+		return kHeaderPresent;
+	}
 }
 } // end of anonymous namespace
 
@@ -90,7 +119,12 @@ bool checkThumbnailHeader(Common::SeekableReadStream &in) {
 	uint32 position = in.pos();
 	ThumbnailHeader header;
 
-	bool hasHeader = loadHeader(in, header, false);
+	// TODO: It is not clear whether this is the best semantics. Now
+	// checkThumbnailHeader will return true even when the thumbnail header
+	// found is actually not usable. However, most engines seem to use this
+	// to detect the presence of any header and if there is none it wont even
+	// try to skip it. Thus, this looks like the best solution for now...
+	bool hasHeader = (loadHeader(in, header, false) != kHeaderNone);
 
 	in.seek(position, SEEK_SET);
 
@@ -101,7 +135,9 @@ bool skipThumbnail(Common::SeekableReadStream &in) {
 	uint32 position = in.pos();
 	ThumbnailHeader header;
 
-	if (!loadHeader(in, header, false)) {
+	// We can skip unsupported and supported headers. So we only seek back
+	// to the old position in case there is no header at all.
+	if (loadHeader(in, header, false) == kHeaderNone) {
 		in.seek(position, SEEK_SET);
 		return false;
 	}
@@ -111,10 +147,23 @@ bool skipThumbnail(Common::SeekableReadStream &in) {
 }
 
 Graphics::Surface *loadThumbnail(Common::SeekableReadStream &in) {
+	const uint32 position = in.pos();
 	ThumbnailHeader header;
-
-	if (!loadHeader(in, header, true))
+	HeaderState headerState = loadHeader(in, header, true);
+
+	// Try to handle unsupported/broken headers gracefully. If there is no
+	// header at all, we seek back and return at this point. If there is an
+	// unsupported/broken header, we skip the actual data and return. The
+	// downside is that we might reset the end of stream flag with this and
+	// the client code would not be able to notice a read past the end of the
+	// stream at this point then.
+	if (headerState == kHeaderNone) {
+		in.seek(position, SEEK_SET);
+		return 0;
+	} else if (headerState == kHeaderUnsupported) {
+		in.seek(header.size - (in.pos() - position), SEEK_CUR);
 		return 0;
+	}
 
 	if (header.format.bytesPerPixel != 2 && header.format.bytesPerPixel != 4) {
 		warning("trying to load thumbnail with unsupported bit depth %d", header.format.bytesPerPixel);


Commit: 57cc59356c14d516c128797e5a17b322ad90820c
    https://github.com/scummvm/scummvm/commit/57cc59356c14d516c128797e5a17b322ad90820c
Author: Johannes Schickel (lordhoto at gmail.com)
Date: 2013-07-12T15:33:19-07:00

Commit Message:
Merge pull request #355 from lordhoto/skip-thumbnail

GRAPHICS: Be more robust with broken/unsupported thumbnail headers.

Changed paths:
    graphics/thumbnail.cpp









More information about the Scummvm-git-logs mailing list