Bug 2251620

Summary: hang on maps.google.co.uk (maybe randomDataOnCanvasExtract/ RandomizePixels?) - downstream only?
Product: [Fedora] Fedora Reporter: Dr. David Alan Gilbert <rh>
Component: firefoxAssignee: Gecko Maintainer <gecko-bugs-nobody>
Status: CLOSED DUPLICATE QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: unspecified    
Version: 39CC: erack, gecko-bugs-nobody, jhorak, klaas, rstrode
Target Milestone: ---Keywords: Regression
Target Release: ---   
Hardware: Unspecified   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2023-11-27 02:57:04 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Dr. David Alan Gilbert 2023-11-27 01:32:53 UTC
In the last few days I've been seeing a hang on maps.google.co.uk; the map renders but then the page hangs solid, I can't interact with the UI in that tab, and sometimes closing the tab takes a few seconds.

I've gathered quite a bit of debug; first what does and doesn't work:

  a) Fails: Downstream firefox-120.0-2.fc39.x86_64 with my standard profile fails
  b) Works: Upstream mozilla.org 120.0 builds with the same profile
  c) Works: Downstream in 'troubleshooting' mode
  c) Fails: Downstream with all plugins disabled and hardware accel disabled still fails

Firefox support suggested I try their profiler and you can see the profile at:
   https://share.firefox.dev/47se8Zm

They also suggested tryign to get a backtrace of the process for the tab by sending it a segfault, instead I connected with gdb; 

mozilla::nsRFPService::RandomizePixels(nsICookieJarSettings*, unsigned char*, unsigned int, unsigned int, unsigned int, mozilla::gfx::SurfaceFormat) [clone .constprop.0] ()
    at /usr/src/debug/firefox-120.0-2.fc39.x86_64/toolkit/components/resistfingerprinting/nsRFPService.cpp:1370
Downloading source file /usr/src/debug/firefox-120.0-2.fc39.x86_64/toolkit/components/resistfingerprinting/nsRFPService.cpp
1370      for (uint8_t i = 0; i <= numNoises; i++) {                                                                 
(gdb) p numNoises
No symbol "numNoises" in current context.
(gdb) where
#0  mozilla::nsRFPService::RandomizePixels(nsICookieJarSettings*, unsigned char*, unsigned int, unsigned int, unsigned int, mozilla::gfx::SurfaceFormat) [clone .constprop.0] ()
    at /usr/src/debug/firefox-120.0-2.fc39.x86_64/toolkit/components/resistfingerprinting/nsRFPService.cpp:1370
#1  0x00007f79b6b8d862 in mozilla::dom::CanvasRenderingContext2D::GetImageDataArray(JSContext*, int, int, unsigned int, unsigned int, nsIPrincipal&, JSObject**) ()
    at /usr/src/debug/firefox-120.0-2.fc39.x86_64/dom/canvas/CanvasRenderingContext2D.cpp:5998
#2  mozilla::dom::CanvasRenderingContext2D::GetImageData(JSContext*, int, int, int, int, nsIPrincipal&, mozilla::ErrorResult&) () at /usr/src/debug/firefox-120.0-2.fc39.x86_64/dom/canvas/CanvasRenderingContext2D.cpp:5887
#3  0x00007f79b6830fe7 in getImageData() () at ../../../dom/bindings/CanvasRenderingContext2DBinding.cpp:5416
#4  0x000017678b558a84 in  ()
#5  0x0000000000000004 in  ()
#6  0x00007fff42eb1540 in  ()
#7  0x000017678b558a37 in  ()
#8  0x0000000000000000 in  ()

so in this randomise loop; I'm not sure if it's stuck there but there is a solid blue bar in the profiler?

1370	  for (uint8_t i = 0; i <= numNoises; i++) {
1371	    // Choose which RGB channel to add a noise. The pixel data is in either
1372	    // the BGRA or the ARGB format depending on the endianess. To choose the
1373	    // color channel we need to add the offset according the endianess.
1374	    uint32_t channel;
1371	    // Choose which RGB channel to add a noise. The pixel data is in either
1372	    // the BGRA or the ARGB format depending on the endianess. To choose the
1373	    // color channel we need to add the offset according the endianess.
1374	    uint32_t channel;
1375	    if (aSurfaceFormat == gfx::SurfaceFormat::B8G8R8A8) {
1376	      channel = rng1.next() % 3;
1377	    } else if (aSurfaceFormat == gfx::SurfaceFormat::A8R8G8B8) {
1378	      channel = rng1.next() % 3 + 1;
1379	    } else {
1380	      return NS_ERROR_INVALID_ARG;

(Possibly unrelated, but gathering the profile got me a mozilla crash;  https://crash-stats.mozilla.org/report/index/cae29340-bf09-450c-99e6-749480231127 )

Reproducible: Always

Steps to Reproduce:
1. Open Firefox tab
2. Bring up maps.google.co.uk
3.
Actual Results:  
Rendered front of the maps, hung tab

Expected Results:  
Working maps

Comment 1 Dr. David Alan Gilbert 2023-11-27 01:38:02 UTC
Given that backtrace I tried turning off:

privacy.resistFingerprinting.randomDataOnCanvasExtract

and it fixes it!

Comment 2 Dr. David Alan Gilbert 2023-11-27 02:48:43 UTC
To me this looks like that code is broken;

in nsRFPService.cpp:

  // Ensure at least 20 random changes may occur.
  uint8_t numNoises = std::clamp<uint8_t>(rnd3, 20, 255);


  for (uint8_t i = 0; i <= numNoises; i++) {

I don't think we're ever getting out of that loop, and I think that's because numNoises is 255 - which the clamp allows.

Comment 3 Dr. David Alan Gilbert 2023-11-27 02:57:04 UTC

*** This bug has been marked as a duplicate of bug 2251202 ***