Guard usages of tellp(). It may return -1 in error cases.
Change-Id: I064ddcad8671b9ade2c02142a6c2c2983846e3a9
Reviewed-on: https://pdfium-review.googlesource.com/24650
Commit-Queue: Henrique Nakashima <hnakashima@chromium.org>
Reviewed-by: dsinclair <dsinclair@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_streamparser.cpp b/core/fpdfapi/page/cpdf_streamparser.cpp
index 2c7e025..71c8c8d 100644
--- a/core/fpdfapi/page/cpdf_streamparser.cpp
+++ b/core/fpdfapi/page/cpdf_streamparser.cpp
@@ -478,6 +478,9 @@
case 0:
if (ch == ')') {
if (parlevel == 0) {
+ if (buf.tellp() <= 0)
+ return ByteString();
+
return ByteString(
buf.str().c_str(),
std::min(static_cast<size_t>(buf.tellp()), kMaxStringLength));
@@ -557,6 +560,9 @@
if (PositionIsInBounds())
++m_Pos;
+ if (buf.tellp() <= 0)
+ return ByteString();
+
return ByteString(
buf.str().c_str(),
std::min(static_cast<size_t>(buf.tellp()), kMaxStringLength));
@@ -590,6 +596,9 @@
if (!bFirst)
buf << static_cast<char>(code);
+ if (buf.tellp() <= 0)
+ return ByteString();
+
return ByteString(
buf.str().c_str(),
std::min(static_cast<size_t>(buf.tellp()), kMaxStringLength));
diff --git a/core/fpdfapi/parser/cpdf_stream.cpp b/core/fpdfapi/parser/cpdf_stream.cpp
index 074e747..5ff7484 100644
--- a/core/fpdfapi/parser/cpdf_stream.cpp
+++ b/core/fpdfapi/parser/cpdf_stream.cpp
@@ -100,6 +100,11 @@
}
void CPDF_Stream::SetDataAndRemoveFilter(std::ostringstream* stream) {
+ if (stream->tellp() <= 0) {
+ SetDataAndRemoveFilter(nullptr, 0);
+ return;
+ }
+
SetDataAndRemoveFilter(
reinterpret_cast<const uint8_t*>(stream->str().c_str()), stream->tellp());
}
@@ -125,6 +130,11 @@
}
void CPDF_Stream::SetData(std::ostringstream* stream) {
+ if (stream->tellp() <= 0) {
+ SetData(nullptr, 0);
+ return;
+ }
+
SetData(reinterpret_cast<const uint8_t*>(stream->str().c_str()),
stream->tellp());
}
diff --git a/core/fxge/win32/cfx_psrenderer.cpp b/core/fxge/win32/cfx_psrenderer.cpp
index 417a1d7..b79de57 100644
--- a/core/fxge/win32/cfx_psrenderer.cpp
+++ b/core/fxge/win32/cfx_psrenderer.cpp
@@ -206,7 +206,7 @@
}
}
}
- m_pStream->WriteBlock(buf.str().c_str(), buf.tellp());
+ WriteToStream(&buf);
}
void CFX_PSRenderer::SetClip_PathFill(const CFX_PathData* pPathData,
@@ -239,7 +239,7 @@
buf << "mx Cm [" << pObject2Device->a << " " << pObject2Device->b << " "
<< pObject2Device->c << " " << pObject2Device->d << " "
<< pObject2Device->e << " " << pObject2Device->f << "]cm ";
- m_pStream->WriteBlock(buf.str().c_str(), buf.tellp());
+ WriteToStream(&buf);
OutputPath(pPathData, nullptr);
CFX_FloatRect rect = pPathData->GetBoundingBox(pGraphState->m_LineWidth,
@@ -272,7 +272,7 @@
buf << "mx Cm [" << pObject2Device->a << " " << pObject2Device->b << " "
<< pObject2Device->c << " " << pObject2Device->d << " "
<< pObject2Device->e << " " << pObject2Device->f << "]cm ";
- m_pStream->WriteBlock(buf.str().c_str(), buf.tellp());
+ WriteToStream(&buf);
}
}
@@ -333,8 +333,7 @@
}
m_CurGraphState.Copy(*pGraphState);
m_bGraphStateSet = true;
- if (buf.tellp())
- m_pStream->WriteBlock(buf.str().c_str(), buf.tellp());
+ WriteToStream(&buf);
}
bool CFX_PSRenderer::SetDIBits(const RetainPtr<CFX_DIBSource>& pSource,
@@ -418,7 +417,7 @@
else
buf << "false 1 colorimage\n";
- m_pStream->WriteBlock(buf.str().c_str(), buf.tellp());
+ WriteToStream(&buf);
WritePSBinary(output_buf.get(), output_size);
output_buf.release();
} else {
@@ -496,7 +495,7 @@
buf << "false " << bpp;
buf << " colorimage\n";
- m_pStream->WriteBlock(buf.str().c_str(), buf.tellp());
+ WriteToStream(&buf);
WritePSBinary(output_buf, output_size);
FX_Free(output_buf);
@@ -522,7 +521,7 @@
m_bColorSet = true;
m_LastColor = color;
}
- m_pStream->WriteBlock(buf.str().c_str(), buf.tellp());
+ WriteToStream(&buf);
}
}
@@ -569,7 +568,7 @@
"currentdict end\n";
buf << "/X" << static_cast<uint32_t>(m_PSFontList.size() - 1)
<< " exch definefont pop\n";
- m_pStream->WriteBlock(buf.str().c_str(), buf.tellp());
+ WriteToStream(&buf);
buf.str("");
}
@@ -631,7 +630,7 @@
buf << "f}bind def end\n";
buf << "/X" << *ps_fontnum << " Ff/Encoding get " << glyphindex << "/"
<< glyphindex << " put\n";
- m_pStream->WriteBlock(buf.str().c_str(), buf.tellp());
+ WriteToStream(&buf);
}
bool CFX_PSRenderer::DrawText(int nChars,
@@ -676,7 +675,7 @@
buf << hex.AsStringView() << "Tj\n";
}
buf << "Q\n";
- m_pStream->WriteBlock(buf.str().c_str(), buf.tellp());
+ WriteToStream(&buf);
pCache->ReleaseCachedFace(pFont);
return true;
}
@@ -693,3 +692,8 @@
m_pStream->WriteBlock(data, len);
}
}
+
+void CFX_PSRenderer::WriteToStream(std::ostringstream* stringStream) {
+ if (stringStream->tellp() > 0)
+ m_pStream->WriteBlock(stringStream->str().c_str(), stringStream->tellp());
+}
diff --git a/core/fxge/win32/cfx_psrenderer.h b/core/fxge/win32/cfx_psrenderer.h
index 33829ea..4116dd4 100644
--- a/core/fxge/win32/cfx_psrenderer.h
+++ b/core/fxge/win32/cfx_psrenderer.h
@@ -85,6 +85,7 @@
int* ps_fontnum,
int* ps_glyphindex);
void WritePSBinary(const uint8_t* data, int len);
+ void WriteToStream(std::ostringstream* stringStream);
RetainPtr<IFX_WriteStream> m_pStream;
int m_PSLevel;
diff --git a/core/fxge/win32/fx_win32_gdipext.cpp b/core/fxge/win32/fx_win32_gdipext.cpp
index 64c8ea7..a83a449 100644
--- a/core/fxge/win32/fx_win32_gdipext.cpp
+++ b/core/fxge/win32/fx_win32_gdipext.cpp
@@ -952,6 +952,8 @@
start = m_ReadPos;
break;
case STREAM_SEEK_END:
+ if (m_InterStream.tellp() < 0)
+ return STG_E_SEEKERROR;
start = m_InterStream.tellp();
break;
default:
@@ -973,6 +975,10 @@
return STG_E_INVALIDFUNCTION;
ZeroMemory(pStatstg, sizeof(STATSTG));
+
+ if (m_InterStream.tellp() < 0)
+ return STG_E_SEEKERROR;
+
pStatstg->cbSize.QuadPart = m_InterStream.tellp();
return S_OK;
}
diff --git a/fpdfsdk/cpdfsdk_interform.cpp b/fpdfsdk/cpdfsdk_interform.cpp
index 03a782b..3b76dca 100644
--- a/fpdfsdk/cpdfsdk_interform.cpp
+++ b/fpdfsdk/cpdfsdk_interform.cpp
@@ -530,7 +530,7 @@
}
nBufSize = fdfEncodedData.tellp();
- if (nBufSize == 0)
+ if (nBufSize <= 0)
return false;
pBuf = FX_Alloc(uint8_t, nBufSize);