[poppler] poppler/Function.cc poppler/Function.h

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Apr 12 20:55:44 UTC 2023


 poppler/Function.cc |   40 +++++++++++++++++++++-------------------
 poppler/Function.h  |    2 +-
 2 files changed, 22 insertions(+), 20 deletions(-)

New commits:
commit 1be35ee8b2d6418dfafc6a8a9bbf6d70eafb2d2e
Author: Albert Astals Cid <aacid at kde.org>
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 <aacid at kde.org>
+// Copyright (C) 2006, 2008-2010, 2013-2015, 2017-2020, 2022, 2023 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2006 Jeff Muizelaar <jeff at infidigm.net>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 // Copyright (C) 2011 Andrea Canciani <ranma42 at gmail.com>
@@ -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;
 


More information about the poppler mailing list