poppler/Function.cc | 40 +++++++++++++++++++++------------------- poppler/Function.h | 2 +- 2 files changed, 22 insertions(+), 20 deletions(-)
New commits: commit 1be35ee8b2d6418dfafc6a8a9bbf6d70eafb2d2e Author: Albert Astals Cid <[email protected]> Date: Wed Apr 5 00:19:04 2023 +0200 Fix stack overflow in PostScriptFunction::parseCode By using a pointer instead of a variable things are on the heap. Fixes issue #1381 diff --git a/poppler/Function.cc b/poppler/Function.cc index 043ae8e9..fd5b38cc 100644 --- a/poppler/Function.cc +++ b/poppler/Function.cc @@ -13,7 +13,7 @@ // All changes made under the Poppler project to this file are licensed // under GPL version 2 or later // -// Copyright (C) 2006, 2008-2010, 2013-2015, 2017-2020, 2022 Albert Astals Cid <[email protected]> +// Copyright (C) 2006, 2008-2010, 2013-2015, 2017-2020, 2022, 2023 Albert Astals Cid <[email protected]> // Copyright (C) 2006 Jeff Muizelaar <[email protected]> // Copyright (C) 2010 Christian Feuersänger <[email protected]> // Copyright (C) 2011 Andrea Canciani <[email protected]> @@ -1131,7 +1131,7 @@ PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) //----- parse the function codeString = new GooString(); str->reset(); - if (getToken(str).cmp("{") != 0) { + if (getToken(str)->cmp("{") != 0) { error(errSyntaxError, -1, "Expected '{{' at start of PostScript function"); goto err1; } @@ -1231,8 +1231,10 @@ bool PostScriptFunction::parseCode(Stream *str, int *codePtr) int a, b, mid, cmp; while (true) { - GooString tok = getToken(str); - const char *p = tok.c_str(); + // This needs to be on the heap to help make parseCode + // able to call itself more times recursively + std::unique_ptr<GooString> tok = getToken(str); + const char *p = tok->c_str(); if (isdigit(*p) || *p == '.' || *p == '-') { isReal = false; for (; *p; ++p) { @@ -1244,13 +1246,13 @@ bool PostScriptFunction::parseCode(Stream *str, int *codePtr) resizeCode(*codePtr); if (isReal) { code[*codePtr].type = psReal; - code[*codePtr].real = gatof(tok.c_str()); + code[*codePtr].real = gatof(tok->c_str()); } else { code[*codePtr].type = psInt; - code[*codePtr].intg = atoi(tok.c_str()); + code[*codePtr].intg = atoi(tok->c_str()); } ++*codePtr; - } else if (!tok.cmp("{")) { + } else if (!tok->cmp("{")) { opPtr = *codePtr; *codePtr += 3; resizeCode(opPtr + 2); @@ -1258,7 +1260,7 @@ bool PostScriptFunction::parseCode(Stream *str, int *codePtr) return false; } tok = getToken(str); - if (!tok.cmp("{")) { + if (!tok->cmp("{")) { elsePtr = *codePtr; if (!parseCode(str, codePtr)) { return false; @@ -1267,7 +1269,7 @@ bool PostScriptFunction::parseCode(Stream *str, int *codePtr) } else { elsePtr = -1; } - if (!tok.cmp("if")) { + if (!tok->cmp("if")) { if (elsePtr >= 0) { error(errSyntaxError, -1, "Got 'if' operator with two blocks in PostScript function"); return false; @@ -1276,7 +1278,7 @@ bool PostScriptFunction::parseCode(Stream *str, int *codePtr) code[opPtr].op = psOpIf; code[opPtr + 2].type = psBlock; code[opPtr + 2].blk = *codePtr; - } else if (!tok.cmp("ifelse")) { + } else if (!tok->cmp("ifelse")) { if (elsePtr < 0) { error(errSyntaxError, -1, "Got 'ifelse' operator with one block in PostScript function"); return false; @@ -1291,7 +1293,7 @@ bool PostScriptFunction::parseCode(Stream *str, int *codePtr) error(errSyntaxError, -1, "Expected if/ifelse operator in PostScript function"); return false; } - } else if (!tok.cmp("}")) { + } else if (!tok->cmp("}")) { resizeCode(*codePtr); code[*codePtr].type = psOperator; code[*codePtr].op = psOpReturn; @@ -1304,7 +1306,7 @@ bool PostScriptFunction::parseCode(Stream *str, int *codePtr) // invariant: psOpNames[a] < tok < psOpNames[b] while (b - a > 1) { mid = (a + b) / 2; - cmp = tok.cmp(psOpNames[mid]); + cmp = tok->cmp(psOpNames[mid]); if (cmp > 0) { a = mid; } else if (cmp < 0) { @@ -1314,7 +1316,7 @@ bool PostScriptFunction::parseCode(Stream *str, int *codePtr) } } if (cmp != 0) { - error(errSyntaxError, -1, "Unknown operator '{0:t}' in PostScript function", &tok); + error(errSyntaxError, -1, "Unknown operator '{0:t}' in PostScript function", tok.get()); return false; } resizeCode(*codePtr); @@ -1326,12 +1328,12 @@ bool PostScriptFunction::parseCode(Stream *str, int *codePtr) return true; } -GooString PostScriptFunction::getToken(Stream *str) +std::unique_ptr<GooString> PostScriptFunction::getToken(Stream *str) { int c; bool comment; - GooString s; + std::string s; comment = false; while (true) { if ((c = str->getChar()) == EOF) { @@ -1349,10 +1351,10 @@ GooString PostScriptFunction::getToken(Stream *str) } } if (c == '{' || c == '}') { - s.append((char)c); + s.push_back((char)c); } else if (isdigit(c) || c == '.' || c == '-') { while (true) { - s.append((char)c); + s.push_back((char)c); c = str->lookChar(); if (c == EOF || !(isdigit(c) || c == '.' || c == '-')) { break; @@ -1362,7 +1364,7 @@ GooString PostScriptFunction::getToken(Stream *str) } } else { while (true) { - s.append((char)c); + s.push_back((char)c); c = str->lookChar(); if (c == EOF || !isalnum(c)) { break; @@ -1371,7 +1373,7 @@ GooString PostScriptFunction::getToken(Stream *str) codeString->append(c); } } - return s; + return std::make_unique<GooString>(s); } void PostScriptFunction::resizeCode(int newSize) diff --git a/poppler/Function.h b/poppler/Function.h index c1544f43..d2c003cc 100644 --- a/poppler/Function.h +++ b/poppler/Function.h @@ -236,7 +236,7 @@ public: private: explicit PostScriptFunction(const PostScriptFunction *func); bool parseCode(Stream *str, int *codePtr); - GooString getToken(Stream *str); + std::unique_ptr<GooString> getToken(Stream *str); void resizeCode(int newSize); void exec(PSStack *stack, int codePtr) const;
