poppler/GfxState.cc | 191 ++++++++++++++++++++++++++++++++++++++++++++-------- poppler/GfxState.h | 16 +++- 2 files changed, 176 insertions(+), 31 deletions(-)
New commits: commit 2e62feafbc5095cedf948aefdf771d328d978de9 Author: Albert Astals Cid <aa...@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 <j...@infidigm.net> // Copyright (C) 2006 Carlos Garcia Campos <carlo...@gnome.org> // Copyright (C) 2009 Koji Otani <s...@bbr.jp> -// Copyright (C) 2009-2011, 2013, 2016-2020 Albert Astals Cid <aa...@kde.org> +// Copyright (C) 2009-2011, 2013, 2016-2021 Albert Astals Cid <aa...@kde.org> // Copyright (C) 2010 Christian Feuersänger <cfeuersaen...@googlemail.com> // Copyright (C) 2011 Andrea Canciani <ranm...@gmail.com> // Copyright (C) 2011-2014, 2016, 2020 Thomas Freitag <thomas.frei...@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; _______________________________________________ poppler mailing list poppler@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/poppler