<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>231364</bug_id>
          
          <creation_ts>2021-10-07 09:25:49 -0700</creation_ts>
          <short_desc>Crash on iOS Safari wasm - two references to the same object return different values from trivial accessor for a primitive field.</short_desc>
          <delta_ts>2021-10-14 09:26:18 -0700</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>WebAssembly</component>
          <version>Safari 15</version>
          <rep_platform>iPhone / iPad</rep_platform>
          <op_sys>Unspecified</op_sys>
          <bug_status>NEW</bug_status>
          <resolution></resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords>InRadar</keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Paris Morgan">paris</reporter>
          <assigned_to name="Nobody">webkit-unassigned</assigned_to>
          <cc>fpizlo</cc>
    
    <cc>keith_miller</cc>
    
    <cc>webkit-bug-importer</cc>
    
    <cc>ysuzuki</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>1801625</commentid>
    <comment_count>0</comment_count>
    <who name="Paris Morgan">paris</who>
    <bug_when>2021-10-07 09:25:49 -0700</bug_when>
    <thetext>Hi all, I&apos;m filing this bug after exhausting many other options. I&apos;m running a wasm binary with link time optimization and have tried running with ASSERTIONS, SAFE_HEAP, STACK_OVERFLOW_CHECK, and --memoryprofiler on emscripten. I&apos;ve also run with an address sanitizer (`--copt=-fsanitize=address --linkopt=-fsanitize=address`), both in native and wasm builds. This bug reproes 100% of the time on iOS Safari, but not on Android, native Mac OS, or desktop Chrome + Safari

But, on to the bug. Here you can see we take two references (o1 and o2) to the same object in a vector:
```
class Object {
  ...
  uint32_t id() const { return id_; }
  ...
  uint32_t id_ = 0;
};

std::vector&lt;Object&gt; objs_;

void f() {
  auto &amp;o1 = objs_.at(idx);
  ...
  auto &amp;o2 = objs_.at(idx);

  ...
  if (std::addressof(o1) == std::addressof(o2) &amp;&amp; o1.id() != o2.id()) {
    printf(&quot;Same object but different values! (%p and %p) (%zu and &amp;zu)&quot;, &amp;o1, &amp;o2, o1.id(), o2.id());
  }
  ...
}
```
We then check if their address is the same but the value of `id()`, which is a trivial accessor for a primitive field, is different - which it is:
```
Same object but different values! (0xb472c8 and 0xb472c8) (3676866271 and 0)
```

The worst part about this bug is that it manifests itself when I change seemingly unrelated code, specifically changing a destructor from an empty user-defined destructor `~Foo() {}`, to a default destructor `~Foo() = default;`. I&apos;ve diff-ed the bitcode before link time optimization with both destructors, and they are the same. So it seems perhaps somewhere in LTO there is a memory issue being introduced.

As an extra hurdle, this bug is resistant to inspection. If I try to print out the memory around o1 and o2, then the bug no longer occurs.
```
for (int i = 0; i &lt; 128; ++i) {
  printf(&quot;%02x &quot;, (unsigned char*)&amp;o1 + i);
}
```

The impact of this bug is that our program is crashing because later when we access `o2.id()`, the value is zero. I have not been able to recreate this with a minimal repro case, but posting this in the hope others have seem something similar or have suggestions on investigating further.

Details:
- iOS Safari
- C++ wasm with link time optimization
- emsdk-sdk-2.0.27
- llvm 8ae5e0b154ae18a78f73c0aef58356002b8ff0d7</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1802674</commentid>
    <comment_count>1</comment_count>
    <who name="Alexey Proskuryakov">ap</who>
    <bug_when>2021-10-11 10:07:43 -0700</bug_when>
    <thetext>Thank you for the report!

Could you please share a test case (one that can be simply open in Safari to observe the problem)?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1803443</commentid>
    <comment_count>2</comment_count>
    <who name="Paris Morgan">paris</who>
    <bug_when>2021-10-12 15:04:27 -0700</bug_when>
    <thetext>Sure, here a link to a repro: https://8w.8thwall.app/safari-memory-bug. I&apos;ve run it on an iPhone 12 Pro running iOS 15.0.1 and an iPhone 6S Plus running iOS 14.8.

You should accept camera permissions and then wave the phone around for ~5 seconds to trigger the crash, upon which you&apos;ll see a screen saying &quot;Oops, something went wrong!&quot;. If you connect to Safari and look at console logs you can then see logs. I&apos;ve slightly modified the code above to instead be:
```
void f() {
  ...
  auto &amp;o1 = objs_.at(idx);
  ...
  auto &amp;o2 = objs_.at(idx);
  ....
  printf(&quot;     (1) First we check if o1 and o2 have the same address but different values:\n&quot;);
  if (std::addressof(o1) == std::addressof(o2) &amp;&amp; o1.id() != o2.id()) {
    printf(&quot;     (1) Same address but different values! o1: %p, o1.id(): %u | o2: %p, o2.id(): %u\n&quot;, &amp;o1, o1.id(), &amp;o2, o2.id());
  } else if (std::addressof(o1) == std::addressof(o2)) {
    printf(&quot;     (1) Same address and same values. o1: %p, o1.id(): %u | o2: %p, o2.id(): %u\n&quot;, &amp;o1, o1.id(), &amp;o2, o2.id());
  }

  printf(&quot;     (2) Now lets print out the addresses and ids of o1 and o2:\n&quot;);
  printf(&quot;     (2) o1: %p, o1.id(): %u | o2: %p, o2.id(): %u\n&quot;, &amp;o1, o1.id(), &amp;o2, o2.id());

  printf(&quot;     (3) Now check again if o1 and o2 have the same address but different values:\n&quot;);
  if (std::addressof(o1) == std::addressof(o2) &amp;&amp; o1.id() != o2.id()) {
    printf(&quot;     (3) Same address but different values! o1: %p, o1.id(): %u | o2: %p, o2.id(): %u\n&quot;, &amp;o1, o1.id(), &amp;o2, o2.id());
  } else if (std::addressof(o1) == std::addressof(o2)) {
    printf(&quot;     (3) Same address and same values. o1: %p, o1.id(): %u | o2: %p, o2.id(): %u\n&quot;, &amp;o1, o1.id(), &amp;o2, o2.id());
  }
```
The result is that on the camera frame that crashes you will see:
```
(1) First we check if o1 and o2 have the same address but different values:
(1) Same address and same values. o1: 0xb392d8, o1.id(): 4240949120 | o2: 0xb392d8, o2.id(): 4240949120
(2) Now lets print out the addresses and ids of o1 and o2:
(2) o1: 0xb392d8, o1.id(): 4240949120 | o2: 0xb392d8, o2.id(): 0
(3) Now check again if o1 and o2 have the same address but different values:
(3) Same address but different values! o1: 0xb392d8, o1.id(): 4240949120 | o2: 0xb392d8, o2.id(): 0
```</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1804306</commentid>
    <comment_count>3</comment_count>
    <who name="Radar WebKit Bug Importer">webkit-bug-importer</who>
    <bug_when>2021-10-14 09:26:18 -0700</bug_when>
    <thetext>&lt;rdar://problem/84258798&gt;</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>