[Scummvm-cvs-logs] SF.net SVN: scummvm:[35047] scummvm/trunk/engines/parallaction

peres001 at users.sourceforge.net peres001 at users.sourceforge.net
Thu Nov 13 16:15:54 CET 2008


Revision: 35047
          http://scummvm.svn.sourceforge.net/scummvm/?rev=35047&view=rev
Author:   peres001
Date:     2008-11-13 15:15:54 +0000 (Thu, 13 Nov 2008)

Log Message:
-----------
Update to the low level parser:
* made it detect buffer overflows 
* removed unused code paths
* general simplification

Modified Paths:
--------------
    scummvm/trunk/engines/parallaction/parser.cpp
    scummvm/trunk/engines/parallaction/parser.h
    scummvm/trunk/engines/parallaction/parser_ns.cpp

Modified: scummvm/trunk/engines/parallaction/parser.cpp
===================================================================
--- scummvm/trunk/engines/parallaction/parser.cpp	2008-11-13 14:25:39 UTC (rev 35046)
+++ scummvm/trunk/engines/parallaction/parser.cpp	2008-11-13 15:15:54 UTC (rev 35047)
@@ -40,48 +40,87 @@
 		delete _input;
 }
 
-char *Script::readLine(char *buf, size_t bufSize) {
-
+char *Script::readLineIntern(char *buf, size_t bufSize) {
 	uint16 i;
 	for (i = 0; i < bufSize; i++) {
-
 		char c = _input->readSByte();
-
 		if (_input->eos())
 			break;
-
-		if (c == 0xA || c == 0xD)
+		if (c == '\n' || c == '\r')
 			break;
+		if (c == '\t')
+			c = ' ';
 
-		if (i < bufSize)
-			buf[i] = c;
+		buf[i] = c;
 	}
-
 	_line++;
-
-	if (i == 0 && _input->eos())
+	if (i == bufSize) {
+		warning("overflow in readLineIntern (line %i)", _line);
+	}
+	if (i == 0 && _input->eos()) {
 		return 0;
+	}
+	buf[i] = '\0';
+	return buf;
+}
 
-	buf[i] = 0xA;
-	buf[i+1] = '\0';
+bool isCommentLine(char *text) {
+	return text[0] == '#';
+}
 
-	return buf;
+bool isStartOfCommentBlock(char *text) {
+	return (text[0] == '[');
+}
 
+bool isEndOfCommentBlock(char *text) {
+	return (text[0] == ']');
 }
 
+char *Script::readLine(char *buf, size_t bufSize) {
+	bool inBlockComment = false;
+	bool ignoreLine = true;
 
+	char *line = 0;
+	do {
+		line = readLineIntern(buf, bufSize);
+		if (line == 0) {
+			return 0;
+		}
 
-void Script::clearTokens() {
+		if (line[0] == '\0')
+			continue;
 
-	for (uint16 i = 0; i < MAX_TOKENS; i++)
-		_tokens[i][0] = '\0';
+		ignoreLine = false;
 
-	_numTokens = 0;
+		line = Common::ltrim(line);
+		if (isCommentLine(line)) {
+			// ignore this line
+			ignoreLine = true;
+		} else
+		if (isStartOfCommentBlock(line)) {
+			// mark this and the following lines as comment
+			inBlockComment = true;
+		} else
+		if (isEndOfCommentBlock(line)) {
+			// comment is finished, so stop ignoring
+			inBlockComment = false;
+			// the current line must be skipped, though,
+			// as it contains the end-of-comment marker
+			ignoreLine = true;
+		}
 
-	return;
+	} while (inBlockComment || ignoreLine);
 
+	return line;
 }
 
+
+
+void Script::clearTokens() {
+	memset(_tokens, 0, sizeof(_tokens));
+	_numTokens = 0;
+}
+
 void Script::skip(const char* endToken) {
 
 	while (scumm_stricmp(_tokens[0], endToken)) {
@@ -111,21 +150,14 @@
 			if (*s == '\0') {
 				*tok = '\0';
 				return s;
-			}
-
+			} else
 			if (strchr(brk, *s)) {
 				*tok = '\0';
 				return ++s;
-			}
-
+			} else
 			if (*s == '"') {
-				if (ignoreQuotes) {
-					*tok++ = *s++;
-					count--;
-				} else {
-					state = QUOTED;
-					s++;
-				}
+				state = QUOTED;
+				s++;
 			} else {
 				*tok++ = *s++;
 				count--;
@@ -136,14 +168,14 @@
 			if (*s == '\0') {
 				*tok = '\0';
 				return s;
-			}
-			if (*s == '"' || *s == '\n' || *s == '\t') {
+			} else
+			if (*s == '"') {
 				*tok = '\0';
 				return ++s;
+			} else {
+				*tok++ = *s++;
+				count--;
 			}
-
-			*tok++ = *s++;
-			count--;
 			break;
 		}
 
@@ -158,74 +190,26 @@
 
 }
 
-uint16 Script::fillTokens(char* line) {
+uint16 Script::readLineToken(bool errorOnEOF) {
+	char buf[200];
+	char *line = readLine(buf, 200);
+	if (!line) {
+		if (errorOnEOF)
+			error("unexpected end of file while parsing");
+		else
+			return 0;
+	}
 
-	uint16 i = 0;
-	while (strlen(line) > 0 && i < MAX_TOKENS) {
-		line = parseNextToken(line, _tokens[i], MAX_TOKEN_LEN, " \t\n");
+	clearTokens();
+	while (strlen(line) > 0 && _numTokens < MAX_TOKENS) {
+		line = parseNextToken(line, _tokens[_numTokens], MAX_TOKEN_LEN, " ");
 		line = Common::ltrim(line);
-		i++;
+		_numTokens++;
 	}
-
-	_numTokens = i;
-
-	return i;
+	return _numTokens;
 }
 
-bool isCommentLine(char *text) {
-	return text[0] == '#';
-}
 
-bool isStartOfCommentBlock(char *text) {
-	return (text[0] == '[');
-}
-
-bool isEndOfCommentBlock(char *text) {
-	return (text[0] == ']');
-}
-
-uint16 Script::readLineToken(bool errorOnEOF) {
-
-	clearTokens();
-
-	bool inBlockComment = false;
-
-	char buf[200];
-	char *line = NULL;
-	char *start;
-	do {
-		line = readLine(buf, 200);
-
-		if (line == NULL) {
-			if (errorOnEOF)
-				error("unexpected end of file while parsing");
-			else
-				return 0;
-		}
-		start = Common::ltrim(line);
-
-		if (isCommentLine(start)) {
-			// ignore this line
-			start[0] = '\0';
-		} else
-		if (isStartOfCommentBlock(start)) {
-			// mark this and the following lines as comment
-			inBlockComment = true;
-		} else
-		if (isEndOfCommentBlock(start)) {
-			// comment is finished, so stop ignoring
-			inBlockComment = false;
-			// the current line must be skipped, though,
-			// as it contains the end-of-comment marker
-			start[0] = '\0';
-		}
-
-	} while (inBlockComment || strlen(start) == 0);
-
-	return fillTokens(start);
-}
-
-
 void Parser::reset() {
 	_currentOpcodes = 0;
 	_currentStatements = 0;
@@ -328,13 +312,11 @@
 	Common::String parseComment(Script &script) {
 		Common::String result;
 		char buf[401];
-
 		do {
-			script.readLine(buf, 400);
-			buf[strlen(buf)-1] = '\0';
-			if (!scumm_stricmp(buf, "endtext"))
+			char *line = script.readLine(buf, 400);
+			if (!scumm_stricmp(line, "endtext"))
 				break;
-			result += Common::String(buf) + "\n";
+			result += Common::String(line) + "\n";
 		} while (true);
 		result += "endtext\n";
 		return result;
@@ -408,8 +390,7 @@
 	_numZones = 0;
 	Common::String text;
 	do {
-		script.readLineToken(false);
-		if (_numTokens == 0)
+		if (script.readLineToken(false) == 0)
 			break;
 
 		StatementDef *def = findDef(_tokens[0]);

Modified: scummvm/trunk/engines/parallaction/parser.h
===================================================================
--- scummvm/trunk/engines/parallaction/parser.h	2008-11-13 14:25:39 UTC (rev 35046)
+++ scummvm/trunk/engines/parallaction/parser.h	2008-11-13 15:15:54 UTC (rev 35047)
@@ -44,8 +44,8 @@
 	uint	_line;				// for debug messages
 
 	void clearTokens();
-	uint16 fillTokens(char* line);
-	char   *parseNextToken(char *s, char *tok, uint16 count, const char *brk, bool ignoreQuotes = false);
+	char *parseNextToken(char *s, char *tok, uint16 count, const char *brk, bool ignoreQuotes = false);
+	char *readLineIntern(char *buf, size_t bufSize);
 
 public:
 	Script(Common::ReadStream *, bool _disposeSource = false);

Modified: scummvm/trunk/engines/parallaction/parser_ns.cpp
===================================================================
--- scummvm/trunk/engines/parallaction/parser_ns.cpp	2008-11-13 14:25:39 UTC (rev 35046)
+++ scummvm/trunk/engines/parallaction/parser_ns.cpp	2008-11-13 15:15:54 UTC (rev 35047)
@@ -943,21 +943,12 @@
 }
 
 char *LocationParser_ns::parseDialogueString() {
-
-	char vC8[200];
-	char *vD0 = NULL;
-	do {
-
-		vD0 = _script->readLine(vC8, 200);
-		if (vD0 == 0) return NULL;
-
-		vD0 = Common::ltrim(vD0);
-
-	} while (strlen(vD0) == 0);
-
-	vD0[strlen(vD0)-1] = '\0';	// deletes the trailing '0xA'
-								// this is critical for Gfx::displayWrappedString to work properly
-	return strdup(vD0);
+	char buf[200];
+	char *line = _script->readLine(buf, 200);
+	if (line == 0) {
+		return 0;
+	}
+	return strdup(line);
 }
 
 
@@ -1275,26 +1266,30 @@
 //	comments are displayed into rectangles on the screen
 //
 char *LocationParser_ns::parseComment() {
-
-	char			_tmp_comment[1000] = "\0";
-	char *v194;
-
+	const int tempSize = 1000;
+	char temp[tempSize] = "\0";
+	int len = 0;
+	char buf[400];
 	do {
-		char v190[400];
-		v194 = _script->readLine(v190, 400);
-
-		v194[strlen(v194)-1] = '\0';
-		if (!scumm_stricmp(v194, "endtext"))
+		char *line = _script->readLine(buf, 400);
+		if (!scumm_stricmp(line, "endtext"))
 			break;
 
-		strcat(_tmp_comment, v194);
-		strcat(_tmp_comment, " ");
-	} while (true);
+		strncat(temp, line, tempSize - len - 1);
+		strcat(temp, " ");
+		len = len + strlen(line) + 1;
+	} while (len < tempSize);
 
-	v194 = strdup(_tmp_comment);
-	_tmp_comment[0] = '\0';
+	if (len == 0) {
+		return 0;
+	}
 
-	return v194;
+	if (len == tempSize) {
+		warning("overflow in LocationParser_ns::parseComment (line %i)", _script->getLine());
+	}
+
+	temp[len-1] = '\0';	// removes the last space pasted in the string
+	return strdup(temp);
 }
 
 DECLARE_ZONE_PARSER(null) {


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