diff options
| author | Filippos Karapetis | 2010-08-17 23:55:07 +0000 | 
|---|---|---|
| committer | Filippos Karapetis | 2010-08-17 23:55:07 +0000 | 
| commit | e32010392665f3e12ad2defa7d3db09d9eb614e7 (patch) | |
| tree | 5e137107cfca62aab5ccb2f787716d56350fedc6 | |
| parent | d8b0b445f3cd0189de5a3cfa92ec68283e9f49d7 (diff) | |
| download | scummvm-rg350-e32010392665f3e12ad2defa7d3db09d9eb614e7.tar.gz scummvm-rg350-e32010392665f3e12ad2defa7d3db09d9eb614e7.tar.bz2 scummvm-rg350-e32010392665f3e12ad2defa7d3db09d9eb614e7.zip  | |
SCI: Refactored readPoint() to accept a segment reference to the polygon data, thus removing the check for invalid segment types. Also, added a sanity check to verify that the memory reference to polygon data is big enough to hold all the expected polygon vertices (thanks to waltervn)
svn-id: r52176
| -rw-r--r-- | engines/sci/engine/kpathing.cpp | 64 | 
1 files changed, 44 insertions, 20 deletions
diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index c3657b4b40..d01fbcb47f 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -261,13 +261,7 @@ struct PathfindingState {  	int findNearPoint(const Common::Point &p, Polygon *polygon, Common::Point *ret);  }; - -static Common::Point read_point(SegManager *segMan, reg_t list, int offset) { -	SegmentRef list_r = segMan->dereference(list); -	if (!list_r.isValid() || list_r.skipByte) { -		// If this happens, then the code below will probably go OOB and crash -		error("read_point(): Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(list)); -	} +static Common::Point readPoint(SegmentRef list_r, int offset) {  	Common::Point point;  	if (list_r.isRaw) { @@ -350,10 +344,16 @@ static void draw_polygon(EngineState *s, reg_t polygon, int width, int height) {  	Common::Point first, prev;  	int i; -	prev = first = read_point(segMan, points, 0); +	SegmentRef pointList = segMan->dereference(points); +	if (!pointList.isValid() || pointList.skipByte) { +		warning("draw_polygon: Polygon data pointer is invalid, skipping polygon"); +		return; +	} + +	prev = first = readPoint(pointList, 0);  	for (i = 1; i < size; i++) { -		Common::Point point = read_point(segMan, points, i); +		Common::Point point = readPoint(pointList, i);  		draw_line(s, prev, point, type, width, height);  		prev = point;  	} @@ -401,12 +401,18 @@ static void print_polygon(SegManager *segMan, reg_t polygon) {  	debugN(-1, "%i:", type); +	SegmentRef pointList = segMan->dereference(points); +	if (!pointList.isValid() || pointList.skipByte) { +		warning("print_polygon: Polygon data pointer is invalid, skipping polygon"); +		return; +	} +  	for (i = 0; i < size; i++) { -		point = read_point(segMan, points, i); +		point = readPoint(pointList, i);  		debugN(-1, " (%i, %i)", point.x, point.y);  	} -	point = read_point(segMan, points, 0); +	point = readPoint(pointList, 0);  	debug(" (%i, %i);", point.x, point.y);  } @@ -1094,26 +1100,37 @@ static Polygon *convert_polygon(EngineState *s, reg_t polygon) {  	Polygon *poly = new Polygon(readSelectorValue(segMan, polygon, SELECTOR(type))); +	SegmentRef pointList = segMan->dereference(points); +	// Check if the target polygon is still valid. It may have been released +	// in the meantime (e.g. in LSL6, room 700, when using the elevator). +	// Refer to bug #3034501. +	if (!pointList.isValid() || pointList.skipByte) { +		warning("convert_polygon: Polygon data pointer is invalid, skipping polygon"); +		return NULL; +	} + +	// Make sure that we have enough points +	if (pointList.maxSize < size * POLY_POINT_SIZE) { +		warning("convert_polygon: Not enough memory allocated for polygon points. " +				"Expected %d, got %d. Skipping polygon",  +				size * POLY_POINT_SIZE, pointList.maxSize); +		return NULL; +	} +  	int skip = 0;  	// WORKAROUND: broken polygon in lsl1sci, room 350, after opening elevator  	// Polygon has 17 points but size is set to 19  	if ((size == 19) && g_sci->getGameId() == GID_LSL1) {  		if ((s->currentRoomNumber() == 350) -		&& (read_point(segMan, points, 18) == Common::Point(108, 137))) { +		&& (readPoint(pointList, 18) == Common::Point(108, 137))) {  			debug(1, "Applying fix for broken polygon in lsl1sci, room 350");  			size = 17;  		}  	} -	// Check if the target polygon is still valid. It may have been released -	// in the meantime (e.g. in LSL6, room 700, when using the elevator). -	// Refer to bug #3034501. -	if (segMan->getSegmentType(points.segment) == SEG_TYPE_INVALID) -		return NULL; -  	for (i = skip; i < size; i++) { -		Vertex *vertex = new Vertex(read_point(segMan, points, i)); +		Vertex *vertex = new Vertex(readPoint(pointList, i));  		poly->vertices.insertHead(vertex);  	} @@ -1408,8 +1425,15 @@ static reg_t output_path(PathfindingState *p, EngineState *s) {  	if (DebugMan.isDebugChannelEnabled(kDebugLevelAvoidPath)) {  		debug("\nReturning path:"); + +		SegmentRef outputList = s->_segMan->dereference(output); +		if (!outputList.isValid() || outputList.skipByte) { +			warning("output_path: Polygon data pointer is invalid, skipping polygon"); +			return output; +		} +  		for (int i = 0; i < offset; i++) { -			Common::Point pt = read_point(s->_segMan, output, i); +			Common::Point pt = readPoint(outputList, i);  			debugN(-1, " (%i, %i)", pt.x, pt.y);  		}  		debug(";\n");  | 
