Bug 1170606 part-1: add short read handling under mailnews/import directory draft
authorISHIKAWA, Chiaki <ishikawa@yk.rim.or.jp>
Sun, 20 Oct 2019 05:51:05 +0900
changeset 80341 83a831a707787d114ce7371453b004ff6ac79284
parent 80340 a1fb776f1cf84d55b1bc868bb67dc951f0750105
child 80342 f030ce2d5f454763ef03f27e870a02d85cc182d1
push id9576
push userishikawa@yk.rim.or.jp
push dateSat, 19 Oct 2019 20:51:19 +0000
treeherdertry-comm-central@4e899dfbba0c [default view] [failures only]
bugs1170606
Bug 1170606 part-1: add short read handling under mailnews/import directory
mailnews/import/becky/src/nsBeckyMail.cpp
mailnews/import/outlook/src/MapiApi.cpp
mailnews/import/outlook/src/nsOutlookCompose.cpp
mailnews/import/src/nsImportScanFile.cpp
--- a/mailnews/import/becky/src/nsBeckyMail.cpp
+++ b/mailnews/import/becky/src/nsBeckyMail.cpp
@@ -1,9 +1,10 @@
 /* vim: set ts=2 et sw=2 tw=80: */
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsIFile.h"
 #include "nsIInputStream.h"
--- a/mailnews/import/outlook/src/MapiApi.cpp
+++ b/mailnews/import/outlook/src/MapiApi.cpp
@@ -135,17 +135,18 @@ BOOL CMapiApi::GetRTFPropertyDecodedAsUT
     // Stream.Stat doesn't work for this stream!
     bool done = false;
     while (!done) {
       // I think 10K is a good guess to minimize the number of reads while
       // keeping memory usage low
       const int bufsize = 10240;
       char buf[bufsize];
       ULONG read;
-      hr = iunstream->Read(buf, bufsize, &read);
+      hr = iunstream->Read(buf, bufsize,
+                           &read);  // Note: short read is acceptable.
       done = (read < bufsize) || (hr != S_OK);
       if (read) streamData.append(buf, read);
     }
     iunstream->Release();
     // if rtf -> convert to plain text.
     if (!gpWrapCompressedRTFStreamEx ||
         (nativeBodyType == MAPI_NATIVE_BODY_TYPE_RTF)) {
       std::stringstream s(streamData);
@@ -1123,17 +1124,29 @@ BOOL CMapiApi::GetLargeProperty(LPMAPIPR
   hr = lpStream->Stat(&st, STATFLAG_NONAME);
   if (HR_FAILED(hr))
     bResult = FALSE;
   else {
     if (!st.cbSize.QuadPart) st.cbSize.QuadPart = 1;
     char *pVal = new char[(int)st.cbSize.QuadPart + 2];
     if (pVal) {
       ULONG sz;
+      // xxx I don't understand the processing here.
+      // Not sure whether short read is acceptable or not.
+      // But Since we seem to require the read the desired octets,
+      // let us use FullyReadStream
+      // xxx we can't cast lpStream to a file stream under Windows.
+      // Does window suffer from not using |FullyReadStream()|?
+      // Unlikely. This is because read system call under windows seems to
+      // handle short read in the kernel.
+#ifdef WIN32
       hr = lpStream->Read(pVal, (ULONG)st.cbSize.QuadPart, &sz);
+#else
+      hr = FullyReadStream(lpStream, pVal, (ULONG)st.cbSize.QuadPart, &sz);
+#endif
       if (HR_FAILED(hr)) {
         bResult = FALSE;
         delete[] pVal;
       } else {
         // Just in case it's a UTF16 string
         pVal[(int)st.cbSize.QuadPart] = pVal[(int)st.cbSize.QuadPart + 1] = 0;
         *result = pVal;
       }
--- a/mailnews/import/outlook/src/nsOutlookCompose.cpp
+++ b/mailnews/import/outlook/src/nsOutlookCompose.cpp
@@ -518,17 +518,31 @@ CCompositionFile::CCompositionFile(nsIFi
 nsresult CCompositionFile::EnsureHasDataInBuffer() {
   if (m_fifoBufferReadPos < m_fifoBufferWrittenPos) return NS_OK;
   // Populate the buffer with new data!
   uint32_t count = m_fifoBufferSize;
   if ((m_fileReadPos + count) > m_fileSize) count = m_fileSize - m_fileReadPos;
   if (!count) return NS_ERROR_FAILURE;  // Isn't there a "No more data" error?
 
   uint32_t bytesRead = 0;
-  nsresult rv = m_pInputStream->Read(m_fifoBuffer, count, &bytesRead);
+  // xxx short read is OK as long as there is a data.
+  // But since FullyReadStream handles EINTR case (hopefully)
+  // [!bytesRead case below.]
+  // Let us use it after checking the available octets.
+  // xxx we should check the available size in advance ...
+  // xxx Let us read available octets using FullyReadStream anyway.
+  {
+    uint64_t available;
+    nsresult rv = m_pInputStream->Available(&available);
+    if (NS_SUCCEEDED(rv) && available > 0) {
+      if (count > available) count = (uint32_t)available;
+    }
+  }
+  nsresult rv =
+      FullyReadStream(m_pInputStream, m_fifoBuffer, count, &bytesRead);
   NS_ENSURE_SUCCESS(rv, rv);
   if (!bytesRead || (bytesRead > count)) return NS_ERROR_FAILURE;
   m_fifoBufferWrittenPos = m_fifoBuffer + bytesRead;
   m_fifoBufferReadPos = m_fifoBuffer;
   m_fileReadPos += bytesRead;
 
   return NS_OK;
 }
--- a/mailnews/import/src/nsImportScanFile.cpp
+++ b/mailnews/import/src/nsImportScanFile.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nscore.h"
 #include "nsImportScanFile.h"
 #include "ImportCharSet.h"
+#include "nsMsgUtils.h"
 
 nsImportScanFile::nsImportScanFile() {
   m_allocated = false;
   m_eof = false;
   m_pBuf = nullptr;
 }
 
 nsImportScanFile::~nsImportScanFile() {
@@ -65,19 +66,23 @@ bool nsImportScanFile::FillBufferFromFil
   // Read in some more bytes
   uint32_t cnt = m_bufSz - m_bytesInBuf;
   // To distinguish from disk errors
   // Check first for end of file?
   // Set a done flag if true...
   uint32_t read;
   char *pBuf = (char *)m_pBuf;
   pBuf += m_bytesInBuf;
-  rv = m_pInputStream->Read(pBuf, (int32_t)cnt, &read);
+  // xxx
+  // At the end, the current code assumes cnt octets are read completely!
+  // m_bytesInBuf += cnt;
+  // So we should avoid short read and check if cnt octets are read
+  rv = FullyReadStream(m_pInputStream, pBuf, (int32_t)cnt, &read);
 
-  if (NS_FAILED(rv)) return false;
+  if (NS_FAILED(rv) || read != cnt) return false;
   rv = m_pInputStream->Available(&available);
   if (NS_FAILED(rv)) m_eof = true;
 
   m_bytesInBuf += cnt;
   return true;
 }
 
 bool nsImportScanFile::Scan(bool *pDone) {