[poppler] poppler/GfxState.cc poppler/GfxState.h

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Feb 12 23:31:25 UTC 2021


 poppler/GfxState.cc |  191 ++++++++++++++++++++++++++++++++++++++++++++--------
 poppler/GfxState.h  |   16 +++-
 2 files changed, 176 insertions(+), 31 deletions(-)

New commits:
commit 2e62feafbc5095cedf948aefdf771d328d978de9
Author: Albert Astals Cid <aacid at kde.org>
Date:   Fri Feb 12 14:16:09 2021 +0100

    Improve well formed check for shading functions

diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index a67c7ff7..05ce3a8e 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -3663,6 +3663,45 @@ GfxFunctionShading *GfxFunctionShading::parse(GfxResources *res, Dict *dict, Out
     return shading;
 }
 
+bool GfxFunctionShading::init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state)
+{
+    const bool parentInit = GfxShading::init(res, dict, out, state);
+    if (!parentInit) {
+        return false;
+    }
+
+    // funcs needs to be one of the two:
+    //  * One function 2-in -> nComps-out
+    //  * nComps functions 2-in -> 1-out
+    const int nComps = colorSpace->getNComps();
+    const int nFuncs = funcs.size();
+    if (nFuncs == 1) {
+        if (funcs[0]->getInputSize() != 2) {
+            error(errSyntaxWarning, -1, "GfxFunctionShading: function with input size != 2");
+            return false;
+        }
+        if (funcs[0]->getOutputSize() != nComps) {
+            error(errSyntaxWarning, -1, "GfxFunctionShading: function with wrong output size");
+            return false;
+        }
+    } else if (nFuncs == nComps) {
+        for (const std::unique_ptr<Function> &f : funcs) {
+            if (f->getInputSize() != 2) {
+                error(errSyntaxWarning, -1, "GfxFunctionShading: function with input size != 2");
+                return false;
+            }
+            if (f->getOutputSize() != 1) {
+                error(errSyntaxWarning, -1, "GfxFunctionShading: function with wrong output size");
+                return false;
+            }
+        }
+    } else {
+        return false;
+    }
+
+    return true;
+}
+
 GfxShading *GfxFunctionShading::copy() const
 {
     return new GfxFunctionShading(this);
@@ -3680,11 +3719,7 @@ void GfxFunctionShading::getColor(double x, double y, GfxColor *color) const
     in[0] = x;
     in[1] = y;
     for (int i = 0; i < getNFuncs(); ++i) {
-        if (likely(funcs[i]->getInputSize() <= 2)) {
-            funcs[i]->transform(in, &out[i]);
-        } else {
-            error(errSyntaxWarning, -1, "GfxFunctionShading::getColor: function with input size > 2");
-        }
+        funcs[i]->transform(in, &out[i]);
     }
     for (int i = 0; i < gfxColorMaxComps; ++i) {
         color->c[i] = dblToCol(out[i]);
@@ -3734,18 +3769,10 @@ GfxUnivariateShading::~GfxUnivariateShading()
 int GfxUnivariateShading::getColor(double t, GfxColor *color)
 {
     double out[gfxColorMaxComps];
-    int nComps;
-
-    if (likely(getNFuncs() >= 1)) {
-        // NB: there can be one function with n outputs or n functions with
-        // one output each (where n = number of color components)
-        nComps = getNFuncs() * funcs[0]->getOutputSize();
-    }
 
-    if (unlikely(getNFuncs() < 1 || nComps > gfxColorMaxComps)) {
-        clearGfxColor(color);
-        return gfxColorMaxComps;
-    }
+    // NB: there can be one function with n outputs or n functions with
+    // one output each (where n = number of color components)
+    const int nComps = getNFuncs() * funcs[0]->getOutputSize();
 
     if (cacheSize > 0) {
         double x, ix, *l, *u, *upper;
@@ -3773,10 +3800,6 @@ int GfxUnivariateShading::getColor(double t, GfxColor *color)
             out[i] = 0;
         }
         for (int i = 0; i < getNFuncs(); ++i) {
-            if (funcs[i]->getInputSize() != 1) {
-                error(errSyntaxWarning, -1, "Invalid shading function (input != 1)");
-                break;
-            }
             funcs[i]->transform(&t, &out[i]);
         }
     }
@@ -3870,6 +3893,45 @@ void GfxUnivariateShading::setupCache(const Matrix *ctm, double xMin, double yMi
     lastMatch = 1;
 }
 
+bool GfxUnivariateShading::init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state)
+{
+    const bool parentInit = GfxShading::init(res, dict, out, state);
+    if (!parentInit) {
+        return false;
+    }
+
+    // funcs needs to be one of the two:
+    //  * One function 1-in -> nComps-out
+    //  * nComps functions 1-in -> 1-out
+    const int nComps = colorSpace->getNComps();
+    const int nFuncs = funcs.size();
+    if (nFuncs == 1) {
+        if (funcs[0]->getInputSize() != 1) {
+            error(errSyntaxWarning, -1, "GfxUnivariateShading: function with input size != 2");
+            return false;
+        }
+        if (funcs[0]->getOutputSize() != nComps) {
+            error(errSyntaxWarning, -1, "GfxUnivariateShading: function with wrong output size");
+            return false;
+        }
+    } else if (nFuncs == nComps) {
+        for (const std::unique_ptr<Function> &f : funcs) {
+            if (f->getInputSize() != 1) {
+                error(errSyntaxWarning, -1, "GfxUnivariateShading: function with input size != 2");
+                return false;
+            }
+            if (f->getOutputSize() != 1) {
+                error(errSyntaxWarning, -1, "GfxUnivariateShading: function with wrong output size");
+                return false;
+            }
+        }
+    } else {
+        return false;
+    }
+
+    return true;
+}
+
 //------------------------------------------------------------------------
 // GfxAxialShading
 //------------------------------------------------------------------------
@@ -4762,6 +4824,46 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(GfxResources *res, i
     return shading;
 }
 
+bool GfxGouraudTriangleShading::init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state)
+{
+    const bool parentInit = GfxShading::init(res, dict, out, state);
+    if (!parentInit) {
+        return false;
+    }
+
+    // funcs needs to be one of the three:
+    //  * One function 1-in -> nComps-out
+    //  * nComps functions 1-in -> 1-out
+    //  * empty
+    const int nComps = colorSpace->getNComps();
+    const int nFuncs = funcs.size();
+    if (nFuncs == 1) {
+        if (funcs[0]->getInputSize() != 1) {
+            error(errSyntaxWarning, -1, "GfxGouraudTriangleShading: function with input size != 2");
+            return false;
+        }
+        if (funcs[0]->getOutputSize() != nComps) {
+            error(errSyntaxWarning, -1, "GfxGouraudTriangleShading: function with wrong output size");
+            return false;
+        }
+    } else if (nFuncs == nComps) {
+        for (const std::unique_ptr<Function> &f : funcs) {
+            if (f->getInputSize() != 1) {
+                error(errSyntaxWarning, -1, "GfxGouraudTriangleShading: function with input size != 2");
+                return false;
+            }
+            if (f->getOutputSize() != 1) {
+                error(errSyntaxWarning, -1, "GfxGouraudTriangleShading: function with wrong output size");
+                return false;
+            }
+        }
+    } else if (nFuncs != 0) {
+        return false;
+    }
+
+    return true;
+}
+
 GfxShading *GfxGouraudTriangleShading::copy() const
 {
     return new GfxGouraudTriangleShading(this);
@@ -4948,15 +5050,6 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(GfxResources *res, int typeA, Di
         }
     }
 
