summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/fpdfapi/page/cpdf_shadingpattern.cpp89
-rw-r--r--core/fpdfapi/page/cpdf_shadingpattern.h6
2 files changed, 95 insertions, 0 deletions
diff --git a/core/fpdfapi/page/cpdf_shadingpattern.cpp b/core/fpdfapi/page/cpdf_shadingpattern.cpp
index ef40f54182..c5972b7dac 100644
--- a/core/fpdfapi/page/cpdf_shadingpattern.cpp
+++ b/core/fpdfapi/page/cpdf_shadingpattern.cpp
@@ -100,9 +100,98 @@ bool CPDF_ShadingPattern::Load() {
m_ShadingType = ToShadingType(pShadingDict->GetIntegerFor("ShadingType"));
+ return Validate();
+}
+
+bool CPDF_ShadingPattern::Validate() const {
+ if (m_ShadingType == kInvalidShading)
+ return false;
+
// We expect to have a stream if our shading type is a mesh.
if (IsMeshShading() && !ToStream(m_pShadingObj.Get()))
return false;
+ // Validate color space
+ switch (m_ShadingType) {
+ case kFunctionBasedShading:
+ case kAxialShading:
+ case kRadialShading: {
+ if (m_pCS->GetFamily() == PDFCS_INDEXED)
+ return false;
+ break;
+ }
+ case kFreeFormGouraudTriangleMeshShading:
+ case kLatticeFormGouraudTriangleMeshShading:
+ case kCoonsPatchMeshShading:
+ case kTensorProductPatchMeshShading: {
+ if (!m_pFunctions.empty() && m_pCS->GetFamily() == PDFCS_INDEXED)
+ return false;
+ break;
+ }
+ default: {
+ NOTREACHED();
+ return false;
+ }
+ }
+
+ uint32_t nNumColorSpaceComponents = m_pCS->CountComponents();
+ switch (m_ShadingType) {
+ case kFunctionBasedShading: {
+ // Either one 2-to-N function or N 2-to-1 functions.
+ if (!ValidateFunctions(1, 2, nNumColorSpaceComponents) &&
+ !ValidateFunctions(nNumColorSpaceComponents, 2, 1)) {
+ return false;
+ }
+ break;
+ }
+ case kAxialShading:
+ case kRadialShading: {
+ // Either one 1-to-N function or N 1-to-1 functions.
+ if (!ValidateFunctions(1, 1, nNumColorSpaceComponents) &&
+ !ValidateFunctions(nNumColorSpaceComponents, 1, 1)) {
+ return false;
+ }
+ break;
+ }
+ case kFreeFormGouraudTriangleMeshShading:
+ case kLatticeFormGouraudTriangleMeshShading:
+ case kCoonsPatchMeshShading:
+ case kTensorProductPatchMeshShading: {
+ // Either no function, one 1-to-N function, or N 1-to-1 functions.
+ if (!m_pFunctions.empty() &&
+ !ValidateFunctions(1, 1, nNumColorSpaceComponents) &&
+ !ValidateFunctions(nNumColorSpaceComponents, 1, 1)) {
+ return false;
+ }
+ break;
+ }
+ default: {
+ NOTREACHED();
+ return false;
+ }
+ }
return true;
}
+
+bool CPDF_ShadingPattern::ValidateFunctions(
+ uint32_t nExpectedNumFunctions,
+ uint32_t nExpectedNumInputs,
+ uint32_t nExpectedNumOutputs) const {
+ if (m_pFunctions.size() != nExpectedNumFunctions)
+ return false;
+
+ pdfium::base::CheckedNumeric<uint32_t> nTotalOutputs = 0;
+ for (const auto& function : m_pFunctions) {
+ if (!function)
+ return false;
+
+ if (function->CountInputs() != nExpectedNumInputs ||
+ function->CountOutputs() != nExpectedNumOutputs) {
+ return false;
+ }
+
+ nTotalOutputs += function->CountOutputs();
+ }
+
+ return nTotalOutputs.IsValid();
+}
diff --git a/core/fpdfapi/page/cpdf_shadingpattern.h b/core/fpdfapi/page/cpdf_shadingpattern.h
index d0fafef0db..17b6e4bb8c 100644
--- a/core/fpdfapi/page/cpdf_shadingpattern.h
+++ b/core/fpdfapi/page/cpdf_shadingpattern.h
@@ -61,6 +61,12 @@ class CPDF_ShadingPattern : public CPDF_Pattern {
}
private:
+ // Constraints in PDF 1.7 spec, 4.6.3 Shading Patterns, pages 308-331.
+ bool Validate() const;
+ bool ValidateFunctions(uint32_t nExpectedNumFunctions,
+ uint32_t nExpectedNumInputs,
+ uint32_t nExpectedNumOutputs) const;
+
ShadingType m_ShadingType;
bool m_bShadingObj;
UnownedPtr<CPDF_Object> m_pShadingObj;