summaryrefslogtreecommitdiff
path: root/widget
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2023-05-10 23:15:23 +0200
committerMoonchild <moonchild@palemoon.org>2023-05-10 23:15:23 +0200
commit0fcefb9d0abef22331961081e5944b3986a9cc00 (patch)
tree8d76ef7b009223234852b32009ee755df71a561a /widget
parent8666ce68fc5fa6eb8547babee23e60ca4c3bfd98 (diff)
downloaduxp-0fcefb9d0abef22331961081e5944b3986a9cc00.tar.gz
[widget] Rewrite data-read loop in OnDataAvailable.
The read-loop in OnDataAvailable was needlessly baroque and used a very strange dialect of Hungarian notation. Factored out the zero-element case for simplicity, and added justification in comments as-appropriate.
Diffstat (limited to 'widget')
-rw-r--r--widget/windows/nsDataObj.cpp57
1 files changed, 40 insertions, 17 deletions
diff --git a/widget/windows/nsDataObj.cpp b/widget/windows/nsDataObj.cpp
index f665e63105..6dc9eb7ecd 100644
--- a/widget/windows/nsDataObj.cpp
+++ b/widget/windows/nsDataObj.cpp
@@ -121,25 +121,48 @@ nsDataObj::CStream::OnDataAvailable(nsIRequest *aRequest,
uint64_t aOffset, // offset within the stream
uint32_t aCount) // bytes available on this call
{
- // Extend the write buffer for the incoming data.
- uint8_t* buffer = mChannelData.AppendElements(aCount, fallible);
- if (!buffer) {
- return NS_ERROR_OUT_OF_MEMORY;
+ // If we've been asked to read zero bytes, call `Read` once, just to ensure
+ // any side-effects take place, and return immediately.
+ if (aCount == 0) {
+ char buffer[1] = {0};
+ uint32_t bytesReadByCall = 0;
+ nsresult rv = aInputStream->Read(buffer, 0, &bytesReadByCall);
+ MOZ_ASSERT(bytesReadByCall == 0);
+ return rv;
+ }
+
+ // Extend the write buffer for the incoming data.
+ size_t oldLength = mChannelData.Length();
+ char* buffer = reinterpret_cast<char*>(mChannelData.AppendElements(aCount, fallible));
+ if (!buffer) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ MOZ_ASSERT(mChannelData.Length() == (aOffset + aCount),
+ "stream length mismatch w/write buffer");
+
+ // Read() may not return aCount on a single call, so loop until we've
+ // accumulated all the data OnDataAvailable has promised.
+ uint32_t bytesRead = 0;
+ while (bytesRead < aCount) {
+ uint32_t bytesReadByCall = 0;
+ nsresult rv = aInputStream->Read(buffer + bytesRead, aCount - bytesRead,
+ &bytesReadByCall);
+ bytesRead += bytesReadByCall;
+
+ if (bytesReadByCall == 0) {
+ // A `bytesReadByCall` of zero indicates EOF without failure... but we
+ // were promised `aCount` elements and haven't gotten them. Return a
+ // generic failure.
+ rv = NS_ERROR_FAILURE;
}
- NS_ASSERTION((mChannelData.Length() == (aOffset + aCount)),
- "stream length mismatch w/write buffer");
- // Read() may not return aCount on a single call, so loop until we've
- // accumulated all the data OnDataAvailable has promised.
- nsresult rv;
- uint32_t odaBytesReadTotal = 0;
- do {
- uint32_t bytesReadByCall = 0;
- rv = aInputStream->Read((char*)(buffer + odaBytesReadTotal),
- aCount, &bytesReadByCall);
- odaBytesReadTotal += bytesReadByCall;
- } while (aCount < odaBytesReadTotal && NS_SUCCEEDED(rv));
- return rv;
+ if (NS_FAILED(rv)) {
+ // Drop any trailing uninitialized elements before erroring out.
+ mChannelData.RemoveElementsAt(oldLength + bytesRead, aCount - bytesRead);
+ return rv;
+ }
+ }
+ return NS_OK;
}
NS_IMETHODIMP nsDataObj::CStream::OnStartRequest(nsIRequest *aRequest,