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);