[Scummvm-cvs-logs] SF.net SVN: scummvm:[50339] scummvm/trunk/engines/sci

m_kiewitz at users.sourceforge.net m_kiewitz at users.sourceforge.net
Sat Jun 26 21:55:50 CEST 2010


Revision: 50339
          http://scummvm.svn.sourceforge.net/scummvm/?rev=50339&view=rev
Author:   m_kiewitz
Date:     2010-06-26 19:55:49 +0000 (Sat, 26 Jun 2010)

Log Message:
-----------
SCI: do boundary checking when loading sci1 sounds and mixing them together. The final end credits song (resource 699) in kq5 has some channels with invalid offsets, crashing ScummVM before

Modified Paths:
--------------
    scummvm/trunk/engines/sci/resource.h
    scummvm/trunk/engines/sci/resource_audio.cpp
    scummvm/trunk/engines/sci/sound/midiparser_sci.cpp

Modified: scummvm/trunk/engines/sci/resource.h
===================================================================
--- scummvm/trunk/engines/sci/resource.h	2010-06-26 19:09:45 UTC (rev 50338)
+++ scummvm/trunk/engines/sci/resource.h	2010-06-26 19:55:49 UTC (rev 50339)
@@ -492,6 +492,7 @@
 		uint16 prio;
 		uint16 size;
 		byte *data;
+		uint16 curPos;
 		long time;
 		byte prev;
 	};

Modified: scummvm/trunk/engines/sci/resource_audio.cpp
===================================================================
--- scummvm/trunk/engines/sci/resource_audio.cpp	2010-06-26 19:09:45 UTC (rev 50338)
+++ scummvm/trunk/engines/sci/resource_audio.cpp	2010-06-26 19:55:49 UTC (rev 50339)
@@ -480,8 +480,8 @@
 	return (_audioMapSCI1 ? _audioMapSCI1->_volumeNumber : 0);
 }
 
-SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) {
-	Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resNumber), true);
+SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) {
+	Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resourceNr), true);
 	int trackNr, channelNr;
 	if (!resource)
 		return;
@@ -554,6 +554,9 @@
 		}
 		_tracks = new Track[_trackCount];
 		data = resource->data;
