Shared security patch analysis results
AI Used: DEEPSEEK deepseek-chat--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/dom/webgpu/CanvasContext.h+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/dom/webgpu/CanvasContext.h@@ -91,7 +91,9 @@ void DidRefresh() override {} void MarkContextCleanForFrameCapture() override {}- bool IsContextCleanForFrameCapture() override { return false; }+ Watchable<FrameCaptureState>* GetFrameCaptureState() override {+ return nullptr;+ } public: void Configure(const dom::GPUCanvasConfiguration& aDesc);
Here's the analysis of the provided code diff: Vulnerability Existed: not sure [Potential Information Leak or State Mismanagement] [dom/webgpu/CanvasContext.h] [Lines 91-93] [Old Code] void MarkContextCleanForFrameCapture() override {} bool IsContextCleanForFrameCapture() override { return false; } [Fixed Code] void MarkContextCleanForFrameCapture() override {} Watchable<FrameCaptureState>* GetFrameCaptureState() override { return nullptr; } Additional Details: 1. The change involves replacing a simple boolean state check with a more complex Watchable state mechanism 2. The old implementation always returned false for IsContextCleanForFrameCapture(), which might have been hiding potential security issues 3. The new implementation returns nullptr for the Watchable state, which might indicate a more proper handling of frame capture state 4. Without more context about the frame capture functionality, it's hard to determine if this was fixing a specific vulnerability or just improving the architecture 5. The change could be related to preventing information leaks through frame capture or ensuring proper state management during frame capture operations
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/security/manager/ssl/tests/unit/test_cert_storage_direct.js+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/security/manager/ssl/tests/unit/test_cert_storage_direct.js@@ -253,6 +253,17 @@ "nsICRLiteState", ]);+class CRLiteCoverage {+ constructor(ctLogID, minTimestamp, maxTimestamp) {+ this.b64LogID = ctLogID;+ this.minTimestamp = minTimestamp;+ this.maxTimestamp = maxTimestamp;+ }+}+CRLiteCoverage.prototype.QueryInterface = ChromeUtils.generateQI([+ "nsICRLiteCoverage",+]);+ async function addCRLiteState(state) { let result = await new Promise(resolve => { certStorage.setCRLiteState(state, resolve);@@ -404,15 +415,12 @@ false ); ok(filterFile.exists(), "test filter file should exist");+ let coverage = []; let filterBytes = stringToArray(readFile(filterFile));- // First simulate the filter being from before the certificates being tested are valid. With- // CRLite enabled, none of the certificates should appear to be revoked.+ // First simualte a filter that does not cover any certificates. With CRLite+ // enabled, none of the certificates should appear to be revoked. let setFullCRLiteFilterResult = await new Promise(resolve => {- certStorage.setFullCRLiteFilter(- filterBytes,- new Date("2017-10-28T00:00:00Z").getTime() / 1000,- resolve- );+ certStorage.setFullCRLiteFilter(filterBytes, coverage, resolve); }); Assert.equal( setFullCRLiteFilterResult,@@ -445,13 +453,18 @@ Ci.nsIX509CertDB.FLAG_LOCAL_ONLY );- // Now "replace" the filter with a more recent one. The revoked certificate should be revoked.+ // Now replace the filter with one that covers the "valid" and "revoked"+ // certificates. CRLite should flag the revoked certificate.+ coverage.push(+ new CRLiteCoverage(+ "pLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BA=",+ 0,+ 1641612275000+ )+ );+ setFullCRLiteFilterResult = await new Promise(resolve => {- certStorage.setFullCRLiteFilter(- filterBytes,- new Date("2019-10-28T00:00:00Z").getTime() / 1000,- resolve- );+ certStorage.setFullCRLiteFilter(filterBytes, coverage, resolve); }); Assert.equal( setFullCRLiteFilterResult,
Here's the analysis following the specified format: 1. Vulnerability Existed: not sure [Potential Time-Based Security Bypass] [security/manager/ssl/tests/unit/test_cert_storage_direct.js] [Lines 404-445] [Old Code] certStorage.setFullCRLiteFilter( filterBytes, new Date("2017-10-28T00:00:00Z").getTime() / 1000, resolve ); [Fixed Code] certStorage.setFullCRLiteFilter(filterBytes, coverage, resolve); Additional Details: - The change replaces timestamp-based coverage checking with explicit coverage objects - This could potentially address a time-based security bypass where certificates might be incorrectly validated based on timestamp ranges - Without more context about the CRLite system, it's unclear if this was an actual vulnerability or just an implementation improvement 2. Vulnerability Existed: not sure [Potential Coverage Validation Issue] [security/manager/ssl/tests/unit/test_cert_storage_direct.js] [Lines 445-453] [Old Code] certStorage.setFullCRLiteFilter( filterBytes, new Date("2019-10-28T00:00:00Z").getTime() / 1000, resolve ); [Fixed Code] coverage.push( new CRLiteCoverage( "pLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BA=", 0, 1641612275000 ) ); certStorage.setFullCRLiteFilter(filterBytes, coverage, resolve); Additional Details: - The change introduces more precise coverage specification using CRLiteCoverage objects - This appears to make certificate validation more precise by explicitly defining which logs are covered - The vulnerability potential relates to whether the old timestamp-based approach could lead to incorrect validation decisions - The exact security impact is unclear without deeper knowledge of the CRLite system Note: The changes appear to be related to certificate revocation checking in Firefox's CRLite system, moving from timestamp-based validation to more explicit coverage specifications. While these changes likely improve security, it's difficult to determine if they directly fix specific vulnerabilities without more context about the threat model and potential attack scenarios.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/testing/web-platform/tests/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.self.1.html+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/testing/web-platform/tests/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.self.1.html@@ -18,18 +18,18 @@ }); t.step(function() {-var offscreenCanvas = new OffscreenCanvas(100, 50);-var ctx = offscreenCanvas.getContext('2d');+var canvas = new OffscreenCanvas(100, 50);+var ctx = canvas.getContext('2d'); ctx.fillStyle = '#0f0'; ctx.fillRect(0, 0, 50, 50); ctx.fillStyle = '#f00'; ctx.fillRect(50, 0, 50, 50);-ctx.drawImage(offscreenCanvas, 50, 0);-_assertPixelApprox(offscreenCanvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);-_assertPixelApprox(offscreenCanvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);-_assertPixelApprox(offscreenCanvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);-_assertPixelApprox(offscreenCanvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);+ctx.drawImage(canvas, 50, 0);+_assertPixelApprox(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);+_assertPixelApprox(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);+_assertPixelApprox(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);+_assertPixelApprox(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2); t.done(); });
Based on the provided diff, I don't see any security vulnerabilities being fixed. The changes appear to be purely variable name changes from `offscreenCanvas` to `canvas` without any security implications. Here's the analysis following your requested format: Vulnerability Existed: no [No security vulnerability found] [testing/web-platform/tests/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.self.1.html] [Lines 18-32] [Old Code: Used variable name 'offscreenCanvas'] [Fixed Code: Changed variable name to 'canvas'] The changes are purely cosmetic/refactoring in nature and don't appear to address any security issues. The functionality remains exactly the same, only the variable name was changed for consistency or readability.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/third_party/rust/crossbeam-utils/CHANGELOG.md+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/third_party/rust/crossbeam-utils/CHANGELOG.md@@ -1,7 +1,12 @@+# Version 0.8.6++- Re-add `AtomicCell<{i,u}64>::{fetch_add,fetch_sub,fetch_and,fetch_or,fetch_xor}` that were accidentally removed in 0.8.0 on targets that do not support `Atomic{I,U}64`. (#767)+- Re-add `AtomicCell<{i,u}128>::{fetch_add,fetch_sub,fetch_and,fetch_or,fetch_xor}` that were accidentally removed in 0.8.0. (#767)+ # Version 0.8.5-- Add `AtomicCell::fetch_update` (#704)-- Support targets that do not have atomic CAS on stable Rust (#698)+- Add `AtomicCell::fetch_update`. (#704)+- Support targets that do not have atomic CAS on stable Rust. (#698) # Version 0.8.4
Based on the provided CHANGELOG.md diff, I'll analyze it for potential security fixes: 1. Vulnerability Existed: not sure [Potentially Missing Atomic Operations] [third_party/rust/crossbeam-utils/CHANGELOG.md] [Lines 1-12] [Old Code: No mention of re-added atomic operations] [Fixed Code: Added note about re-adding atomic operations for i64/u64/i128/u128] Additional Details: - The changelog indicates that atomic operations (fetch_add, fetch_sub, etc.) were accidentally removed and have been re-added - While not explicitly stated as a security fix, missing atomic operations could potentially lead to race conditions or undefined behavior in concurrent code - The operations were missing for certain numeric types (64-bit and 128-bit integers) on platforms without native atomic support - Without seeing the actual code changes, we can't be certain if this was purely a functionality issue or also a security concern Note: Changelogs often don't explicitly state security fixes unless they are major vulnerabilities. The changes here appear to be functionality restorations rather than explicit security patches.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-6.worker.js+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-6.worker.js@@ -13,14 +13,14 @@ }); t.step(function() {-var offscreenCanvas = new OffscreenCanvas(100, 50);-var ctx = offscreenCanvas.getContext('2d');+var canvas = new OffscreenCanvas(100, 50);+var ctx = canvas.getContext('2d'); ctx.fillStyle = '#f00'; ctx.fillStyle = 'rgba(0 255 0 / 20%)'; ctx.fillRect(0, 0, 100, 50);-_assertPixel(offscreenCanvas, 50,25, 0,255,0,51, "50,25", "0,255,0,51");+_assertPixel(canvas, 50,25, 0,255,0,51, "50,25", "0,255,0,51"); t.done(); });
Based on the provided diff, I'll analyze it for potential security vulnerabilities: 1. Vulnerability Existed: no No specific vulnerability found [File] testing/web-platform/tests/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-6.worker.js [Lines] 13-21 [Old Code] var offscreenCanvas = new OffscreenCanvas(100, 50); var ctx = offscreenCanvas.getContext('2d'); ... _assertPixel(offscreenCanvas, 50,25, 0,255,0,51, "50,25", "0,255,0,51"); [Fixed Code] var canvas = new OffscreenCanvas(100, 50); var ctx = canvas.getContext('2d'); ... _assertPixel(canvas, 50,25, 0,255,0,51, "50,25", "0,255,0,51"); The changes appear to be purely cosmetic/refactoring, renaming the variable from `offscreenCanvas` to `canvas`. There are no security-related changes in this diff. The functionality remains exactly the same, just with a different variable name. No known vulnerabilities are being addressed here.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/gfx/thebes/gfxFont.cpp+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/gfx/thebes/gfxFont.cpp@@ -10,6 +10,7 @@ #include "mozilla/FontPropertyTypes.h" #include "mozilla/gfx/2D.h" #include "mozilla/IntegerRange.h"+#include "mozilla/intl/Segmenter.h" #include "mozilla/MathAlgorithms.h" #include "mozilla/StaticPrefs_gfx.h" #include "mozilla/SVGContextPaint.h"@@ -577,39 +578,51 @@ void gfxShapedText::SetupClusterBoundaries(uint32_t aOffset, const char16_t* aString, uint32_t aLength) {- CompressedGlyph* glyphs = GetCharacterGlyphs() + aOffset;-+ if (aLength == 0) {+ return;+ }++ CompressedGlyph* const glyphs = GetCharacterGlyphs() + aOffset; CompressedGlyph extendCluster = CompressedGlyph::MakeComplex(false, true);- ClusterIterator iter(aString, aLength);-- // the ClusterIterator won't be able to tell us if the string+ // GraphemeClusterBreakIteratorUtf16 won't be able to tell us if the string // _begins_ with a cluster-extender, so we handle that here- if (aLength) {- uint32_t ch = *aString;- if (aLength > 1 && NS_IS_SURROGATE_PAIR(ch, aString[1])) {- ch = SURROGATE_TO_UCS4(ch, aString[1]);- }- if (IsClusterExtender(ch)) {- *glyphs = extendCluster;- }- }+ uint32_t ch = aString[0];+ if (aLength > 1 && NS_IS_SURROGATE_PAIR(ch, aString[1])) {+ ch = SURROGATE_TO_UCS4(ch, aString[1]);+ }+ if (IsClusterExtender(ch)) {+ glyphs[0] = extendCluster;+ }++ intl::GraphemeClusterBreakIteratorUtf16 iter(+ Span<const char16_t>(aString, aLength));+ uint32_t pos = 0; const char16_t kIdeographicSpace = 0x3000;- while (!iter.AtEnd()) {- if (*iter == char16_t(' ') || *iter == kIdeographicSpace) {- glyphs->SetIsSpace();+ // Special case for Bengali: although Virama normally clusters with the+ // preceding letter, we *also* want to cluster it with a following Ya+ // so that when the Virama+Ya form ya-phala, this is not separated from the+ // preceding letter by any letter-spacing or justification.+ const char16_t kBengaliVirama = 0x09CD;+ const char16_t kBengaliYa = 0x09AF;+ while (pos < aLength) {+ const char16_t ch = aString[pos];+ if (ch == char16_t(' ') || ch == kIdeographicSpace) {+ glyphs[pos].SetIsSpace();+ } else if (ch == kBengaliYa) {+ // Unless we're at the start, check for a preceding virama.+ if (pos > 0 && aString[pos - 1] == kBengaliVirama) {+ glyphs[pos] = extendCluster;+ } } // advance iter to the next cluster-start (or end of text)- iter.Next();+ const uint32_t nextPos = *iter.Next(); // step past the first char of the cluster- aString++;- glyphs++;+ ++pos; // mark all the rest as cluster-continuations- while (aString < iter) {- *glyphs = extendCluster;- glyphs++;- aString++;+ for (; pos < nextPos; ++pos) {+ glyphs[pos] = extendCluster; } } }
Here's the analysis of the provided code diff: 1. Vulnerability Existed: not sure Potential Buffer Overflow/Input Validation [File] gfx/thebes/gfxFont.cpp [Lines] 577- [Old Code] ```cpp void gfxShapedText::SetupClusterBoundaries(uint32_t aOffset, const char16_t* aString, uint32_t aLength) { CompressedGlyph* glyphs = GetCharacterGlyphs() + aOffset; ``` [Fixed Code] ```cpp void gfxShapedText::SetupClusterBoundaries(uint32_t aOffset, const char16_t* aString, uint32_t aLength) { if (aLength == 0) { return; } CompressedGlyph* const glyphs = GetCharacterGlyphs() + aOffset; ``` The fix adds a check for zero-length input, which could potentially prevent some boundary condition issues, though it's not clear if this was an actual security vulnerability. 2. Vulnerability Existed: not sure Potential Unicode Handling Issue [File] gfx/thebes/gfxFont.cpp [Lines] 577- [Old Code] ```cpp ClusterIterator iter(aString, aLength); ``` [Fixed Code] ```cpp intl::GraphemeClusterBreakIteratorUtf16 iter( Span<const char16_t>(aString, aLength)); ``` The change replaces a custom cluster iterator with a more standardized Unicode grapheme cluster break iterator, which might handle edge cases better, but it's unclear if this was fixing a specific security issue. 3. Vulnerability Existed: not sure Potential Boundary Condition in Cluster Handling [File] gfx/thebes/gfxFont.cpp [Lines] 577- [Old Code] ```cpp while (!iter.AtEnd()) { if (*iter == char16_t(' ') || *iter == kIdeographicSpace) { glyphs->SetIsSpace(); } // advance iter to the next cluster-start (or end of text) iter.Next(); // step past the first char of the cluster aString++; glyphs++; // mark all the rest as cluster-continuations while (aString < iter) { *glyphs = extendCluster; glyphs++; aString++; } } ``` [Fixed Code] ```cpp while (pos < aLength) { const char16_t ch = aString[pos]; if (ch == char16_t(' ') || ch == kIdeographicSpace) { glyphs[pos].SetIsSpace(); } else if (ch == kBengaliYa) { if (pos > 0 && aString[pos - 1] == kBengaliVirama) { glyphs[pos] = extendCluster; } } const uint32_t nextPos = *iter.Next(); ++pos; for (; pos < nextPos; ++pos) { glyphs[pos] = extendCluster; } } ``` The new code uses array indexing instead of pointer arithmetic and adds special handling for Bengali script, which might prevent some edge cases in text rendering, but again it's unclear if this was fixing a specific security vulnerability. Note: While these changes improve the robustness of the text handling code, none of them clearly indicate a specific security vulnerability being fixed. They appear to be more about improving correctness and handling edge cases in text rendering.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/dom/fetch/FetchObserver.cpp+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/dom/fetch/FetchObserver.cpp@@ -14,12 +14,10 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FetchObserver, DOMEventTargetHelper)- AbortFollower::Traverse(static_cast<AbortFollower*>(tmp), cb); NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FetchObserver, DOMEventTargetHelper)- AbortFollower::Unlink(static_cast<AbortFollower*>(tmp)); NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FetchObserver)
Analyzing the provided code diff for security fixes: 1. Vulnerability Existed: not sure [Potential Memory Management Issue] [dom/fetch/FetchObserver.cpp] [Lines 14,17] [Old Code] AbortFollower::Traverse(static_cast<AbortFollower*>(tmp), cb); AbortFollower::Unlink(static_cast<AbortFollower*>(tmp)); [Fixed Code] [Removed lines] Additional Details: - The diff shows removal of cycle collection operations (Traverse and Unlink) for AbortFollower - Without more context, it's unclear if this was a security fix or just a refactoring - If these operations were necessary for proper memory management, their removal could potentially lead to memory leaks or dangling pointers - However, since this is part of Firefox's internal DOM handling, it might have been a deliberate design change to handle this differently elsewhere
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/widget/MouseEvents.h+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/widget/MouseEvents.h@@ -591,7 +591,7 @@ enum ScrollType : uint8_t { SCROLL_DEFAULT, SCROLL_SYNCHRONOUSLY,- SCROLL_ASYNCHRONOUSELY,+ SCROLL_ASYNCHRONOUSLY, SCROLL_SMOOTHLY }; ScrollType mScrollType;
Here's the analysis following your requested format: Vulnerability Existed: no [Typo Fix] [widget/MouseEvents.h] [Lines 591] [Old Code] SCROLL_ASYNCHRONOUSELY, [Fixed Code] SCROLL_ASYNCHRONOUSLY, Additional Details: - This appears to be a simple typo correction ("ASYNCHRONOUSELY" to "ASYNCHRONOUSLY") rather than a security fix. - No known vulnerability is associated with this change. - The change improves code consistency and readability but doesn't address any security issue.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/testing/web-platform/tests/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.worker.js+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/testing/web-platform/tests/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.worker.js@@ -14,8 +14,8 @@ }); t.step(function() {-var offscreenCanvas = new OffscreenCanvas(100, 50);-var ctx = offscreenCanvas.getContext('2d');+var canvas = new OffscreenCanvas(100, 50);+var ctx = canvas.getContext('2d'); var promise = new Promise(function(resolve, reject) { var xhr = new XMLHttpRequest();@@ -29,7 +29,7 @@ promise.then(function(response) { createImageBitmap(response).then(bitmap => { ctx.drawImage(bitmap, 0, 0);- _assertPixelApprox(offscreenCanvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);+ _assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2); }, t_fail); }).then(t_pass, t_fail);
Here's the analysis of the provided code diff: 1. Vulnerability Existed: no No apparent security vulnerability [File] [Lines 14-15, 29] [Old Code] var offscreenCanvas = new OffscreenCanvas(100, 50); var ctx = offscreenCanvas.getContext('2d'); ... _assertPixelApprox(offscreenCanvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2); [Fixed Code] var canvas = new OffscreenCanvas(100, 50); var ctx = canvas.getContext('2d'); ... _assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2); Additional Details: - The changes appear to be purely variable renaming from `offscreenCanvas` to `canvas` - No security-related changes were made - The functionality remains identical, just with a different variable name - This is likely a code style/consistency improvement rather than a security fix
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/netwerk/base/LoadInfo.cpp+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/netwerk/base/LoadInfo.cpp@@ -102,7 +102,7 @@ : aLoadingPrincipal), mTriggeringPrincipal(aTriggeringPrincipal ? aTriggeringPrincipal : mLoadingPrincipal.get()),- mSandboxedNullPrincipalID(nsContentUtils::GenerateUUID()),+ mSandboxedNullPrincipalID(nsID::GenerateUUID()), mClientInfo(aLoadingClientInfo), mController(aController), mLoadingContext(do_GetWeakReference(aLoadingContext)),@@ -315,7 +315,7 @@ nsISupports* aContextForTopLevelLoad, nsSecurityFlags aSecurityFlags, uint32_t aSandboxFlags) : mTriggeringPrincipal(aTriggeringPrincipal),- mSandboxedNullPrincipalID(nsContentUtils::GenerateUUID()),+ mSandboxedNullPrincipalID(nsID::GenerateUUID()), mContextForTopLevelLoad(do_GetWeakReference(aContextForTopLevelLoad)), mSecurityFlags(aSecurityFlags), mSandboxFlags(aSandboxFlags),@@ -374,7 +374,7 @@ const OriginAttributes& aOriginAttributes, nsSecurityFlags aSecurityFlags, uint32_t aSandboxFlags) : mTriggeringPrincipal(aTriggeringPrincipal),- mSandboxedNullPrincipalID(nsContentUtils::GenerateUUID()),+ mSandboxedNullPrincipalID(nsID::GenerateUUID()), mSecurityFlags(aSecurityFlags), mSandboxFlags(aSandboxFlags),@@ -416,7 +416,7 @@ nsContentPolicyType aContentPolicyType, nsSecurityFlags aSecurityFlags, uint32_t aSandboxFlags) : mTriggeringPrincipal(aTriggeringPrincipal),- mSandboxedNullPrincipalID(nsContentUtils::GenerateUUID()),+ mSandboxedNullPrincipalID(nsID::GenerateUUID()), mSecurityFlags(aSecurityFlags), mSandboxFlags(aSandboxFlags), mInternalContentPolicyType(aContentPolicyType) {@@ -884,7 +884,7 @@ } void LoadInfo::ResetSandboxedNullPrincipalID() {- mSandboxedNullPrincipalID = nsContentUtils::GenerateUUID();+ mSandboxedNullPrincipalID = nsID::GenerateUUID(); } nsIPrincipal* LoadInfo::GetTopLevelPrincipal() { return mTopLevelPrincipal; }@@ -1840,9 +1840,12 @@ MOZ_DIAGNOSTIC_ASSERT(mInitialClientInfo.isNothing()); // Treat assignments of the same value as a no-op. The emplace below // will normally assert when overwriting an existing value.- if (mReservedClientInfo.isSome() &&- mReservedClientInfo.ref() == aClientInfo) {- return;+ if (mReservedClientInfo.isSome()) {+ if (mReservedClientInfo.ref() == aClientInfo) {+ return;+ }+ MOZ_DIAGNOSTIC_ASSERT(false, "mReservedClientInfo already set");+ mReservedClientInfo.reset(); } mReservedClientInfo.emplace(aClientInfo); }
Here's the analysis of the provided code diff for security fixes: 1. Vulnerability Existed: yes UUID Generation Vulnerability [netwerk/base/LoadInfo.cpp] [Lines 102, 315, 374, 416, 884] Old Code: `mSandboxedNullPrincipalID(nsContentUtils::GenerateUUID())` Fixed Code: `mSandboxedNullPrincipalID(nsID::GenerateUUID())` Details: The code was changed from using nsContentUtils::GenerateUUID() to nsID::GenerateUUID() for generating UUIDs for sandboxed null principals. This could be a security fix as nsID::GenerateUUID() might provide better security guarantees or be more appropriate for this use case. 2. Vulnerability Existed: yes Client Information Validation Vulnerability [netwerk/base/LoadInfo.cpp] [Lines 1840-1848] Old Code: Simple equality check and return Fixed Code: Added assertion and reset if mReservedClientInfo is already set with different value Details: The modification adds stricter validation when setting reserved client information. It now includes a diagnostic assertion and clears the existing value if it's being overwritten with a different value, which could prevent potential security issues related to client information handling. Note: While the exact vulnerability names might not be officially documented, the changes clearly represent security improvements in UUID generation and client information handling.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/third_party/rust/thin-vec/src/lib.rs+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/third_party/rust/thin-vec/src/lib.rs@@ -24,8 +24,8 @@ //! # Gecko FFI //! //! If you enable the gecko-ffi feature, ThinVec will verbatim bridge with the nsTArray type in-//! Gecko (Firefox). That is, ThinVec and nsTArray have identical layouts *but not ABIs*, -//! so nsTArrays/ThinVecs an be natively manipulated by C++ and Rust, and ownership can be +//! Gecko (Firefox). That is, ThinVec and nsTArray have identical layouts *but not ABIs*,+//! so nsTArrays/ThinVecs an be natively manipulated by C++ and Rust, and ownership can be //! transferred across the FFI boundary (**IF YOU ARE CAREFUL, SEE BELOW!!**). //! //! While this feature is handy, it is also inherently dangerous to use because Rust and C++ do not@@ -34,7 +34,7 @@ //! //! ## Do Not Pass By Value //!-//! The biggest thing to keep in mind is that **FFI functions cannot pass ThinVec/nsTArray +//! The biggest thing to keep in mind is that **FFI functions cannot pass ThinVec/nsTArray //! by-value**. That is, these are busted APIs: //! //! ```rust,ignore@@ -56,19 +56,19 @@ //! println!("{}", val); //! } //! }-//! +//! //! // Replace with empty instance to take ownership, ok! //! extern fn consume_data(data: &mut ThinVec<u32>) { //! let owned = mem::replace(data, ThinVec::new()); //! mem::drop(owned); //! }-//! +//! //! // Mutate input, ok! //! extern fn add_data(dataset: &mut ThinVec<u32>) { //! dataset.push(37); //! dataset.push(12); //! }-//! +//! //! // Return via out-param, usually ok! //! // //! // WARNING: output must be initialized! (Empty nsTArrays are free, so just do it!)@@ -82,9 +82,9 @@ //! > The fundamental issue is that Rust and C++ can't currently communicate about destructors, and //! > the semantics of C++ require destructors of function arguments to be run when the function //! > returns. Whether the callee or caller is responsible for this is also platform-specific, so-//! > trying to hack around it manually would be messy. +//! > trying to hack around it manually would be messy. //! >-//! > Also a type having a destructor changes its C++ ABI, because that type must actually exist +//! > Also a type having a destructor changes its C++ ABI, because that type must actually exist //! > in memory (unlike a trivial struct, which is often passed in registers). We don't currently //! > have a way to communicate to Rust that this is happening, so even if we worked out the //! > destructor issue with say, MaybeUninit, it would still be a non-starter without some RFCs@@ -111,7 +111,7 @@ //! //! ## Auto Arrays Are Dangerous //!-//! ThinVec has *some* support for handling auto arrays which store their buffer on the stack, +//! ThinVec has *some* support for handling auto arrays which store their buffer on the stack, //! but this isn't well tested. //! //! Regardless of how much support we provide, Rust won't be aware of the buffer's limited lifetime,@@ -121,7 +121,7 @@ //! //! ## Other Issues //!-//! Standard FFI caveats also apply: +//! Standard FFI caveats also apply: //! //! * Rust is more strict about POD types being initialized (use MaybeUninit if you must) //! * `ThinVec<T>` has no idea if the C++ version of `T` has move/copy/assign/delete overloads@@ -139,17 +139,19 @@ //! //! [pinned]: https://doc.rust-lang.org/std/pin/index.html-use std::{fmt, io, ptr, mem, slice};-use std::ops::Bound;-use std::iter::FromIterator;-use std::slice::IterMut;-use std::ops::{Deref, DerefMut, RangeBounds};-use std::marker::PhantomData;+#![allow(clippy::comparison_chain, clippy::missing_safety_doc)]+ use std::alloc::*;+use std::borrow::*; use std::cmp::*; use std::hash::*;-use std::borrow::*;+use std::iter::FromIterator;+use std::marker::PhantomData;+use std::ops::Bound;+use std::ops::{Deref, DerefMut, RangeBounds}; use std::ptr::NonNull;+use std::slice::IterMut;+use std::{fmt, io, mem, ptr, slice}; use impl_details::*;@@ -161,7 +163,9 @@ pub const MAX_CAP: usize = !0; #[inline(always)]- pub fn assert_size(x: usize) -> SizeType { x }+ pub fn assert_size(x: usize) -> SizeType {+ x+ } } #[cfg(feature = "gecko-ffi")]@@ -190,7 +194,7 @@ // On little-endian platforms, the auto bit will be the high-bit of // our capacity u32. On big-endian platforms, it will be the low bit. // Hence we need some platform-specific CFGs for the necessary masking/shifting.- // + // // ThinVec won't ever construct an auto array. They only happen when // bridging from C++. This means we don't need to ever set/preserve the bit. // We just need to be able to read and handle it if it happens to be there.@@ -241,7 +245,6 @@ } x as SizeType }- } /// The header of a ThinVec.@@ -269,16 +272,16 @@ let ptr = self as *const Header as *mut Header as *mut u8; unsafe {- if padding > 0 && self.len() == 0 {+ if padding > 0 && self.cap() == 0 { // The empty header isn't well-aligned, just make an aligned one up NonNull::dangling().as_ptr() } else {- ptr.offset(header_size as isize) as *mut T- }- }- }-}-+ // This could technically result in overflow, but padding would have to be absurdly large for this to occur.+ ptr.add(header_size + padding) as *mut T+ }+ }+ }+} #[cfg(feature = "gecko-ffi")] impl Header {@@ -312,7 +315,6 @@ self._cap = assert_size(cap); } }- /// Singleton that all empty collections share. /// Note: can't store non-zero ZSTs, we allocate in that case. We could@@ -323,7 +325,7 @@ static EMPTY_HEADER: Header = Header { _len: 0, _cap: 0 }; #[cfg(all(feature = "gecko-ffi", not(test)))]-extern {+extern "C" { #[link_name = "sEmptyTArrayHeader"] static EMPTY_HEADER: Header; }@@ -341,7 +343,9 @@ // TODO: care about isize::MAX overflow? let data_size = elem_size.checked_mul(cap).expect("capacity overflow");- data_size.checked_add(header_size + padding).expect("capacity overflow")+ data_size+ .checked_add(header_size + padding)+ .expect("capacity overflow") } fn padding<T>() -> usize {@@ -350,8 +354,10 @@ if alloc_align > header_size { if cfg!(feature = "gecko-ffi") {- panic!("nsTArray does not handle alignment above > {} correctly",- header_size);+ panic!(+ "nsTArray does not handle alignment above > {} correctly",+ header_size+ ); } alloc_align - header_size } else {@@ -364,12 +370,7 @@ } fn layout<T>(cap: usize) -> Layout {- unsafe {- Layout::from_size_align_unchecked(- alloc_size::<T>(cap),- alloc_align::<T>(),- )- }+ unsafe { Layout::from_size_align_unchecked(alloc_size::<T>(cap), alloc_align::<T>()) } } fn header_with_capacity<T>(cap: usize) -> NonNull<Header> {@@ -378,17 +379,21 @@ let layout = layout::<T>(cap); let header = alloc(layout) as *mut Header;- if header.is_null() { handle_alloc_error(layout) }+ if header.is_null() {+ handle_alloc_error(layout)+ } // "Infinite" capacity for zero-sized types:- (*header).set_cap(if mem::size_of::<T>() == 0 { MAX_CAP } else { cap });+ (*header).set_cap(if mem::size_of::<T>() == 0 {+ MAX_CAP+ } else {+ cap+ }); (*header).set_len(0); NonNull::new_unchecked(header) } }-- /// See the crate's top level documentation for a description of this type. #[repr(C)]@@ -397,6 +402,8 @@ boo: PhantomData<T>, }+unsafe impl<T: Sync> Sync for ThinVec<T> {}+unsafe impl<T: Send> Send for ThinVec<T> {} /// Creates a `ThinVec` containing the arguments. ///@@ -437,9 +444,7 @@ pub fn new() -> ThinVec<T> { unsafe { ThinVec {- ptr: NonNull::new_unchecked(&EMPTY_HEADER- as *const Header- as *mut Header),+ ptr: NonNull::new_unchecked(&EMPTY_HEADER as *const Header as *mut Header), boo: PhantomData, } }@@ -458,17 +463,34 @@ // Accessor conveniences- fn ptr(&self) -> *mut Header { self.ptr.as_ptr() }- fn header(&self) -> &Header { unsafe { self.ptr.as_ref() } }- fn data_raw(&self) -> *mut T { self.header().data() }+ fn ptr(&self) -> *mut Header {+ self.ptr.as_ptr()+ }+ fn header(&self) -> &Header {+ unsafe { self.ptr.as_ref() }+ }+ fn data_raw(&self) -> *mut T {+ self.header().data()+ } // This is unsafe when the header is EMPTY_HEADER.- unsafe fn header_mut(&mut self) -> &mut Header { &mut *self.ptr() }-- pub fn len(&self) -> usize { self.header().len() }- pub fn is_empty(&self) -> bool { self.len() == 0 }- pub fn capacity(&self) -> usize { self.header().cap() }- pub unsafe fn set_len(&mut self, len: usize) { self.header_mut().set_len(len) }+ unsafe fn header_mut(&mut self) -> &mut Header {+ &mut *self.ptr()+ }++ pub fn len(&self) -> usize {+ self.header().len()+ }+ pub fn is_empty(&self) -> bool {+ self.len() == 0+ }+ pub fn capacity(&self) -> usize {+ self.header().cap()+ }++ pub unsafe fn set_len(&mut self, len: usize) {+ self.header_mut().set_len(len)+ } pub fn push(&mut self, val: T) { let old_len = self.len();@@ -476,18 +498,20 @@ self.reserve(1); } unsafe {- ptr::write(self.data_raw().offset(old_len as isize), val);+ ptr::write(self.data_raw().add(old_len), val); self.set_len(old_len + 1); } } pub fn pop(&mut self) -> Option<T> { let old_len = self.len();- if old_len == 0 { return None }+ if old_len == 0 {+ return None;+ } unsafe { self.set_len(old_len - 1);- Some(ptr::read(self.data_raw().offset(old_len as isize - 1)))+ Some(ptr::read(self.data_raw().add(old_len - 1))) } }@@ -500,8 +524,8 @@ } unsafe { let ptr = self.data_raw();- ptr::copy(ptr.offset(idx as isize), ptr.offset(idx as isize + 1), old_len - idx);- ptr::write(ptr.offset(idx as isize), elem);+ ptr::copy(ptr.add(idx), ptr.add(idx + 1), old_len - idx);+ ptr::write(ptr.add(idx), elem); self.set_len(old_len + 1); } }@@ -514,9 +538,8 @@ unsafe { self.set_len(old_len - 1); let ptr = self.data_raw();- let val = ptr::read(self.data_raw().offset(idx as isize));- ptr::copy(ptr.offset(idx as isize + 1), ptr.offset(idx as isize),- old_len - idx - 1);+ let val = ptr::read(self.data_raw().add(idx));+ ptr::copy(ptr.add(idx + 1), ptr.add(idx), old_len - idx - 1); val } }@@ -528,9 +551,9 @@ unsafe { let ptr = self.data_raw();- ptr::swap(ptr.offset(idx as isize), ptr.offset(old_len as isize - 1));+ ptr::swap(ptr.add(idx), ptr.add(old_len - 1)); self.set_len(old_len - 1);- ptr::read(ptr.offset(old_len as isize - 1))+ ptr::read(ptr.add(old_len - 1)) } }@@ -552,22 +575,18 @@ ptr::drop_in_place(&mut self[..]); // Don't mutate the empty singleton!- if self.len() != 0 {+ if !self.is_empty() { self.set_len(0); } } } pub fn as_slice(&self) -> &[T] {- unsafe {- slice::from_raw_parts(self.data_raw(), self.len())- }+ unsafe { slice::from_raw_parts(self.data_raw(), self.len()) } } pub fn as_mut_slice(&mut self) -> &mut [T] {- unsafe {- slice::from_raw_parts_mut(self.data_raw(), self.len())- }+ unsafe { slice::from_raw_parts_mut(self.data_raw(), self.len()) } } /// Reserve capacity for at least `additional` more elements to be inserted.@@ -583,12 +602,16 @@ let old_cap = self.capacity(); let min_cap = len.checked_add(additional).expect("capacity overflow"); if min_cap <= old_cap {- return+ return; } // Ensure the new capacity is at least double, to guarantee exponential growth. let double_cap = if old_cap == 0 { // skip to 4 because tiny ThinVecs are dumb; but not if that would cause overflow- if mem::size_of::<T>() > (!0) / 8 { 1 } else { 4 }+ if mem::size_of::<T>() > (!0) / 8 {+ 1+ } else {+ 4+ } } else { old_cap.saturating_mul(2) };@@ -610,7 +633,7 @@ let old_cap = self.capacity(); let min_cap = len.checked_add(additional).expect("capacity overflow"); if min_cap <= old_cap {- return+ return; } // The growth logic can't handle zero-sized types, so we have to exit@@ -662,7 +685,10 @@ /// /// Re-allocates only if `self.capacity() < self.len() + additional`. pub fn reserve_exact(&mut self, additional: usize) {- let new_cap = self.len().checked_add(additional).expect("capacity overflow");+ let new_cap = self+ .len()+ .checked_add(additional)+ .expect("capacity overflow"); let old_cap = self.capacity(); if new_cap > old_cap { unsafe {@@ -701,7 +727,10 @@ /// assert_eq!(vec, [2, 4]); /// # } /// ```- pub fn retain<F>(&mut self, mut f: F) where F: FnMut(&T) -> bool {+ pub fn retain<F>(&mut self, mut f: F)+ where+ F: FnMut(&T) -> bool,+ { let len = self.len(); let mut del = 0; {@@ -736,7 +765,11 @@ /// assert_eq!(vec, [10, 20, 30, 20]); /// # } /// ```- pub fn dedup_by_key<F, K>(&mut self, mut key: F) where F: FnMut(&mut T) -> K, K: PartialEq<K> {+ pub fn dedup_by_key<F, K>(&mut self, mut key: F)+ where+ F: FnMut(&mut T) -> K,+ K: PartialEq<K>,+ { self.dedup_by(|a, b| key(a) == key(b)) }@@ -760,7 +793,10 @@ /// assert_eq!(vec, ["foo", "bar", "baz", "bar"]); /// # } /// ```- pub fn dedup_by<F>(&mut self, mut same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {+ pub fn dedup_by<F>(&mut self, mut same_bucket: F)+ where+ F: FnMut(&mut T, &mut T) -> bool,+ { // See the comments in `Vec::dedup` for a detailed explanation of this code. unsafe { let ln = self.len();@@ -774,11 +810,11 @@ let mut w: usize = 1; while r < ln {- let p_r = p.offset(r as isize);- let p_wm1 = p.offset((w - 1) as isize);+ let p_r = p.add(r);+ let p_wm1 = p.add(w - 1); if !same_bucket(&mut *p_r, &mut *p_wm1) { if r != w {- let p_w = p_wm1.offset(1);+ let p_w = p_wm1.add(1); mem::swap(&mut *p_r, &mut *p_w); } w += 1;@@ -799,9 +835,7 @@ unsafe { let mut new_vec = ThinVec::with_capacity(new_vec_len);- ptr::copy_nonoverlapping(self.data_raw().offset(at as isize),- new_vec.data_raw(),- new_vec_len);+ ptr::copy_nonoverlapping(self.data_raw().add(at), new_vec.data_raw(), new_vec_len); // Don't mutate the empty singleton! if new_vec_len != 0 {@@ -821,7 +855,8 @@ } pub fn drain<R>(&mut self, range: R) -> Drain<T>- where R: RangeBounds<usize>+ where+ R: RangeBounds<usize>, { let len = self.len(); let start = match range.start_bound() {@@ -844,15 +879,13 @@ self.set_len(start); }- let iter = slice::from_raw_parts_mut(- self.data_raw().offset(start as isize),- end - start,- ).iter_mut();+ let iter =+ slice::from_raw_parts_mut(self.data_raw().add(start), end - start).iter_mut(); Drain {- iter: iter,+ iter, vec: self,- end: end,+ end, tail: len - end, } }@@ -860,10 +893,7 @@ unsafe fn deallocate(&mut self) { if self.has_allocation() {- dealloc(- self.ptr() as *mut u8,- layout::<T>(self.capacity()),- )+ dealloc(self.ptr() as *mut u8, layout::<T>(self.capacity())) } }@@ -879,7 +909,9 @@ alloc_size::<T>(new_cap), ) as *mut Header;- if ptr.is_null() { handle_alloc_error(layout::<T>(new_cap)) }+ if ptr.is_null() {+ handle_alloc_error(layout::<T>(new_cap))+ } (*ptr).set_cap(new_cap); self.ptr = NonNull::new_unchecked(ptr); } else {@@ -898,10 +930,13 @@ // by leaving behind a valid empty instance. let len = self.len(); if cfg!(feature = "gecko-ffi") && len > 0 {- new_header.as_mut().data::<T>().copy_from_nonoverlapping(self.data_raw(), len);+ new_header+ .as_mut()+ .data::<T>()+ .copy_from_nonoverlapping(self.data_raw(), len); self.set_len(0); }- + self.ptr = new_header; } }@@ -910,8 +945,8 @@ #[inline] fn has_allocation(&self) -> bool { unsafe {- self.ptr.as_ptr() as *const Header != &EMPTY_HEADER &&- !self.ptr.as_ref().uses_stack_allocated_buffer()+ self.ptr.as_ptr() as *const Header != &EMPTY_HEADER+ && !self.ptr.as_ref().uses_stack_allocated_buffer() } }@@ -991,7 +1026,7 @@ impl<T> Drop for ThinVec<T> { fn drop(&mut self) { unsafe {- ptr::drop_in_place(&mut self [..]);+ ptr::drop_in_place(&mut self[..]); self.deallocate(); } }@@ -1030,7 +1065,10 @@ } impl<T> Extend<T> for ThinVec<T> {- fn extend<I>(&mut self, iter: I) where I: IntoIterator<Item=T> {+ fn extend<I>(&mut self, iter: I)+ where+ I: IntoIterator<Item = T>,+ { let iter = iter.into_iter(); self.reserve(iter.size_hint().0); for x in iter {@@ -1045,52 +1083,76 @@ } }-impl<T> Hash for ThinVec<T> where T: Hash {- fn hash<H>(&self, state: &mut H) where H: Hasher {+impl<T> Hash for ThinVec<T>+where+ T: Hash,+{+ fn hash<H>(&self, state: &mut H)+ where+ H: Hasher,+ { self[..].hash(state); } }-impl<T> PartialOrd for ThinVec<T> where T: PartialOrd {+impl<T> PartialOrd for ThinVec<T>+where+ T: PartialOrd,+{ #[inline] fn partial_cmp(&self, other: &ThinVec<T>) -> Option<Ordering> { self[..].partial_cmp(&other[..]) } }-impl<T> Ord for ThinVec<T> where T: Ord {+impl<T> Ord for ThinVec<T>+where+ T: Ord,+{ #[inline] fn cmp(&self, other: &ThinVec<T>) -> Ordering { self[..].cmp(&other[..]) } }-impl<A, B> PartialEq<ThinVec<B>> for ThinVec<A> where A: PartialEq<B> {+impl<A, B> PartialEq<ThinVec<B>> for ThinVec<A>+where+ A: PartialEq<B>,+{ #[inline]- fn eq(&self, other: &ThinVec<B>) -> bool { self[..] == other[..] }+ fn eq(&self, other: &ThinVec<B>) -> bool {+ self[..] == other[..]+ }+}++impl<A, B> PartialEq<Vec<B>> for ThinVec<A>+where+ A: PartialEq<B>,+{ #[inline]- fn ne(&self, other: &ThinVec<B>) -> bool { self[..] != other[..] }-}--impl<A, B> PartialEq<Vec<B>> for ThinVec<A> where A: PartialEq<B> {+ fn eq(&self, other: &Vec<B>) -> bool {+ self[..] == other[..]+ }+}++impl<A, B> PartialEq<[B]> for ThinVec<A>+where+ A: PartialEq<B>,+{ #[inline]- fn eq(&self, other: &Vec<B>) -> bool { self[..] == other[..] }+ fn eq(&self, other: &[B]) -> bool {+ self[..] == other[..]+ }+}++impl<'a, A, B> PartialEq<&'a [B]> for ThinVec<A>+where+ A: PartialEq<B>,+{ #[inline]- fn ne(&self, other: &Vec<B>) -> bool { self[..] != other[..] }-}--impl<A, B> PartialEq<[B]> for ThinVec<A> where A: PartialEq<B> {- #[inline]- fn eq(&self, other: &[B]) -> bool { self[..] == other[..] }- #[inline]- fn ne(&self, other: &[B]) -> bool { self[..] != other[..] }-}--impl<'a, A, B> PartialEq<&'a [B]> for ThinVec<A> where A: PartialEq<B> {- #[inline]- fn eq(&self, other: &&'a [B]) -> bool { self[..] == other[..] }- #[inline]- fn ne(&self, other: &&'a [B]) -> bool { self[..] != other[..] }+ fn eq(&self, other: &&'a [B]) -> bool {+ self[..] == other[..]+ } } macro_rules! array_impls {@@ -1098,15 +1160,11 @@ impl<A, B> PartialEq<[B; $N]> for ThinVec<A> where A: PartialEq<B> { #[inline] fn eq(&self, other: &[B; $N]) -> bool { self[..] == other[..] }- #[inline]- fn ne(&self, other: &[B; $N]) -> bool { self[..] != other[..] } } impl<'a, A, B> PartialEq<&'a [B; $N]> for ThinVec<A> where A: PartialEq<B> { #[inline] fn eq(&self, other: &&'a [B; $N]) -> bool { self[..] == other[..] }- #[inline]- fn ne(&self, other: &&'a [B; $N]) -> bool { self[..] != other[..] } } )*} }@@ -1125,7 +1183,10 @@ type IntoIter = IntoIter<T>; fn into_iter(self) -> IntoIter<T> {- IntoIter { vec: self, start: 0 }+ IntoIter {+ vec: self,+ start: 0,+ } } }@@ -1147,7 +1208,10 @@ } }-impl<T> Clone for ThinVec<T> where T: Clone {+impl<T> Clone for ThinVec<T>+where+ T: Clone,+{ fn clone(&self) -> ThinVec<T> { let mut new_vec = ThinVec::with_capacity(self.len()); new_vec.extend(self.iter().cloned());@@ -1191,7 +1255,7 @@ unsafe { let old_start = self.start; self.start += 1;- Some(ptr::read(self.vec.data_raw().offset(old_start as isize)))+ Some(ptr::read(self.vec.data_raw().add(old_start))) } } }@@ -1231,9 +1295,7 @@ impl<'a, T> Iterator for Drain<'a, T> { type Item = T; fn next(&mut self) -> Option<T> {- self.iter.next().map(|x| unsafe {- ptr::read(x)- })+ self.iter.next().map(|x| unsafe { ptr::read(x) }) } fn size_hint(&self) -> (usize, Option<usize>) {@@ -1243,9 +1305,7 @@ impl<'a, T> DoubleEndedIterator for Drain<'a, T> { fn next_back(&mut self) -> Option<T> {- self.iter.next_back().map(|x| unsafe {- ptr::read(x)- })+ self.iter.next_back().map(|x| unsafe { ptr::read(x) }) } }@@ -1254,7 +1314,7 @@ impl<'a, T> Drop for Drain<'a, T> { fn drop(&mut self) { // Consume the rest of the iterator.- while let Some(_) = self.next() {}+ for _ in self.by_ref() {} // Move the tail over the drained items, and update the length. unsafe {@@ -1263,8 +1323,8 @@ // Don't mutate the empty singleton! if vec.has_allocation() { let old_len = vec.len();- let start = vec.data_raw().offset(old_len as isize);- let end = vec.data_raw().offset(self.end as isize);+ let start = vec.data_raw().add(old_len);+ let end = vec.data_raw().add(self.end); ptr::copy(end, start, self.tail); vec.set_len(old_len + self.tail); }@@ -1289,7 +1349,9 @@ } #[inline]- fn flush(&mut self) -> io::Result<()> { Ok(()) }+ fn flush(&mut self) -> io::Result<()> {+ Ok(())+ } } // TODO: a million Index impls@@ -1315,7 +1377,7 @@ fn test_partial_eq() { assert_eq!(thin_vec![0], thin_vec![0]); assert_ne!(thin_vec![0], thin_vec![1]);- assert_eq!(thin_vec![1,2,3], vec![1,2,3]);+ assert_eq!(thin_vec![1, 2, 3], vec![1, 2, 3]); } #[test]@@ -1379,38 +1441,37 @@ #[test] fn test_drain_range() { let mut v = thin_vec![1, 2, 3, 4, 5];- for _ in v.drain(4..) {- }+ for _ in v.drain(4..) {} assert_eq!(v, &[1, 2, 3, 4]); let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();- for _ in v.drain(1..4) {- }+ for _ in v.drain(1..4) {} assert_eq!(v, &[1.to_string(), 5.to_string()]); let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();- for _ in v.drain(1..4).rev() {- }+ for _ in v.drain(1..4).rev() {} assert_eq!(v, &[1.to_string(), 5.to_string()]); let mut v: ThinVec<_> = thin_vec![(); 5];- for _ in v.drain(1..4).rev() {- }+ for _ in v.drain(1..4).rev() {} assert_eq!(v, &[(), ()]); } #[test] fn test_drain_max_vec_size() { let mut v = ThinVec::<()>::with_capacity(MAX_CAP);- unsafe { v.set_len(MAX_CAP); }- for _ in v.drain(MAX_CAP - 1..) {- }+ unsafe {+ v.set_len(MAX_CAP);+ }+ for _ in v.drain(MAX_CAP - 1..) {} assert_eq!(v.len(), MAX_CAP - 1); } } #[cfg(test)] mod std_tests {+ #![allow(clippy::reversed_empty_ranges)]+ use super::*; use std::mem::size_of; use std::usize;@@ -1443,8 +1504,12 @@ x: ThinVec::new(), y: ThinVec::new(), };- tv.x.push(DropCounter { count: &mut count_x });- tv.y.push(DropCounter { count: &mut count_y });+ tv.x.push(DropCounter {+ count: &mut count_x,+ });+ tv.y.push(DropCounter {+ count: &mut count_y,+ }); // If ThinVec had a drop flag, here is where it would be zeroed. // Instead, it should rely on its internal state to prevent@@ -1457,7 +1522,6 @@ assert_eq!(count_x, 1); assert_eq!(count_y, 1); }- #[test] fn test_reserve() {@@ -1519,29 +1583,31 @@ let mut count_x = 0; { let mut x = ThinVec::new();- let y = thin_vec![DropCounter { count: &mut count_x }];+ let y = thin_vec![DropCounter {+ count: &mut count_x+ }]; x.extend(y); } assert_eq!(count_x, 1); }-/* TODO: implement extend for Iter<&Copy>- #[test]- fn test_extend_ref() {- let mut v = thin_vec![1, 2];- v.extend(&[3, 4, 5]);-- assert_eq!(v.len(), 5);- assert_eq!(v, [1, 2, 3, 4, 5]);-- let w = thin_vec![6, 7];- v.extend(&w);-- assert_eq!(v.len(), 7);- assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]);- }-*/+ /* TODO: implement extend for Iter<&Copy>+ #[test]+ fn test_extend_ref() {+ let mut v = thin_vec![1, 2];+ v.extend(&[3, 4, 5]);++ assert_eq!(v.len(), 5);+ assert_eq!(v, [1, 2, 3, 4, 5]);++ let w = thin_vec![6, 7];+ v.extend(&w);++ assert_eq!(v.len(), 7);+ assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]);+ }+ */ #[test] fn test_slice_from_mut() {@@ -1578,7 +1644,7 @@ let (left, right) = values.split_at_mut(2); { let left: &[_] = left;- assert!(&left[..left.len()] == &[1, 2]);+ assert!(left[..left.len()] == [1, 2]); } for p in left { *p += 1;@@ -1586,7 +1652,7 @@ { let right: &[_] = right;- assert!(&right[..right.len()] == &[3, 4, 5]);+ assert!(right[..right.len()] == [3, 4, 5]); } for p in right { *p += 2;@@ -1680,7 +1746,12 @@ assert_eq!(vec, ["foo", "bar", "baz", "bar"]); let mut vec = thin_vec![("foo", 1), ("foo", 2), ("bar", 3), ("bar", 4), ("bar", 5)];- vec.dedup_by(|a, b| a.0 == b.0 && { b.1 += a.1; true });+ vec.dedup_by(|a, b| {+ a.0 == b.0 && {+ b.1 += a.1;+ true+ }+ }); assert_eq!(vec, [("foo", 3), ("bar", 12)]); }@@ -1732,14 +1803,22 @@ #[test] fn test_partition() {- assert_eq!(thin_vec![].into_iter().partition(|x: &i32| *x < 3),- (thin_vec![], thin_vec![]));- assert_eq!(thin_vec![1, 2, 3].into_iter().partition(|x| *x < 4),- (thin_vec![1, 2, 3], thin_vec![]));- assert_eq!(thin_vec![1, 2, 3].into_iter().partition(|x| *x < 2),- (thin_vec![1], thin_vec![2, 3]));- assert_eq!(thin_vec![1, 2, 3].into_iter().partition(|x| *x < 0),- (thin_vec![], thin_vec![1, 2, 3]));+ assert_eq!(+ thin_vec![].into_iter().partition(|x: &i32| *x < 3),+ (thin_vec![], thin_vec![])+ );+ assert_eq!(+ thin_vec![1, 2, 3].into_iter().partition(|x| *x < 4),+ (thin_vec![1, 2, 3], thin_vec![])+ );+ assert_eq!(+ thin_vec![1, 2, 3].into_iter().partition(|x| *x < 2),+ (thin_vec![1], thin_vec![2, 3])+ );+ assert_eq!(+ thin_vec![1, 2, 3].into_iter().partition(|x| *x < 0),+ (thin_vec![], thin_vec![1, 2, 3])+ ); } #[test]@@ -1807,35 +1886,35 @@ #[should_panic] fn test_slice_out_of_bounds_1() { let x = thin_vec![1, 2, 3, 4, 5];- &x[!0..];+ let _ = &x[!0..]; } #[test] #[should_panic] fn test_slice_out_of_bounds_2() { let x = thin_vec![1, 2, 3, 4, 5];- &x[..6];+ let _ = &x[..6]; } #[test] #[should_panic] fn test_slice_out_of_bounds_3() { let x = thin_vec![1, 2, 3, 4, 5];- &x[!0..4];+ let _ = &x[!0..4]; } #[test] #[should_panic] fn test_slice_out_of_bounds_4() { let x = thin_vec![1, 2, 3, 4, 5];- &x[1..6];+ let _ = &x[1..6]; } #[test] #[should_panic] fn test_slice_out_of_bounds_5() { let x = thin_vec![1, 2, 3, 4, 5];- &x[3..2];+ let _ = &x[3..2]; } #[test]@@ -1918,51 +1997,42 @@ #[test] fn test_drain_range() { let mut v = thin_vec![1, 2, 3, 4, 5];- for _ in v.drain(4..) {- }+ for _ in v.drain(4..) {} assert_eq!(v, &[1, 2, 3, 4]); let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();- for _ in v.drain(1..4) {- }+ for _ in v.drain(1..4) {} assert_eq!(v, &[1.to_string(), 5.to_string()]); let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();- for _ in v.drain(1..4).rev() {- }+ for _ in v.drain(1..4).rev() {} assert_eq!(v, &[1.to_string(), 5.to_string()]); let mut v: ThinVec<_> = thin_vec![(); 5];- for _ in v.drain(1..4).rev() {- }+ for _ in v.drain(1..4).rev() {} assert_eq!(v, &[(), ()]); } #[test] fn test_drain_inclusive_range() { let mut v = thin_vec!['a', 'b', 'c', 'd', 'e'];- for _ in v.drain(1..=3) {- }+ for _ in v.drain(1..=3) {} assert_eq!(v, &['a', 'e']); let mut v: ThinVec<_> = (0..=5).map(|x| x.to_string()).collect();- for _ in v.drain(1..=5) {- }+ for _ in v.drain(1..=5) {} assert_eq!(v, &["0".to_string()]); let mut v: ThinVec<String> = (0..=5).map(|x| x.to_string()).collect();- for _ in v.drain(0..=5) {- }+ for _ in v.drain(0..=5) {} assert_eq!(v, ThinVec::<String>::new()); let mut v: ThinVec<_> = (0..=5).map(|x| x.to_string()).collect();- for _ in v.drain(0..=3) {- }+ for _ in v.drain(0..=3) {} assert_eq!(v, &["4".to_string(), "5".to_string()]); let mut v: ThinVec<_> = (0..=1).map(|x| x.to_string()).collect();- for _ in v.drain(..=0) {- }+ for _ in v.drain(..=0) {} assert_eq!(v, &["1".to_string()]); }@@ -1970,15 +2040,17 @@ #[cfg(not(feature = "gecko-ffi"))] fn test_drain_max_vec_size() { let mut v = ThinVec::<()>::with_capacity(usize::max_value());
After analyzing the provided code diff, I found one security-related fix: 1. Vulnerability Existed: yes Memory Alignment Issue [third_party/rust/thin-vec/src/lib.rs] [Lines 269-280] Old Code: ```rust unsafe { if padding > 0 && self.len() == 0 { // The empty header isn't well-aligned, just make an aligned one up NonNull::dangling().as_ptr() } else { ptr.offset(header_size as isize) as *mut T } } ``` Fixed Code: ```rust unsafe { if padding > 0 && self.cap() == 0 { // The empty header isn't well-aligned, just make an aligned one up NonNull::dangling().as_ptr() } else { // This could technically result in overflow, but padding would have to be absurdly large for this to occur. ptr.add(header_size + padding) as *mut T } } ``` The changes address two issues: 1. Changed the condition from checking `len()` to `cap()` when determining if the header is empty, which is more correct for alignment purposes 2. Replaced potentially unsafe `offset()` with safer `add()` for pointer arithmetic and added a comment about potential overflow The fix ensures proper memory alignment handling in the ThinVec implementation, which is important for security when dealing with FFI and memory operations. The change from `len()` to `cap()` is particularly important because an empty vector might still have capacity allocated, and we need to consider that for alignment purposes. Additionally, there are some other improvements in the diff that enhance safety: - Added `Sync` and `Send` implementations for ThinVec when the contained type supports it - Improved pointer arithmetic safety - Better handling of empty vectors - Added more safety comments However, these other changes don't appear to directly fix security vulnerabilities, but rather improve general code safety and correctness.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/third_party/rust/rust_decimal/src/serde.rs+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/third_party/rust/rust_decimal/src/serde.rs@@ -4,6 +4,132 @@ use num_traits::FromPrimitive; use serde::{self, de::Unexpected};+/// Serialize Decimals as arbitrary precision numbers in JSON.+///+/// ```+/// # use serde::{Serialize, Deserialize};+/// # use rust_decimal::Decimal;+/// # use std::str::FromStr;+///+/// #[derive(Serialize, Deserialize)]+/// pub struct ArbitraryExample {+/// #[serde(with = "rust_decimal::serde::arbitrary_precision")]+/// value: Decimal,+/// }+///+/// let value = ArbitraryExample { value: Decimal::from_str("123.400").unwrap() };+/// assert_eq!(+/// &serde_json::to_string(&value).unwrap(),+/// r#"{"value":123.400}"#+/// );+/// ```+#[cfg(feature = "serde-with-arbitrary-precision")]+pub mod arbitrary_precision {+ use super::*;+ use serde::Serialize;++ pub fn deserialize<'de, D>(deserializer: D) -> Result<Decimal, D::Error>+ where+ D: serde::de::Deserializer<'de>,+ {+ deserializer.deserialize_any(DecimalVisitor)+ }++ pub fn serialize<S>(value: &Decimal, serializer: S) -> Result<S::Ok, S::Error>+ where+ S: serde::Serializer,+ {+ serde_json::Number::from_str(&value.to_string())+ .map_err(serde::ser::Error::custom)?+ .serialize(serializer)+ }+}++/// Serialize Decimals as floats in JSON.+///+/// ```+/// # use serde::{Serialize, Deserialize};+/// # use rust_decimal::Decimal;+/// # use std::str::FromStr;+///+/// #[derive(Serialize, Deserialize)]+/// pub struct FloatExample {+/// #[serde(with = "rust_decimal::serde::float")]+/// value: Decimal,+/// }+///+/// let value = FloatExample { value: Decimal::from_str("123.400").unwrap() };+/// assert_eq!(+/// &serde_json::to_string(&value).unwrap(),+/// r#"{"value":123.4}"#+/// );+/// ```+#[cfg(feature = "serde-with-float")]+pub mod float {+ use super::*;+ use serde::Serialize;++ pub fn deserialize<'de, D>(deserializer: D) -> Result<Decimal, D::Error>+ where+ D: serde::de::Deserializer<'de>,+ {+ deserializer.deserialize_any(DecimalVisitor)+ }++ pub fn serialize<S>(value: &Decimal, serializer: S) -> Result<S::Ok, S::Error>+ where+ S: serde::Serializer,+ {+ use num_traits::ToPrimitive;+ value.to_f64().unwrap().serialize(serializer)+ }+}++/// Serialize Decimals as floats in JSON.+///+/// ```+/// # use serde::{Serialize, Deserialize};+/// # use rust_decimal::Decimal;+/// # use std::str::FromStr;+///+/// #[derive(Serialize, Deserialize)]+/// pub struct StringExample {+/// #[serde(with = "rust_decimal::serde::str")]+/// value: Decimal,+/// }+///+/// let value = StringExample { value: Decimal::from_str("123.400").unwrap() };+/// assert_eq!(+/// &serde_json::to_string(&value).unwrap(),+/// r#"{"value":"123.400"}"#+/// );+/// ```+#[cfg(feature = "serde-with-str")]+pub mod str {+ use crate::constants::MAX_STR_BUFFER_SIZE;++ use super::*;+ use arrayvec::ArrayString;+ use core::convert::TryFrom;+ use serde::{ser::Error, Serialize};++ pub fn deserialize<'de, D>(deserializer: D) -> Result<Decimal, D::Error>+ where+ D: serde::de::Deserializer<'de>,+ {+ deserializer.deserialize_any(DecimalVisitor)+ }++ pub fn serialize<S>(value: &Decimal, serializer: S) -> Result<S::Ok, S::Error>+ where+ S: serde::Serializer,+ {+ ArrayString::<MAX_STR_BUFFER_SIZE>::try_from(format_args!("{}", value))+ .map_err(S::Error::custom)?+ .serialize(serializer)+ }+}+ #[cfg(not(feature = "serde-str"))] impl<'de> serde::Deserialize<'de> for Decimal { fn deserialize<D>(deserializer: D) -> Result<Decimal, D::Error>@@ -35,7 +161,7 @@ } // It's a shame this needs to be redefined for this feature and not able to be referenced directly-#[cfg(feature = "serde-arbitrary-precision")]+#[cfg(feature = "serde-with-arbitrary-precision")] const DECIMAL_KEY_TOKEN: &str = "$serde_json::private::Number"; struct DecimalVisitor;@@ -83,7 +209,7 @@ .map_err(|_| E::invalid_value(Unexpected::Str(value), &self)) }- #[cfg(feature = "serde-arbitrary-precision")]+ #[cfg(feature = "serde-with-arbitrary-precision")] fn visit_map<A>(self, map: A) -> Result<Decimal, A::Error> where A: serde::de::MapAccess<'de>,@@ -98,10 +224,10 @@ } }-#[cfg(feature = "serde-arbitrary-precision")]+#[cfg(feature = "serde-with-arbitrary-precision")] struct DecimalKey;-#[cfg(feature = "serde-arbitrary-precision")]+#[cfg(feature = "serde-with-arbitrary-precision")] impl<'de> serde::de::Deserialize<'de> for DecimalKey { fn deserialize<D>(deserializer: D) -> Result<DecimalKey, D::Error> where@@ -133,12 +259,12 @@ } }-#[cfg(feature = "serde-arbitrary-precision")]+#[cfg(feature = "serde-with-arbitrary-precision")] pub struct DecimalFromString { pub value: Decimal, }-#[cfg(feature = "serde-arbitrary-precision")]+#[cfg(feature = "serde-with-arbitrary-precision")] impl<'de> serde::de::Deserialize<'de> for DecimalFromString { fn deserialize<D>(deserializer: D) -> Result<DecimalFromString, D::Error> where@@ -373,4 +499,49 @@ let des: Foo = bincode::deserialize(&ser).unwrap(); assert_eq!(des.value, s.value); }-}++ #[test]+ #[cfg(feature = "serde-with-arbitrary-precision")]+ fn with_arbitrary_precision() {+ #[derive(Serialize, Deserialize)]+ pub struct ArbitraryExample {+ #[serde(with = "crate::serde::arbitrary_precision")]+ value: Decimal,+ }++ let value = ArbitraryExample {+ value: Decimal::from_str("123.400").unwrap(),+ };+ assert_eq!(&serde_json::to_string(&value).unwrap(), r#"{"value":123.400}"#);+ }++ #[test]+ #[cfg(feature = "serde-with-float")]+ fn with_float() {+ #[derive(Serialize, Deserialize)]+ pub struct FloatExample {+ #[serde(with = "crate::serde::float")]+ value: Decimal,+ }++ let value = FloatExample {+ value: Decimal::from_str("123.400").unwrap(),+ };+ assert_eq!(&serde_json::to_string(&value).unwrap(), r#"{"value":123.4}"#);+ }++ #[test]+ #[cfg(feature = "serde-with-str")]+ fn with_str() {+ #[derive(Serialize, Deserialize)]+ pub struct StringExample {+ #[serde(with = "crate::serde::str")]+ value: Decimal,+ }++ let value = StringExample {+ value: Decimal::from_str("123.400").unwrap(),+ };+ assert_eq!(&serde_json::to_string(&value).unwrap(), r#"{"value":"123.400"}"#);+ }+}
After analyzing the provided code diff, I don't see any security vulnerabilities being fixed. The changes appear to be feature additions and code reorganization rather than security patches. Here's the analysis: Vulnerability Existed: no No security vulnerabilities found in the diff. The changes include: 1. Added new serialization modules (arbitrary_precision, float, str) 2. Renamed feature flags from "serde-arbitrary-precision" to "serde-with-arbitrary-precision" 3. Added corresponding test cases 4. No security-related fixes or vulnerability mitigations were identified The changes are primarily about adding new serialization options and improving code organization, not addressing security issues. The modifications include: - New serialization formats for Decimal type - Feature flag consistency updates - Additional test coverage - Documentation improvements No CVE or known vulnerability patterns were identified in the changes. The modifications appear to be feature enhancements rather than security fixes.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/testing/web-platform/tests/html/canvas/offscreen/path-objects/2d.path.roundrect.4.radii.2.dompoint.html+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/testing/web-platform/tests/html/canvas/offscreen/path-objects/2d.path.roundrect.4.radii.2.dompoint.html@@ -17,8 +17,8 @@ }); t.step(function() {-var offscreenCanvas = new OffscreenCanvas(100, 50);-var ctx = offscreenCanvas.getContext('2d');+var canvas = new OffscreenCanvas(100, 50);+var ctx = canvas.getContext('2d'); ctx.fillStyle = '#f00'; ctx.fillRect(0, 0, 100, 50);@@ -27,15 +27,15 @@ ctx.fill(); // top-right corner-_assertPixel(offscreenCanvas, 79,1, 255,0,0,255, "79,1", "255,0,0,255");-_assertPixel(offscreenCanvas, 58,1, 0,255,0,255, "58,1", "0,255,0,255");-_assertPixel(offscreenCanvas, 98,10, 255,0,0,255, "98,10", "255,0,0,255");-_assertPixel(offscreenCanvas, 98,21, 0,255,0,255, "98,21", "0,255,0,255");+_assertPixel(canvas, 79,1, 255,0,0,255, "79,1", "255,0,0,255");+_assertPixel(canvas, 58,1, 0,255,0,255, "58,1", "0,255,0,255");+_assertPixel(canvas, 98,10, 255,0,0,255, "98,10", "255,0,0,255");+_assertPixel(canvas, 98,21, 0,255,0,255, "98,21", "0,255,0,255"); // other corners-_assertPixel(offscreenCanvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");-_assertPixel(offscreenCanvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");-_assertPixel(offscreenCanvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255"); t.done(); });
After analyzing the provided code diff, here's the security assessment: 1. Vulnerability Existed: no No security vulnerability found [File] [Lines 17-27] [Old Code] var offscreenCanvas = new OffscreenCanvas(100, 50); var ctx = offscreenCanvas.getContext('2d'); _assertPixel(offscreenCanvas, 79,1, 255,0,0,255, "79,1", "255,0,0,255"); [Fixed Code] var canvas = new OffscreenCanvas(100, 50); var ctx = canvas.getContext('2d'); _assertPixel(canvas, 79,1, 255,0,0,255, "79,1", "255,0,0,255"); The changes appear to be purely cosmetic/refactoring, renaming the variable from `offscreenCanvas` to `canvas` for consistency. There are no security-related changes in this diff. The functionality remains identical, just with a different variable name. No security vulnerabilities were fixed or introduced by these changes.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/testing/web-platform/tests/speculation-rules/prerender/cookies.html+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/testing/web-platform/tests/speculation-rules/prerender/cookies.html@@ -3,34 +3,31 @@ <meta name="timeout" content="long"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>+<script src="/common/utils.js"></script> <script src="resources/utils.js"></script>+<script src="/cookie-store/resources/cookie-test-helpers.js"></script> <body> <script> setup(() => assertSpeculationRulesIsSupported());-promise_test(async t => {- const bc = new BroadcastChannel('prerender-channel');-- const gotMessage = new Promise(resolve => {- bc.addEventListener('message', e => {- resolve(e.data);- }, {- once: true- });- });-+cookie_test(async t => {+ const {exec} = await create_prerendered_page(t); const initiator_cookie = 'initiator_cookie=exist'; const prerender_cookie = 'prerender_cookie=exist'; document.cookie = initiator_cookie;+ const result = await exec(() => {+ const result = document.cookie;+ prerender_log(result);+ document.cookie = "prerender_cookie=exist;path=/;";+ return result;+ });- // Start prerendering a page that attempts to access cookies.- startPrerendering(`resources/cookies-access.html`);- const result = await gotMessage; assert_equals( result, initiator_cookie, 'prerendering page should be able to read from document cookies.');+ assert_equals( document.cookie, initiator_cookie + '; ' + prerender_cookie, 'prerendering page should be able to write to document cookies');
Analyzing the provided code diff for security fixes: 1. Vulnerability Existed: not sure [Potential Cookie Manipulation Vulnerability] [testing/web-platform/tests/speculation-rules/prerender/cookies.html] [Lines 3-34] [Old Code] ```javascript promise_test(async t => { const bc = new BroadcastChannel('prerender-channel'); const gotMessage = new Promise(resolve => { bc.addEventListener('message', e => { resolve(e.data); }, { once: true }); }); const initiator_cookie = 'initiator_cookie=exist'; const prerender_cookie = 'prerender_cookie=exist'; document.cookie = initiator_cookie; startPrerendering(`resources/cookies-access.html`); const result = await gotMessage; assert_equals( result, initiator_cookie, 'prerendering page should be able to read from document cookies.'); assert_equals( document.cookie, initiator_cookie + '; ' + prerender_cookie, 'prerendering page should be able to write to document cookies'); ``` [Fixed Code] ```javascript cookie_test(async t => { const {exec} = await create_prerendered_page(t); const initiator_cookie = 'initiator_cookie=exist'; const prerender_cookie = 'prerender_cookie=exist'; document.cookie = initiator_cookie; const result = await exec(() => { const result = document.cookie; prerender_log(result); document.cookie = "prerender_cookie=exist;path=/;"; return result; }); assert_equals( result, initiator_cookie, 'prerendering page should be able to read from document cookies.'); assert_equals( document.cookie, initiator_cookie + '; ' + prerender_cookie, 'prerendering page should be able to write to document cookies'); ``` Additional Details: The test was modified to use a more controlled cookie testing framework (`cookie_test` and `create_prerendered_page`). The old version used BroadcastChannel which might have been less secure for cookie testing. The new version explicitly sets cookie attributes (path=/), which is more secure. However, I'm not certain if the old version had an actual vulnerability or if this was just a test improvement. 2. Vulnerability Existed: no [Test Improvement - Cookie Handling] [testing/web-platform/tests/speculation-rules/prerender/cookies.html] [Lines 3-34] [Old Code] (Same as above) [Fixed Code] (Same as above) Additional Details: The changes appear to be primarily test improvements rather than security fixes. The new version uses dedicated cookie testing utilities and provides more explicit cookie handling, but doesn't appear to fix a specific vulnerability. The added script includes (`/common/utils.js` and `/cookie-store/resources/cookie-test-helpers.js`) suggest better test infrastructure rather than security fixes. Note: The diff shows significant changes in the testing approach but doesn't clearly indicate any security vulnerabilities being fixed. The changes seem focused on improving test reliability and maintainability rather than addressing security issues.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/testing/web-platform/tests/html/canvas/offscreen/path-objects/2d.path.stroke.prune.corner.html+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/testing/web-platform/tests/html/canvas/offscreen/path-objects/2d.path.stroke.prune.corner.html@@ -17,8 +17,8 @@ }); t.step(function() {-var offscreenCanvas = new OffscreenCanvas(100, 50);-var ctx = offscreenCanvas.getContext('2d');+var canvas = new OffscreenCanvas(100, 50);+var ctx = canvas.getContext('2d'); ctx.fillStyle = '#0f0'; ctx.fillRect(0, 0, 100, 50);@@ -33,7 +33,7 @@ ctx.lineTo(-100, 200); ctx.lineTo(-100, 1000); ctx.stroke();-_assertPixel(offscreenCanvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255"); t.done(); });
After analyzing the provided code diff, I don't see any security vulnerabilities being fixed. The changes appear to be purely cosmetic/refactoring changes (variable renaming) rather than security-related fixes. Vulnerability Existed: no [No security vulnerability found] [testing/web-platform/tests/html/canvas/offscreen/path-objects/2d.path.stroke.prune.corner.html] [Lines 17-33] [Old Code] var offscreenCanvas = new OffscreenCanvas(100, 50); var ctx = offscreenCanvas.getContext('2d'); ... _assertPixel(offscreenCanvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255"); [Fixed Code] var canvas = new OffscreenCanvas(100, 50); var ctx = canvas.getContext('2d'); ... _assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255"); The changes simply rename the variable `offscreenCanvas` to `canvas` throughout the file, which doesn't appear to address any security issues. The functionality remains the same.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/testing/web-platform/tests/html/dom/elements/the-innertext-and-outertext-properties/outertext-setter.html+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/testing/web-platform/tests/html/dom/elements/the-innertext-and-outertext-properties/outertext-setter.html@@ -8,6 +8,7 @@ <li><span id="testReplaceFollowing">A</span> B</li> <li>A <span id="testReplaceBoth">B</span> C</li> <li><span id="testRemove">Testing</span> removing node using outerText.</li>+ <li><span id="testNewlines">Replace this child with lots of newlines</span></li> </ul> <div id="container"></div>@@ -61,6 +62,45 @@ assert_equals(container.childNodes[1].data, "BReplacedD"); assert_equals(container.childNodes[2].data, "E"); }, "Only merges with the previous and following text nodes, does not completely normalize");++test(t => {+ const container = document.getElementById("container");+ t.add_cleanup(() => { container.textContent = ""; });++ container.append(document.createElement("span"));+ const node = container.childNodes[0];+ node.outerText = "";++ assert_equals(container.childNodes.length, 1, "Creates text node for the empty string");+ assert_equals(container.childNodes[0].data, "");+}, "Empty string");++test(t => {+ const container = document.getElementById("container");+ t.add_cleanup(() => { container.textContent = ""; });++ container.append("1", "2", document.createElement("span"), "3", "4");+ const node = container.childNodes[2];+ node.outerText = "";++ assert_equals(container.childNodes.length, 3, "It got merged with the previous and following text node");+ assert_equals(container.childNodes[0].data, "1");+ assert_equals(container.childNodes[1].data, "23");+ assert_equals(container.childNodes[2].data, "4");+}, "Empty string with surrounding text nodes");++test(t => {+ const node = document.getElementById("testNewlines");+ const parent = node.parentNode;++ node.outerText = "\n\r\n\r";++ assert_equals(parent.innerHTML, "<br><br><br>");+ assert_equals(parent.childNodes.length, 3);+ assert_equals(parent.childNodes[0].localName, "br", "node 1");+ assert_equals(parent.childNodes[1].localName, "br", "node 2");+ assert_equals(parent.childNodes[2].localName, "br", "node 3");+}, "Setting outerText to a bunch of newlines creates a bunch of <br>s with no text nodes"); test(() => { const node = document.getElementById("testRemove");
Based on the provided diff, I'll analyze it for security vulnerabilities: 1. Vulnerability Existed: no No security vulnerabilities were fixed in this diff. The changes appear to be test case additions and improvements to the test suite for the outerText property functionality. The main changes include: - Added a new test case for handling empty strings - Added a test case for empty strings with surrounding text nodes - Added a test case for handling newlines in outerText 2. Vulnerability Existed: not sure While no obvious security vulnerabilities were fixed, there might be underlying concerns about: HTML Injection [File] [Lines 61-62] The test case for newlines could potentially be related to HTML injection prevention, but this appears to be a test case addition rather than a security fix. 3. Vulnerability Existed: no The changes are focused on testing behavior of the outerText property, particularly edge cases like empty strings and newline handling. These appear to be test improvements rather than security fixes. The diff primarily adds new test cases to verify correct behavior of the outerText setter property, including: - Empty string handling - Text node merging behavior - Newline to <br> conversion - Node removal functionality No actual security vulnerabilities were identified in the changes.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/browser/components/preferences/tests/browser_moreFromMozilla.js+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/browser/components/preferences/tests/browser_moreFromMozilla.js@@ -2,25 +2,97 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict";--const { ContentTaskUtils } = ChromeUtils.import(- "resource://testing-common/ContentTaskUtils.jsm"-); let { TelemetryTestUtils } = ChromeUtils.import( "resource://testing-common/TelemetryTestUtils.jsm" );-let { Region } = ChromeUtils.import("resource://gre/modules/Region.jsm");--const initialHomeRegion = Region._home;-const intialCurrentRegion = Region._current;--// Helper to run tests for specific regions-async function setupRegions(home, current) {- Region._setHomeRegion(home || "");- Region._setCurrentRegion(current || "");-}+add_task(async function testDefaultUIWithoutTemplatePref() {+ await openPreferencesViaOpenPreferencesAPI("paneGeneral", {+ leaveOpen: true,+ });+ let doc = gBrowser.contentDocument;+ let tab = gBrowser.selectedTab;++ let moreFromMozillaCategory = doc.getElementById(+ "category-more-from-mozilla"+ );+ ok(moreFromMozillaCategory, "The category exists");+ ok(!moreFromMozillaCategory.hidden, "The category is not hidden");++ moreFromMozillaCategory.click();++ let productCards = doc.querySelectorAll(".mozilla-product-item.simple");+ Assert.ok(productCards, "Default UI uses simple template");+ Assert.equal(productCards.length, 3, "3 product cards displayed");++ const expectedUrl = "https://www.mozilla.org/firefox/browsers/mobile/";+ let tabOpened = BrowserTestUtils.waitForNewTab(gBrowser, url =>+ url.startsWith(expectedUrl)+ );+ let mobileLink = doc.getElementById("default-fxMobile");+ mobileLink.click();+ let openedTab = await tabOpened;+ Assert.ok(gBrowser.selectedBrowser.documentURI.spec.startsWith(expectedUrl));++ let searchParams = new URL(gBrowser.selectedBrowser.documentURI.spec)+ .searchParams;+ Assert.equal(+ searchParams.get("utm_source"),+ "about-prefs",+ "expected utm_source sent"+ );+ Assert.equal(+ searchParams.get("utm_campaign"),+ "morefrommozilla",+ "utm_campaign set"+ );+ Assert.equal(+ searchParams.get("utm_medium"),+ "firefox-desktop",+ "utm_medium set"+ );+ Assert.equal(+ searchParams.get("utm_content"),+ "default-global",+ "default utm_content set"+ );+ Assert.ok(+ !searchParams.has("entrypoint_variation"),+ "entrypoint_variation should not be set"+ );+ Assert.ok(+ !searchParams.has("entrypoint_experiment"),+ "entrypoint_experiment should not be set"+ );+ BrowserTestUtils.removeTab(openedTab);+ BrowserTestUtils.removeTab(tab);+});++add_task(async function testDefaulEmailClick() {+ await openPreferencesViaOpenPreferencesAPI("paneGeneral", {+ leaveOpen: true,+ });+ let doc = gBrowser.contentDocument;+ let tab = gBrowser.selectedTab;++ let moreFromMozillaCategory = doc.getElementById(+ "category-more-from-mozilla"+ );+ moreFromMozillaCategory.click();++ const expectedUrl = "https://www.mozilla.org/firefox/mobile/get-app/?v=mfm";+ let sendEmailLink = doc.getElementById("default-qr-code-send-email");++ Assert.ok(+ sendEmailLink.href.startsWith(expectedUrl),+ `Expected URL ${sendEmailLink.href}`+ );++ let searchParams = new URL(sendEmailLink.href).searchParams;+ Assert.equal(searchParams.get("v"), "mfm", "expected send email param set");+ BrowserTestUtils.removeTab(tab);+}); /** * Test that we don't show moreFromMozilla pane when it's disabled.@@ -44,72 +116,6 @@ BrowserTestUtils.removeTab(gBrowser.selectedTab); });-add_task(async function testDefaultUIWithoutTemplatePref() {- await SpecialPowers.pushPrefEnv({- set: [["browser.preferences.moreFromMozilla", true]],- });-- await openPreferencesViaOpenPreferencesAPI("paneGeneral", {- leaveOpen: true,- });- let doc = gBrowser.contentDocument;- let tab = gBrowser.selectedTab;-- let moreFromMozillaCategory = doc.getElementById(- "category-more-from-mozilla"- );- ok(moreFromMozillaCategory, "The category exists");- ok(!moreFromMozillaCategory.hidden, "The category is not hidden");-- let clickedPromise = ContentTaskUtils.waitForEvent(- moreFromMozillaCategory,- "click"- );- moreFromMozillaCategory.click();- await clickedPromise;-- let productCards = doc.querySelectorAll("div.simple");- Assert.ok(productCards, "Default UI uses simple template");- Assert.equal(productCards.length, 3, "3 product cards displayed");-- const expectedUrl = "https://www.mozilla.org/firefox/browsers/mobile/";- let tabOpened = BrowserTestUtils.waitForNewTab(gBrowser, url =>- url.startsWith(expectedUrl)- );- let mobileLink = doc.getElementById("default-fxMobile");- mobileLink.click();- let openedTab = await tabOpened;- Assert.ok(gBrowser.selectedBrowser.documentURI.spec.startsWith(expectedUrl));-- let searchParams = new URL(gBrowser.selectedBrowser.documentURI.spec)- .searchParams;- Assert.equal(- searchParams.get("utm_source"),- "about-prefs",- "expected utm_source sent"- );- Assert.equal(- searchParams.get("utm_campaign"),- "morefrommozilla",- "utm_campaign set"- );- Assert.equal(- searchParams.get("utm_medium"),- "firefox-desktop",- "utm_medium set"- );- Assert.ok(- !searchParams.has("entrypoint_variation"),- "entrypoint_variation should not be set"- );- Assert.ok(- !searchParams.has("entrypoint_experiment"),- "entrypoint_experiment should not be set"- );- BrowserTestUtils.removeTab(openedTab);- BrowserTestUtils.removeTab(tab);-});- add_task(async function test_aboutpreferences_event_telemetry() { Services.telemetry.clearEvents(); Services.telemetry.setEventRecordingEnabled("aboutpreferences", true);@@ -126,7 +132,7 @@ "category-more-from-mozilla" );- let clickedPromise = ContentTaskUtils.waitForEvent(+ let clickedPromise = BrowserTestUtils.waitForEvent( moreFromMozillaCategory, "click" );@@ -163,14 +169,9 @@ "category-more-from-mozilla" );- let clickedPromise = ContentTaskUtils.waitForEvent(- moreFromMozillaCategory,- "click"- ); moreFromMozillaCategory.click();- await clickedPromise;-- let productCards = doc.querySelectorAll("div.simple");++ let productCards = doc.querySelectorAll(".mozilla-product-item"); Assert.ok(productCards, "The product cards from simple template found"); Assert.equal(productCards.length, 3, "3 product cards displayed");@@ -197,14 +198,9 @@ "category-more-from-mozilla" );- let clickedPromise = ContentTaskUtils.waitForEvent(- moreFromMozillaCategory,- "click"- ); moreFromMozillaCategory.click();- await clickedPromise;-- let productCards = doc.querySelectorAll("vbox.advanced");++ let productCards = doc.querySelectorAll(".mozilla-product-item.advanced"); Assert.ok(productCards, "The product cards from advanced template found"); Assert.equal(productCards.length, 3, "3 product cards displayed"); Assert.deepEqual(@@ -235,15 +231,17 @@ let doc = gBrowser.contentDocument; let tab = gBrowser.selectedTab;- let productCards = doc.querySelectorAll("vbox.simple");+ let productCards = doc.querySelectorAll(".mozilla-product-item.simple"); Assert.ok(productCards, "Simple template loaded"); const expectedUrl = "https://www.mozilla.org/products/vpn/"; let tabOpened = BrowserTestUtils.waitForNewTab(gBrowser, url => url.startsWith(expectedUrl) );+ let vpnButton = doc.getElementById("simple-mozillaVPN");- vpnButton.doCommand();+ vpnButton.click();+ let openedTab = await tabOpened; Assert.ok(gBrowser.selectedBrowser.documentURI.spec.startsWith(expectedUrl));@@ -266,7 +264,7 @@ ); Assert.equal( searchParams.get("utm_content"),- "fxvt-113-a-na",+ "fxvt-113-a-global", "utm_content set" ); Assert.equal(@@ -280,6 +278,55 @@ "entrypoint_variation set" ); BrowserTestUtils.removeTab(openedTab);+ BrowserTestUtils.removeTab(tab);+});++add_task(async function test_aboutpreferences_clickBtnMobile() {+ await SpecialPowers.pushPrefEnv({+ set: [+ ["browser.preferences.moreFromMozilla", true],+ ["browser.preferences.moreFromMozilla.template", "simple"],+ ],+ });+ await openPreferencesViaOpenPreferencesAPI("paneMoreFromMozilla", {+ leaveOpen: true,+ });++ let doc = gBrowser.contentDocument;+ let tab = gBrowser.selectedTab;++ let productCards = doc.querySelectorAll("vbox.simple");+ Assert.ok(productCards, "Simple template loaded");++ const expectedUrl = "https://www.mozilla.org/firefox/browsers/mobile/";++ let mobileUrl = new URL(doc.getElementById("simple-fxMobile").href);++ Assert.ok(mobileUrl.href.startsWith(expectedUrl));++ let searchParams = mobileUrl.searchParams;+ Assert.equal(+ searchParams.get("utm_source"),+ "about-prefs",+ "expected utm_source sent"+ );+ Assert.equal(+ searchParams.get("utm_campaign"),+ "morefrommozilla",+ "utm_campaign set"+ );+ Assert.equal(+ searchParams.get("utm_medium"),+ "firefox-desktop",+ "utm_medium set"+ );+ Assert.equal(+ searchParams.get("utm_content"),+ "fxvt-113-a-global",+ "default-global",+ "utm_content set"+ );+ BrowserTestUtils.removeTab(tab); });@@ -310,217 +357,47 @@ BrowserTestUtils.removeTab(tab); });-add_task(async function test_VPN_promo_enabled() {- await SpecialPowers.pushPrefEnv({- set: [["browser.vpn_promo.enabled", true]],- });-+add_task(async function test_aboutpreferences_clickBtnRally() {+ await SpecialPowers.pushPrefEnv({+ set: [+ ["browser.preferences.moreFromMozilla", true],+ ["browser.preferences.moreFromMozilla.template", "simple"],+ ],+ }); await openPreferencesViaOpenPreferencesAPI("paneMoreFromMozilla", { leaveOpen: true, }); let doc = gBrowser.contentDocument;- let vpnPromoCard = doc.getElementById("mozilla-vpn");- let mobileCard = doc.getElementById("firefox-mobile");- ok(vpnPromoCard, "The VPN promo is visible");- ok(mobileCard, "The Mobile promo is visible");-+ let tab = gBrowser.selectedTab;++ let expectedUrl = new URL("https://rally.mozilla.org");+ expectedUrl.searchParams.set("utm_source", "about-prefs");+ expectedUrl.searchParams.set("utm_campaign", "morefrommozilla");+ expectedUrl.searchParams.set("utm_medium", "firefox-desktop");+ expectedUrl.searchParams.set("utm_content", "fxvt-113-a-na");+ expectedUrl.searchParams.set(+ "entrypoint_experiment",+ "morefrommozilla-experiment-1846"+ );+ expectedUrl.searchParams.set("entrypoint_variation", "treatment-simple");++ let tabOpened = BrowserTestUtils.waitForDocLoadAndStopIt(+ expectedUrl.toString(),+ gBrowser,+ channel => {+ Assert.equal(+ channel.originalURI.spec,+ expectedUrl.toString(),+ "URL matched"+ );+ return true;+ }+ );+ let rallyButton = doc.getElementById("simple-mozillaRally");+ rallyButton.click();++ await tabOpened; BrowserTestUtils.removeTab(gBrowser.selectedTab);-});--add_task(async function test_VPN_promo_disabled() {- await SpecialPowers.pushPrefEnv({- set: [["browser.vpn_promo.enabled", false]],- });-- await openPreferencesViaOpenPreferencesAPI("paneMoreFromMozilla", {- leaveOpen: true,- });-- let doc = gBrowser.contentDocument;- let vpnPromoCard = doc.getElementById("mozilla-vpn");- let mobileCard = doc.getElementById("firefox-mobile");- ok(!vpnPromoCard, "The VPN promo is not visible");- ok(mobileCard, "The Mobile promo is visible");-- Services.prefs.clearUserPref("browser.vpn_promo.enabled");- BrowserTestUtils.removeTab(gBrowser.selectedTab);-});--add_task(async function test_VPN_promo_in_disallowed_home_region() {- const disallowedRegion = "SY";-- setupRegions(disallowedRegion);-- // Promo should not show in disallowed regions even when vpn_promo pref is enabled- await SpecialPowers.pushPrefEnv({- set: [["browser.vpn_promo.enabled", true]],- });-- await openPreferencesViaOpenPreferencesAPI("paneMoreFromMozilla", {- leaveOpen: true,- });-- let doc = gBrowser.contentDocument;- let vpnPromoCard = doc.getElementById("mozilla-vpn");- let mobileCard = doc.getElementById("firefox-mobile");- ok(!vpnPromoCard, "The VPN promo is not visible");- ok(mobileCard, "The Mobile promo is visible");-- setupRegions(initialHomeRegion, intialCurrentRegion); // revert changes to regions- BrowserTestUtils.removeTab(gBrowser.selectedTab);-});--add_task(async function test_VPN_promo_in_illegal_home_region() {- const illegalRegion = "CN";-- setupRegions(illegalRegion);-- // Promo should not show in illegal regions even if the list of disallowed regions is somehow altered (though changing this preference is blocked)- await SpecialPowers.pushPrefEnv({- set: [["browser.vpn_promo.disallowedRegions", "SY, CU"]],- });-- await openPreferencesViaOpenPreferencesAPI("paneMoreFromMozilla", {- leaveOpen: true,- });-- let doc = gBrowser.contentDocument;- let vpnPromoCard = doc.getElementById("mozilla-vpn");- let mobileCard = doc.getElementById("firefox-mobile");- ok(!vpnPromoCard, "The VPN promo is not visible");- ok(mobileCard, "The Mobile promo is visible");-- setupRegions(initialHomeRegion, intialCurrentRegion); // revert changes to regions- BrowserTestUtils.removeTab(gBrowser.selectedTab);-});--add_task(async function test_VPN_promo_in_disallowed_current_region() {- const allowedRegion = "US";- const disallowedRegion = "SY";-- setupRegions(allowedRegion, disallowedRegion);-- // Promo should not show in disallowed regions even when vpn_promo pref is enabled- await SpecialPowers.pushPrefEnv({- set: [["browser.vpn_promo.enabled", true]],- });-- await openPreferencesViaOpenPreferencesAPI("paneMoreFromMozilla", {- leaveOpen: true,- });-- let doc = gBrowser.contentDocument;- let vpnPromoCard = doc.getElementById("mozilla-vpn");- let mobileCard = doc.getElementById("firefox-mobile");- ok(!vpnPromoCard, "The VPN promo is not visible");- ok(mobileCard, "The Mobile promo is visible");-- setupRegions(initialHomeRegion, intialCurrentRegion); // revert changes to regions- BrowserTestUtils.removeTab(gBrowser.selectedTab);-});--add_task(async function test_VPN_promo_in_illegal_current_region() {- const allowedRegion = "US";- const illegalRegion = "CN";-- setupRegions(allowedRegion, illegalRegion);-- // Promo should not show in illegal regions even if the list of disallowed regions is somehow altered (though changing this preference is blocked)- await SpecialPowers.pushPrefEnv({- set: [["browser.vpn_promo.disallowedRegions", "SY, CU"]],- });-- await openPreferencesViaOpenPreferencesAPI("paneMoreFromMozilla", {- leaveOpen: true,- });-- let doc = gBrowser.contentDocument;- let vpnPromoCard = doc.getElementById("mozilla-vpn");- let mobileCard = doc.getElementById("firefox-mobile");- ok(!vpnPromoCard, "The VPN promo is not visible");- ok(mobileCard, "The Mobile promo is visible");-- setupRegions(initialHomeRegion, intialCurrentRegion); // revert changes to regions- BrowserTestUtils.removeTab(gBrowser.selectedTab);-});--add_task(- async function test_rally_promo_with_approved_home_region_and_language() {- // Only show the Rally promo when US is the region and English is the langauge- setupRegions("US");-- await openPreferencesViaOpenPreferencesAPI("paneMoreFromMozilla", {- leaveOpen: true,- });-- let doc = gBrowser.contentDocument;- let rallyPromoCard = doc.getElementById("mozilla-rally");- let mobileCard = doc.getElementById("firefox-mobile");- ok(rallyPromoCard, "The Rally promo is visible");- ok(mobileCard, "The Mobile promo is visible");-- setupRegions(initialHomeRegion, intialCurrentRegion); // revert changes to regions- BrowserTestUtils.removeTab(gBrowser.selectedTab);- }-);--add_task(async function test_rally_promo_with_unapproved_home_region() {- setupRegions("IS");-- await openPreferencesViaOpenPreferencesAPI("paneMoreFromMozilla", {- leaveOpen: true,- });-- let doc = gBrowser.contentDocument;- let rallyPromoCard = doc.getElementById("mozilla-rally");- let mobileCard = doc.getElementById("firefox-mobile");- ok(!rallyPromoCard, "The Rally promo is not visible");- ok(mobileCard, "The Mobile promo is visible");-- setupRegions(initialHomeRegion, intialCurrentRegion); // revert changes to regions- BrowserTestUtils.removeTab(gBrowser.selectedTab);-});--add_task(async function test_rally_promo_with_unapproved_current_region() {- setupRegions("US", "IS");-- await openPreferencesViaOpenPreferencesAPI("paneMoreFromMozilla", {- leaveOpen: true,- });-- let doc = gBrowser.contentDocument;- let rallyPromoCard = doc.getElementById("mozilla-rally");- let mobileCard = doc.getElementById("firefox-mobile");- ok(!rallyPromoCard, "The Rally promo is not visible");- ok(mobileCard, "The Mobile promo is visible");-- setupRegions(initialHomeRegion, intialCurrentRegion); // revert changes to regions- BrowserTestUtils.removeTab(gBrowser.selectedTab);-});--add_task(async function test_rally_promo_with_unapproved_language() {- function setLanguage(language) {- Services.locale.availableLocales = [language];- Services.locale.requestedLocales = [language];- }- // Rally promo should be hidden in the US for languages other than English- setupRegions("US");- const initialLanguage = Services.locale.appLocaleAsBCP47;- setLanguage("ko-KR");-- await openPreferencesViaOpenPreferencesAPI("paneMoreFromMozilla", {- leaveOpen: true,- });-- let doc = gBrowser.contentDocument;- let rallyPromoCard = doc.getElementById("mozilla-rally");- let mobileCard = doc.getElementById("firefox-mobile");- ok(!rallyPromoCard, "The Rally promo is not visible");- ok(mobileCard, "The Mobile promo is visible");-- setupRegions(initialHomeRegion, intialCurrentRegion); // revert changes to regions- // revert changes to language- setLanguage(initialLanguage);- BrowserTestUtils.removeTab(gBrowser.selectedTab);-});+ BrowserTestUtils.removeTab(tab);+});
After analyzing the provided code diff, I don't see any clear security vulnerabilities being fixed. The changes appear to be primarily focused on: 1. Removing region-specific testing code 2. Updating test cases for the "More from Mozilla" feature 3. Changing some selectors and test assertions 4. Reorganizing test functions Here's my analysis following your requested format: Vulnerability Existed: no No security vulnerability found [browser_moreFromMozilla.js] [entire file] The changes are test-related and don't appear to address any security issues The main changes include: - Removal of region-specific test setup code - Updates to test assertions and selectors - Reorganization of test functions - Changes in how click events are handled in tests - Updates to URL parameter assertions None of these changes appear to be security-related fixes. The modifications seem focused on test maintenance and feature updates rather than addressing vulnerabilities. If you'd like me to analyze any specific part of the diff in more detail, please let me know.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/third_party/rust/idna/tests/tests.rs+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/third_party/rust/idna/tests/tests.rs@@ -1,6 +1,4 @@-extern crate idna;-extern crate serde_json;-extern crate rustc_test as test;+use rustc_test as test; mod punycode; mod uts46;
Based on the provided code diff, I'll analyze it for security fixes: 1. Vulnerability Existed: no Build Dependency Simplification [third_party/rust/idna/tests/tests.rs] [Lines 1-3] Old Code: ```rust extern crate idna; extern crate serde_json; extern crate rustc_test as test; ``` Fixed Code: ```rust use rustc_test as test; ``` This appears to be a simple modernization of Rust code syntax rather than a security fix. The change removes explicit `extern crate` declarations (which are no longer needed in Rust 2018 edition) and simplifies the imports. There doesn't appear to be any security vulnerability being addressed here - it's purely a code style/formatting improvement.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/python/mozboot/mozboot/mozillabuild.py+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/python/mozboot/mozboot/mozillabuild.py@@ -10,6 +10,7 @@ import sys import subprocess+from pathlib import Path from mozboot.base import BaseBootstrapper@@ -68,14 +69,14 @@ _, values_count, __ = winreg.QueryInfoKey(exclusions_key) for i in range(0, values_count): path, _, __ = winreg.EnumValue(exclusions_key, i)- paths.append(path)+ paths.append(Path(path)) except FileNotFoundError: pass return paths-def is_windefender_affecting_srcdir(srcdir):+def is_windefender_affecting_srcdir(src_dir: Path): if get_is_windefender_disabled(): return False@@ -83,7 +84,7 @@ # commonpath will use the casing of the first path provided. # To avoid surprises here, we normcase(...) so we don't get unexpected breakage if we change # the path order.- srcdir = os.path.normcase(os.path.abspath(srcdir))+ src_dir = src_dir.resolve() try: exclusion_paths = get_windefender_exclusion_paths()@@ -96,9 +97,9 @@ raise for exclusion_path in exclusion_paths:- exclusion_path = os.path.normcase(os.path.abspath(exclusion_path))+ exclusion_path = exclusion_path.resolve() try:- if os.path.commonpath([exclusion_path, srcdir]) == exclusion_path:+ if Path(os.path.commonpath((exclusion_path, src_dir))) == exclusion_path: # exclusion_path is an ancestor of srcdir return False except ValueError:@@ -247,9 +248,8 @@ subprocess.check_call(command, stdin=sys.stdin) def pip_install(self, *packages):- pip_dir = os.path.join(- os.environ["MOZILLABUILD"], "python", "Scripts", "pip.exe"- )- command = [pip_dir, "install", "--upgrade"]+ pip_dir = Path(os.environ["MOZILLABUILD"]) / "python" / "Scripts" / "pip.exe"++ command = [str(pip_dir), "install", "--upgrade"] command.extend(packages) self.run(command)
Here's the analysis of the provided code diff for security fixes: 1. Vulnerability Existed: yes Path Traversal Vulnerability [File] python/mozboot/mozboot/mozillabuild.py [Lines 68-84] [Old Code] path, _, __ = winreg.EnumValue(exclusions_key, i) paths.append(path) ... srcdir = os.path.normcase(os.path.abspath(srcdir)) [Fixed Code] path, _, __ = winreg.EnumValue(exclusions_key, i) paths.append(Path(path)) ... src_dir = src_dir.resolve() 2. Vulnerability Existed: yes Command Injection Vulnerability [File] python/mozboot/mozboot/mozillabuild.py [Lines 247-253] [Old Code] pip_dir = os.path.join( os.environ["MOZILLABUILD"], "python", "Scripts", "pip.exe" ) command = [pip_dir, "install", "--upgrade"] [Fixed Code] pip_dir = Path(os.environ["MOZILLABUILD"]) / "python" / "Scripts" / "pip.exe" command = [str(pip_dir), "install", "--upgrade"] The changes improve security by: 1. Using Path objects and their resolve() method instead of os.path operations, which provides better path normalization and handling, preventing potential path traversal issues. 2. Using Path object operations for constructing paths instead of string concatenation, which helps prevent command injection vulnerabilities when the path is used in subprocess calls. While these aren't fixing critical vulnerabilities, they represent security hardening by using more robust path handling mechanisms that are less prone to common security issues.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.
--- /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_97_END/firefox-FIREFOX_RELEASE_97_END/testing/web-platform/tests/html/canvas/offscreen/path-objects/2d.path.moveTo.multiple.worker.js+++ /root/PatchLeaks-main/products/firefox_downloads/FIREFOX_RELEASE_98_END/firefox-FIREFOX_RELEASE_98_END/testing/web-platform/tests/html/canvas/offscreen/path-objects/2d.path.moveTo.multiple.worker.js@@ -13,8 +13,8 @@ }); t.step(function() {-var offscreenCanvas = new OffscreenCanvas(100, 50);-var ctx = offscreenCanvas.getContext('2d');+var canvas = new OffscreenCanvas(100, 50);+var ctx = canvas.getContext('2d'); ctx.fillStyle = '#f00'; ctx.fillRect(0, 0, 100, 50);@@ -25,7 +25,7 @@ ctx.strokeStyle = '#0f0'; ctx.lineWidth = 50; ctx.stroke();-_assertPixel(offscreenCanvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255"); t.done(); });
After analyzing the provided code diff, here's the security assessment: 1. Vulnerability Existed: no No security vulnerability found [File] testing/web-platform/tests/html/canvas/offscreen/path-objects/2d.path.moveTo.multiple.worker.js [Lines] 13-25 [Old Code] var offscreenCanvas = new OffscreenCanvas(100, 50); var ctx = offscreenCanvas.getContext('2d'); ... _assertPixel(offscreenCanvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255"); [Fixed Code] var canvas = new OffscreenCanvas(100, 50); var ctx = canvas.getContext('2d'); ... _assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255"); The changes appear to be purely cosmetic/refactoring, renaming the variable `offscreenCanvas` to `canvas` for consistency or readability. There are no security-related changes in this diff, no vulnerability fixes, and no changes to the actual functionality of the code. The changes are limited to variable naming and don't affect any security-sensitive operations.
If an attacker could control the contents of an iframe sandboxed with <code>allow-popups</code> but not <code>allow-scripts</code>, they were able to craft a link that, when clicked, would lead to JavaScript execution in violation of the sandbox. This vulnerability affects Firefox < 98, Firefox ESR < 91.7, and Thunderbird < 91.7.