mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
CwCheatScreen: fix crash on malformed cheat database lines
GetLineNoNewline() computed `line + strlen(line) - 1` to strip a trailing newline; fgets() doesn't stop at embedded NUL bytes, so a line starting with one made strlen() return 0, pointing `end` one byte before the buffer (a small OOB read, and conditionally an OOB write if that byte happened to equal '\n'). ImportCheats() also called substr(4) on a "_C" cheat-name line without checking its length first - a line that's just "_C"/"_C0"/"_C1" with no name is shorter than 4 characters, and substr() throws std::out_of_range, uncaught anywhere in this call chain, crashing the app. Both are reachable by importing a shared/downloaded cheat database file (the normal way users add cheats), which could be corrupted or maliciously crafted.
This commit is contained in:
1 parent
b68e0c0896
commit
7f7fe3c712
1 file changed
+9
-2
@@ -398,6 +398,10 @@ static char *GetLineNoNewline(char *temp, int sz, FILE *fp) {
|
||||
char *line = fgets(temp, sz, fp);
|
||||
if (!line)
|
||||
return nullptr;
|
||||
// fgets() doesn't stop at embedded NUL bytes, so a "line" starting with one would
|
||||
// otherwise make strlen() return 0 here, and `end` would point before the buffer.
|
||||
if (line[0] == '\0')
|
||||
return line;
|
||||
|
||||
// If the last character is \n, just make it the terminator.
|
||||
char *end = line + strlen(line) - 1;
|
||||
@@ -487,8 +491,11 @@ bool CwCheatScreen::ImportCheats(const Path &cheatFile, int *cheatsFound) {
|
||||
parseGameEntry = gameID == line;
|
||||
parseCheatEntry = false;
|
||||
} else if (parseGameEntry && line[0] == '_' && line[1] == 'C') {
|
||||
// Test if cheat already exists.
|
||||
parseCheatEntry = !HasCheatWithName(std::string(line).substr(4));
|
||||
// Test if cheat already exists. A malformed/truncated line (e.g. just
|
||||
// "_C" or "_C0" with no name) is shorter than 4 chars - substr(4) would
|
||||
// throw std::out_of_range, uncaught here, crashing the whole app.
|
||||
std::string lineStr(line);
|
||||
parseCheatEntry = lineStr.size() < 4 || !HasCheatWithName(lineStr.substr(4));
|
||||
}
|
||||
|
||||
if (!parseGameEntry) {
|
||||
|
||||
Reference in new issue
Block a user