Firefox · Networking
CVE-2026-117952
Logic Error in Networking
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
fornetwerk/cache2/CacheFile.cpp |
modified | |
ifnetwerk/cache2/CacheFile.cpp |
modified |
Files Changed
netwerk/cache2/CacheFile.cppnetwerk/cache2/CacheFileChunk.cppnetwerk/cache2/CacheFileInputStream.h
Patch
diff --git a/netwerk/cache2/CacheFile.cpp b/netwerk/cache2/CacheFile.cpp
index 4c2a4476343..018017bf853 100644
--- a/netwerk/cache2/CacheFile.cpp
+++ b/netwerk/cache2/CacheFile.cpp
@@ -2191,16 +2191,12 @@ void CacheFile::RemoveOutput(CacheFileOutputStream* aOutput, nsresult aStatus) {
mOutput = nullptr; // XXX should this be after NotifyCloseListener?
- // Cancel all queued chunk and update listeners that cannot be satisfied
- NotifyListenersAboutOutputRemoval();
-
- if (!mMemoryOnly) WriteMetadataIfNeededLocked();
+ bool failed = NS_FAILED(aStatus) && aStatus != NS_BASE_STREAM_CLOSED;
// Make sure the CacheFile status is set to a failure when the output stream
// is closed with a fatal error. This way we propagate correctly and w/o any
// windows the failure state of this entry to end consumers.
- if (NS_SUCCEEDED(mStatus) && NS_FAILED(aStatus) &&
- aStatus != NS_BASE_STREAM_CLOSED) {
+ if (NS_SUCCEEDED(mStatus) && failed) {
if (aOutput->IsAlternativeData()) {
MOZ_ASSERT(mAltDataOffset != -1);
// If there is no alt-data input stream truncate only alt-data, otherwise
@@ -2233,6 +2229,25 @@ void CacheFile::RemoveOutput(CacheFileOutputStream* aOutput, nsresult aStatus) {
}
}
+ // Propagate the failure to alt-data readers.
+ if (failed && aOutput->IsAlternativeData() && NS_FAILED(mStatus)) {
+ for (CacheFileInputStream* input : mInputs) {
+ if (input->IsAlternativeData()) {
+ // Closing may drop the last outside reference to an input; keep it
+ // alive until the lock is released so RemoveInput() isn't reentered.
+ ReleaseOutsideLock(RefPtr<nsIInputStream>(input));
+ input->CloseWithStatusLocked(mStatus);
+ }
+ }
+ }
+
+ // Cancel all queued chunk and update listeners that cannot be satisfied
+ NotifyListenersAboutOutputRemoval();
+
+ if (!mMemoryOnly) {
+ WriteMetadataIfNeededLocked();
+ }
+
// Notify close listener as the last action
aOutput->NotifyCloseListener();
diff --git a/netwerk/cache2/CacheFileChunk.cpp b/netwerk/cache2/CacheFileChunk.cpp
index ff421e9b361..0ef21c4a8a7 100644
--- a/netwerk/cache2/CacheFileChunk.cpp
+++ b/netwerk/cache2/CacheFileChunk.cpp
@@ -498,7 +498,8 @@ void CacheFileChunk::CancelWait(CacheFileChunkListener* aCallback) {
LOG(("CacheFileChunk::CancelWait() [this=%p, listener=%p]", this, aCallback));
- MOZ_ASSERT(IsReady());
+ // The chunk may have failed while the listener was waiting.
+ MOZ_ASSERT(mState == READY || mState == WRITING);
uint32_t i;
for (i = 0; i < mUpdateListeners.Length(); i++) {
diff --git a/netwerk/cache2/CacheFileInputStream.h b/netwerk/cache2/CacheFileInputStream.h
index 36a56803b73..0d77f8eb55b 100644
--- a/netwerk/cache2/CacheFileInputStream.h
+++ b/netwerk/cache2/CacheFileInputStream.h
@@ -44,6 +44,8 @@ class CacheFileInputStream : public nsIAsyncInputStream,
};
private:
+ friend class CacheFile;
+
virtual ~CacheFileInputStream();
void CloseWithStatusLocked(nsresult aStatus);
Loading diff…
References
On This Page