+
+		byte channelCount;
+
 		for (trackNr = 0; trackNr < _trackCount; trackNr++) {
 			// Track info starts with track type:BYTE
 			// Then the channel information gets appended Unknown:WORD, ChannelOffset:WORD, ChannelSize:WORD
@@ -563,34 +566,47 @@
 			_tracks[trackNr].type = *data++;
 			// Counting # of channels used
 			data2 = data;
-			_tracks[trackNr].channelCount = 0;
+			channelCount = 0;
 			while (*data2 != 0xFF) {
 				data2 += 6;
+				channelCount++;
 				_tracks[trackNr].channelCount++;
 			}
-			_tracks[trackNr].channels = new Channel[_tracks[trackNr].channelCount];
+			_tracks[trackNr].channels = new Channel[channelCount];
+			_tracks[trackNr].channelCount = 0;
 			_tracks[trackNr].digitalChannelNr = -1; // No digital sound associated
 			_tracks[trackNr].digitalSampleRate = 0;
 			_tracks[trackNr].digitalSampleSize = 0;
 			_tracks[trackNr].digitalSampleStart = 0;
 			_tracks[trackNr].digitalSampleEnd = 0;
 			if (_tracks[trackNr].type != 0xF0) { // Digital track marker - not supported currently
-				for (channelNr = 0; channelNr < _tracks[trackNr].channelCount; channelNr++) {
+				channelNr = 0;
+				while (channelCount--) {
 					channel = &_tracks[trackNr].channels[channelNr];
 					channel->prio = READ_LE_UINT16(data);
-					channel->data = resource->data + READ_LE_UINT16(data + 2) + 2;
-					channel->size = READ_LE_UINT16(data + 4) - 2; // Not counting channel header
-					channel->number = *(channel->data - 2);
-					channel->poly = *(channel->data - 1);
-					channel->time = channel->prev = 0;
-					if (channel->number == 0xFE) { // Digital channel
-						_tracks[trackNr].digitalChannelNr = channelNr;
-						_tracks[trackNr].digitalSampleRate = READ_LE_UINT16(channel->data);
-						_tracks[trackNr].digitalSampleSize = READ_LE_UINT16(channel->data + 2);
-						_tracks[trackNr].digitalSampleStart = READ_LE_UINT16(channel->data + 4);
-						_tracks[trackNr].digitalSampleEnd = READ_LE_UINT16(channel->data + 6);
-						channel->data += 8; // Skip over header
-						channel->size -= 8;
+					uint dataOffset = READ_LE_UINT16(data + 2);
+					if (dataOffset < resource->size) {
+						channel->data = resource->data + dataOffset;
+						channel->size = READ_LE_UINT16(data + 4);
+						channel->curPos = 0;
+						channel->number = *channel->data;
+						channel->poly = *(channel->data + 1);
+						channel->time = channel->prev = 0;
+						channel->data += 2; // skip over header
+						channel->size -= 2; // remove header size
+						if (channel->number == 0xFE) { // Digital channel
+							_tracks[trackNr].digitalChannelNr = channelNr;
+							_tracks[trackNr].digitalSampleRate = READ_LE_UINT16(channel->data);
+							_tracks[trackNr].digitalSampleSize = READ_LE_UINT16(channel->data + 2);
+							_tracks[trackNr].digitalSampleStart = READ_LE_UINT16(channel->data + 4);
+							_tracks[trackNr].digitalSampleEnd = READ_LE_UINT16(channel->data + 6);
+							channel->data += 8; // Skip over header
+							channel->size -= 8;
+						}
+						_tracks[trackNr].channelCount++;
+						channelNr++;
+					} else {
+						warning("Invalid offset inside sound resource %d: track %d, channel %d", resourceNr, trackNr, channelNr);
 					}
 					data += 6;
 				}

Modified: scummvm/trunk/engines/sci/sound/midiparser_sci.cpp
===================================================================
--- scummvm/trunk/engines/sci/sound/midiparser_sci.cpp	2010-06-26 19:09:45 UTC (rev 50338)
+++ scummvm/trunk/engines/sci/sound/midiparser_sci.cpp	2010-06-26 19:55:49 UTC (rev 50339)
@@ -422,7 +422,10 @@
 	for (int i = 0; i < _track->channelCount; i++) {
 		if (_track->channels[i].time == -1) // channel ended
 			continue;
-		next = *_track->channels[i].data; // when the next event should occur
+		SoundResource::Channel *curChannel = &_track->channels[i];
+		if (curChannel->curPos >= curChannel->size)
+			continue;
+		next = curChannel->data[curChannel->curPos]; // when the next event should occur
 		if (next == 0xF8) // 0xF8 means 240 ticks delay
 			next = 240;
 		next += _track->channels[i].time;
@@ -449,21 +452,21 @@
 	byte *outData = new byte[totalSize * 2]; // FIXME: creates overhead and still may be not enough to hold all data
 	_mixedData = outData;
 	long ticker = 0;
-	byte curr, curDelta;
+	byte channelNr, curDelta;
 	byte command = 0, par1, global_prev = 0;
 	long new_delta;
 	SoundResource::Channel *channel;
 
-	while ((curr = midiGetNextChannel(ticker)) != 0xFF) { // there is still an active channel
-		channel = &_track->channels[curr];
-		curDelta = *channel->data++;
+	while ((channelNr = midiGetNextChannel(ticker)) != 0xFF) { // there is still an active channel
+		channel = &_track->channels[channelNr];
+		curDelta = channel->data[channel->curPos++];
 		channel->time += (curDelta == 0xF8 ? 240 : curDelta); // when the command is supposed to occur
 		if (curDelta == 0xF8)
 			continue;
 		new_delta = channel->time - ticker;
 		ticker += new_delta;
 
-		command = *channel->data++;
+		command = channel->data[channel->curPos++];
 		if (command != kEndOfTrack) {
 			debugC(4, kDebugLevelSound, "\nDELTA ");
 			// Write delta
@@ -481,7 +484,7 @@
 			*outData++ = command;
 			debugC(4, kDebugLevelSound, "%02X ", command);
 			do {
-				par1 = *channel->data++;
+				par1 = channel->data[channel->curPos++];
 				*outData++ = par1; // out
 			} while (par1 != 0xF7);
 			break;
@@ -492,7 +495,7 @@
 			break;
 		default: // MIDI command
 			if (command & 0x80) {
-				par1 = *channel->data++;
+				par1 = channel->data[channel->curPos++];
 			} else {// running status
 				par1 = command;
 				command = channel->prev;
@@ -506,7 +509,7 @@
 				*outData++ = command; // out command
 			*outData++ = par1;// pout par1
 			if (nMidiParams[(command >> 4) - 8] == 2)
-				*outData++ = *channel->data++; // out par2
+				*outData++ = channel->data[channel->curPos++]; // out par2
 			channel->prev = command;
 			global_prev = command;
 		}// switch(command)


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list