-    for (unsigned int k = 0; k < funcsA.size(); ++k) {
-        if (funcsA[k]->getInputSize() > 1) {
-            return nullptr;
-        }
-        if (funcsA[k]->getOutputSize() > static_cast<int>(gfxColorMaxComps - k)) {
-            return nullptr;
-        }
-    }
-
     nPatchesA = 0;
     patchesA = nullptr;
     patchesSize = 0;
@@ -5378,6 +5471,46 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(GfxResources *res, int typeA, Di
     return shading;
 }
 
+bool GfxPatchMeshShading::init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state)
+{
+    const bool parentInit = GfxShading::init(res, dict, out, state);
+    if (!parentInit) {
+        return false;
+    }
+
+    // funcs needs to be one of the three:
+    //  * One function 1-in -> nComps-out
+    //  * nComps functions 1-in -> 1-out
+    //  * empty
+    const int nComps = colorSpace->getNComps();
+    const int nFuncs = funcs.size();
+    if (nFuncs == 1) {
+        if (funcs[0]->getInputSize() != 1) {
+            error(errSyntaxWarning, -1, "GfxPatchMeshShading: function with input size != 2");
+            return false;
+        }
+        if (funcs[0]->getOutputSize() != nComps) {
+            error(errSyntaxWarning, -1, "GfxPatchMeshShading: function with wrong output size");
+            return false;
+        }
+    } else if (nFuncs == nComps) {
+        for (const std::unique_ptr<Function> &f : funcs) {
+            if (f->getInputSize() != 1) {
+                error(errSyntaxWarning, -1, "GfxPatchMeshShading: function with input size != 2");
+                return false;
+            }
+            if (f->getOutputSize() != 1) {
+                error(errSyntaxWarning, -1, "GfxPatchMeshShading: function with wrong output size");
+                return false;
+            }
+        }
+    } else if (nFuncs != 0) {
+        return false;
+    }
+
+    return true;
+}
+
 void GfxPatchMeshShading::getParameterizedColor(double t, GfxColor *color) const
 {
     double out[gfxColorMaxComps] = {};
diff --git a/poppler/GfxState.h b/poppler/GfxState.h
index 10953b0b..aec5c6c8 100644
--- a/poppler/GfxState.h
+++ b/poppler/GfxState.h
@@ -17,7 +17,7 @@
 // Copyright (C) 2006, 2007 Jeff Muizelaar <jeff at infidigm.net>
 // Copyright (C) 2006 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2009 Koji Otani <sho at bbr.jp>
-// Copyright (C) 2009-2011, 2013, 2016-2020 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2009-2011, 2013, 2016-2021 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 // Copyright (C) 2011 Andrea Canciani <ranma42 at gmail.com>
 // Copyright (C) 2011-2014, 2016, 2020 Thomas Freitag <Thomas.Freitag at alfa.de>
@@ -878,7 +878,7 @@ public:
     bool getHasBBox() const { return hasBBox; }
 
 protected:
-    bool init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state);
+    virtual bool init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state);
 
     // 1: Function-based shading
     // 2: Axial shading
@@ -922,6 +922,9 @@ public:
 
     virtual double getDistance(double sMin, double sMax) const = 0;
 
+protected:
+    bool init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state) override;
+
 private:
     double t0, t1;
     std::vector<std::unique_ptr<Function>> funcs;
@@ -960,6 +963,9 @@ public:
     const Function *getFunc(int i) const { return funcs[i].get(); }
     void getColor(double x, double y, GfxColor *color) const;
 
+protected:
+    bool init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state) override;
+
 private:
     double x0, y0, x1, y1;
     double matrix[6];
@@ -1087,6 +1093,9 @@ public:
 
     void getParameterizedColor(double t, GfxColor *color) const;
 
+protected:
+    bool init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state) override;
+
 private:
     GfxGouraudVertex *vertices;
     int nVertices;
@@ -1165,6 +1174,9 @@ public:
 
     void getParameterizedColor(double t, GfxColor *color) const;
 
+protected:
+    bool init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state) override;
+
 private:
     GfxPatch *patches;
     int nPatches;


More information about the poppler mailing list