summaryrefslogtreecommitdiff
path: root/core/fpdfapi/fpdf_page
diff options
context:
space:
mode:
authorthestig <thestig@chromium.org>2016-05-19 15:47:01 -0700
committerCommit bot <commit-bot@chromium.org>2016-05-19 15:47:01 -0700
commit9b1a0ee2a8f24411609a2f7554119597950dbd04 (patch)
tree3a2254a800f581bff51442184cdb9056ee8e2542 /core/fpdfapi/fpdf_page
parentdb9e49889d4129bbe96abdbce7dc3662e97a9df8 (diff)
downloadpdfium-9b1a0ee2a8f24411609a2f7554119597950dbd04.tar.xz
Fix Undefined-shift in CPDF_SampledFunc::v_Init().
Also fix a divide by zero in CPDF_SampledFunc. Do some cleanups too. BUG=596530,613032 Review-Url: https://codereview.chromium.org/1990843004
Diffstat (limited to 'core/fpdfapi/fpdf_page')
-rw-r--r--core/fpdfapi/fpdf_page/fpdf_page_func.cpp180
-rw-r--r--core/fpdfapi/fpdf_page/pageint.h27
2 files changed, 114 insertions, 93 deletions
diff --git a/core/fpdfapi/fpdf_page/fpdf_page_func.cpp b/core/fpdfapi/fpdf_page/fpdf_page_func.cpp
index 31faf6a2d7..1acf62b596 100644
--- a/core/fpdfapi/fpdf_page/fpdf_page_func.cpp
+++ b/core/fpdfapi/fpdf_page/fpdf_page_func.cpp
@@ -476,25 +476,48 @@ FX_BOOL CPDF_PSEngine::DoOperator(PDF_PSOP op) {
}
return TRUE;
}
-static FX_FLOAT PDF_Interpolate(FX_FLOAT x,
- FX_FLOAT xmin,
- FX_FLOAT xmax,
- FX_FLOAT ymin,
- FX_FLOAT ymax) {
- return ((x - xmin) * (ymax - ymin) / (xmax - xmin)) + ymin;
+
+// See PDF Reference 1.7, page 170, table 3.36.
+bool IsValidBitsPerSample(uint32_t x) {
+ switch (x) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 12:
+ case 16:
+ case 24:
+ case 32:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// See PDF Reference 1.7, page 170.
+FX_FLOAT PDF_Interpolate(FX_FLOAT x,
+ FX_FLOAT xmin,
+ FX_FLOAT xmax,
+ FX_FLOAT ymin,
+ FX_FLOAT ymax) {
+ FX_FLOAT divisor = xmax - xmin;
+ return ymin + (divisor ? (x - xmin) * (ymax - ymin) / divisor : 0);
}
-static uint32_t _GetBits32(const uint8_t* pData, int bitpos, int nbits) {
+
+uint32_t GetBits32(const uint8_t* pData, int bitpos, int nbits) {
int result = 0;
- for (int i = 0; i < nbits; i++)
- if (pData[(bitpos + i) / 8] & (1 << (7 - (bitpos + i) % 8))) {
+ for (int i = 0; i < nbits; i++) {
+ if (pData[(bitpos + i) / 8] & (1 << (7 - (bitpos + i) % 8)))
result |= 1 << (nbits - i - 1);
- }
+ }
return result;
}
class CPDF_PSFunc : public CPDF_Function {
public:
- CPDF_PSFunc() : CPDF_Function(Type::kType4PostScript) {}
+ CPDF_PSFunc() {}
+ ~CPDF_PSFunc() override {}
+
// CPDF_Function
FX_BOOL v_Init(CPDF_Object* pObj) override;
FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override;
@@ -525,17 +548,9 @@ FX_BOOL CPDF_PSFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const {
} // namespace
-CPDF_SampledFunc::CPDF_SampledFunc() : CPDF_Function(Type::kType0Sampled) {
- m_pSampleStream = NULL;
- m_pEncodeInfo = NULL;
- m_pDecodeInfo = NULL;
-}
+CPDF_SampledFunc::CPDF_SampledFunc() {}
-CPDF_SampledFunc::~CPDF_SampledFunc() {
- delete m_pSampleStream;
- FX_Free(m_pEncodeInfo);
- FX_Free(m_pDecodeInfo);
-}
+CPDF_SampledFunc::~CPDF_SampledFunc() {}
FX_BOOL CPDF_SampledFunc::v_Init(CPDF_Object* pObj) {
CPDF_Stream* pStream = pObj->AsStream();
@@ -547,14 +562,14 @@ FX_BOOL CPDF_SampledFunc::v_Init(CPDF_Object* pObj) {
CPDF_Array* pEncode = pDict->GetArrayBy("Encode");
CPDF_Array* pDecode = pDict->GetArrayBy("Decode");
m_nBitsPerSample = pDict->GetIntegerBy("BitsPerSample");
- if (m_nBitsPerSample > 32) {
+ if (!IsValidBitsPerSample(m_nBitsPerSample))
return FALSE;
- }
+
m_SampleMax = 0xffffffff >> (32 - m_nBitsPerSample);
- m_pSampleStream = new CPDF_StreamAcc;
+ m_pSampleStream.reset(new CPDF_StreamAcc);
m_pSampleStream->LoadAllData(pStream, FALSE);
- m_pEncodeInfo = FX_Alloc(SampleEncodeInfo, m_nInputs);
FX_SAFE_UINT32 nTotalSampleBits = 1;
+ m_pEncodeInfo.resize(m_nInputs);
for (uint32_t i = 0; i < m_nInputs; i++) {
m_pEncodeInfo[i].sizes = pSize ? pSize->GetIntegerAt(i) : 0;
if (!pSize && i == 0)
@@ -565,10 +580,9 @@ FX_BOOL CPDF_SampledFunc::v_Init(CPDF_Object* pObj) {
m_pEncodeInfo[i].encode_max = pEncode->GetFloatAt(i * 2 + 1);
} else {
m_pEncodeInfo[i].encode_min = 0;
- if (m_pEncodeInfo[i].sizes == 1)
- m_pEncodeInfo[i].encode_max = 1;
- else
- m_pEncodeInfo[i].encode_max = (FX_FLOAT)m_pEncodeInfo[i].sizes - 1;
+ m_pEncodeInfo[i].encode_max = m_pEncodeInfo[i].sizes == 1
+ ? 1
+ : (FX_FLOAT)m_pEncodeInfo[i].sizes - 1;
}
}
nTotalSampleBits *= m_nBitsPerSample;
@@ -580,7 +594,7 @@ FX_BOOL CPDF_SampledFunc::v_Init(CPDF_Object* pObj) {
nTotalSampleBytes.ValueOrDie() > m_pSampleStream->GetSize()) {
return FALSE;
}
- m_pDecodeInfo = FX_Alloc(SampleDecodeInfo, m_nOutputs);
+ m_pDecodeInfo.resize(m_nOutputs);
for (uint32_t i = 0; i < m_nOutputs; i++) {
if (pDecode) {
m_pDecodeInfo[i].decode_min = pDecode->GetFloatAt(2 * i);
@@ -614,27 +628,27 @@ FX_BOOL CPDF_SampledFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const {
}
FX_SAFE_INT32 bits_to_output = m_nOutputs;
bits_to_output *= m_nBitsPerSample;
- if (!bits_to_output.IsValid()) {
+ if (!bits_to_output.IsValid())
return FALSE;
- }
+
FX_SAFE_INT32 bitpos = pos;
bitpos *= bits_to_output.ValueOrDie();
- if (!bitpos.IsValid()) {
+ if (!bitpos.IsValid())
return FALSE;
- }
+
FX_SAFE_INT32 range_check = bitpos;
range_check += bits_to_output.ValueOrDie();
- if (!range_check.IsValid()) {
+ if (!range_check.IsValid())
return FALSE;
- }
+
const uint8_t* pSampleData = m_pSampleStream->GetData();
- if (!pSampleData) {
+ if (!pSampleData)
return FALSE;
- }
+
for (uint32_t j = 0; j < m_nOutputs; j++) {
uint32_t sample =
- _GetBits32(pSampleData, bitpos.ValueOrDie() + j * m_nBitsPerSample,
- m_nBitsPerSample);
+ GetBits32(pSampleData, bitpos.ValueOrDie() + j * m_nBitsPerSample,
+ m_nBitsPerSample);
FX_FLOAT encoded = (FX_FLOAT)sample;
for (uint32_t i = 0; i < m_nInputs; i++) {
if (index[i] == m_pEncodeInfo[i].sizes - 1) {
@@ -649,7 +663,7 @@ FX_BOOL CPDF_SampledFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const {
if (!bitpos2.IsValid())
return FALSE;
uint32_t sample1 =
- _GetBits32(pSampleData, bitpos2.ValueOrDie(), m_nBitsPerSample);
+ GetBits32(pSampleData, bitpos2.ValueOrDie(), m_nBitsPerSample);
encoded += (encoded_input[i] - index[i]) *
((FX_FLOAT)sample1 - (FX_FLOAT)sample);
}
@@ -661,8 +675,7 @@ FX_BOOL CPDF_SampledFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const {
return TRUE;
}
-CPDF_ExpIntFunc::CPDF_ExpIntFunc()
- : CPDF_Function(Type::kType2ExpotentialInterpolation) {
+CPDF_ExpIntFunc::CPDF_ExpIntFunc() {
m_pBeginValues = NULL;
m_pEndValues = NULL;
}
@@ -709,18 +722,16 @@ FX_BOOL CPDF_ExpIntFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const {
return TRUE;
}
-CPDF_StitchFunc::CPDF_StitchFunc() : CPDF_Function(Type::kType3Stitching) {
+CPDF_StitchFunc::CPDF_StitchFunc() {
m_pBounds = NULL;
m_pEncode = NULL;
}
CPDF_StitchFunc::~CPDF_StitchFunc() {
- for (auto& sub : m_pSubFunctions) {
- delete sub;
- }
FX_Free(m_pBounds);
FX_Free(m_pEncode);
}
+
FX_BOOL CPDF_StitchFunc::v_Init(CPDF_Object* pObj) {
CPDF_Dictionary* pDict = pObj->GetDict();
if (!pDict) {
@@ -755,7 +766,7 @@ FX_BOOL CPDF_StitchFunc::v_Init(CPDF_Object* pObj) {
m_nOutputs = pFunc->CountOutputs();
}
- m_pSubFunctions.push_back(pFunc.release());
+ m_pSubFunctions.push_back(std::move(pFunc));
}
m_pBounds = FX_Alloc(FX_FLOAT, nSubs + 1);
m_pBounds[0] = m_pDomains[0];
@@ -774,6 +785,7 @@ FX_BOOL CPDF_StitchFunc::v_Init(CPDF_Object* pObj) {
m_pEncode[i] = pArray->GetFloatAt(i);
return TRUE;
}
+
FX_BOOL CPDF_StitchFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* outputs) const {
FX_FLOAT input = inputs[0];
size_t i;
@@ -781,9 +793,6 @@ FX_BOOL CPDF_StitchFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* outputs) const {
if (input < m_pBounds[i + 1])
break;
}
- if (!m_pSubFunctions[i]) {
- return FALSE;
- }
input = PDF_Interpolate(input, m_pBounds[i], m_pBounds[i + 1],
m_pEncode[i * 2], m_pEncode[i * 2 + 1]);
int nresults;
@@ -791,38 +800,47 @@ FX_BOOL CPDF_StitchFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* outputs) const {
return TRUE;
}
+// static
CPDF_Function* CPDF_Function::Load(CPDF_Object* pFuncObj) {
- if (!pFuncObj) {
- return NULL;
- }
- int type;
- if (CPDF_Stream* pStream = pFuncObj->AsStream()) {
- type = pStream->GetDict()->GetIntegerBy("FunctionType");
- } else if (CPDF_Dictionary* pDict = pFuncObj->AsDictionary()) {
- type = pDict->GetIntegerBy("FunctionType");
- } else {
- return NULL;
- }
- CPDF_Function* pFunc = NULL;
- if (type == 0) {
- pFunc = new CPDF_SampledFunc();
- } else if (type == 2) {
- pFunc = new CPDF_ExpIntFunc();
- } else if (type == 3) {
- pFunc = new CPDF_StitchFunc();
- } else if (type == 4) {
- pFunc = new CPDF_PSFunc();
- } else {
- return NULL;
- }
- if (!pFunc->Init(pFuncObj)) {
- delete pFunc;
- return NULL;
- }
- return pFunc;
+ if (!pFuncObj)
+ return nullptr;
+
+ int iType = -1;
+ if (CPDF_Stream* pStream = pFuncObj->AsStream())
+ iType = pStream->GetDict()->GetIntegerBy("FunctionType");
+ else if (CPDF_Dictionary* pDict = pFuncObj->AsDictionary())
+ iType = pDict->GetIntegerBy("FunctionType");
+
+ Type type = IntegerToFunctionType(iType);
+ std::unique_ptr<CPDF_Function> pFunc;
+ if (type == Type::kType0Sampled)
+ pFunc.reset(new CPDF_SampledFunc());
+ else if (type == Type::kType2ExpotentialInterpolation)
+ pFunc.reset(new CPDF_ExpIntFunc());
+ else if (type == Type::kType3Stitching)
+ pFunc.reset(new CPDF_StitchFunc());
+ else if (type == Type::kType4PostScript)
+ pFunc.reset(new CPDF_PSFunc());
+
+ if (!pFunc || !pFunc->Init(pFuncObj))
+ return nullptr;
+ return pFunc.release();
+}
+
+// static
+CPDF_Function::Type CPDF_Function::IntegerToFunctionType(int iType) {
+ switch (iType) {
+ case 0:
+ case 2:
+ case 3:
+ case 4:
+ return static_cast<Type>(iType);
+ default:
+ return Type::kTypeInvalid;
+ }
}
-CPDF_Function::CPDF_Function(Type type) : m_Type(type) {
+CPDF_Function::CPDF_Function() {
m_pDomains = NULL;
m_pRanges = NULL;
}
@@ -831,6 +849,7 @@ CPDF_Function::~CPDF_Function() {
FX_Free(m_pDomains);
FX_Free(m_pRanges);
}
+
FX_BOOL CPDF_Function::Init(CPDF_Object* pObj) {
CPDF_Stream* pStream = pObj->AsStream();
CPDF_Dictionary* pDict = pStream ? pStream->GetDict() : pObj->AsDictionary();
@@ -867,6 +886,7 @@ FX_BOOL CPDF_Function::Init(CPDF_Object* pObj) {
}
return TRUE;
}
+
FX_BOOL CPDF_Function::Call(FX_FLOAT* inputs,
uint32_t ninputs,
FX_FLOAT* results,
diff --git a/core/fpdfapi/fpdf_page/pageint.h b/core/fpdfapi/fpdf_page/pageint.h
index d1364d0dd1..8d507a181d 100644
--- a/core/fpdfapi/fpdf_page/pageint.h
+++ b/core/fpdfapi/fpdf_page/pageint.h
@@ -367,13 +367,16 @@ class CPDF_DocPageData {
class CPDF_Function {
public:
enum class Type {
- kType0Sampled,
- kType2ExpotentialInterpolation,
- kType3Stitching,
- kType4PostScript,
+ kTypeInvalid = -1,
+ kType0Sampled = 0,
+ kType2ExpotentialInterpolation = 2,
+ kType3Stitching = 3,
+ kType4PostScript = 4,
};
static CPDF_Function* Load(CPDF_Object* pFuncObj);
+ static Type IntegerToFunctionType(int iType);
+
virtual ~CPDF_Function();
FX_BOOL Call(FX_FLOAT* inputs,
uint32_t ninputs,
@@ -381,12 +384,10 @@ class CPDF_Function {
int& nresults) const;
uint32_t CountInputs() const { return m_nInputs; }
uint32_t CountOutputs() const { return m_nOutputs; }
- FX_FLOAT GetDomain(int i) const { return m_pDomains[i]; }
- FX_FLOAT GetRange(int i) const { return m_pRanges[i]; }
- Type GetType() const { return m_Type; }
protected:
- CPDF_Function(Type type);
+ CPDF_Function();
+
FX_BOOL Init(CPDF_Object* pObj);
virtual FX_BOOL v_Init(CPDF_Object* pObj) = 0;
virtual FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const = 0;
@@ -395,7 +396,6 @@ class CPDF_Function {
uint32_t m_nOutputs;
FX_FLOAT* m_pDomains;
FX_FLOAT* m_pRanges;
- Type m_Type;
};
class CPDF_ExpIntFunc : public CPDF_Function {
@@ -433,11 +433,12 @@ class CPDF_SampledFunc : public CPDF_Function {
FX_BOOL v_Init(CPDF_Object* pObj) override;
FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override;
- SampleEncodeInfo* m_pEncodeInfo;
- SampleDecodeInfo* m_pDecodeInfo;
+ private:
+ std::vector<SampleEncodeInfo> m_pEncodeInfo;
+ std::vector<SampleDecodeInfo> m_pDecodeInfo;
uint32_t m_nBitsPerSample;
uint32_t m_SampleMax;
- CPDF_StreamAcc* m_pSampleStream;
+ std::unique_ptr<CPDF_StreamAcc> m_pSampleStream;
};
class CPDF_StitchFunc : public CPDF_Function {
@@ -449,7 +450,7 @@ class CPDF_StitchFunc : public CPDF_Function {
FX_BOOL v_Init(CPDF_Object* pObj) override;
FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override;
- std::vector<CPDF_Function*> m_pSubFunctions;
+ std::vector<std::unique_ptr<CPDF_Function>> m_pSubFunctions;
FX_FLOAT* m_pBounds;
FX_FLOAT* m_pEncode;