<?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>280593</bug_id>
          
          <creation_ts>2024-09-29 16:52:00 -0700</creation_ts>
          <short_desc>TextDecoder raises &quot;RangeError: Bad value&quot; exception after 2GB of text</short_desc>
          <delta_ts>2025-04-08 07:41:07 -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>DOM</component>
          <version>Safari 18</version>
          <rep_platform>Mac (Apple Silicon)</rep_platform>
          <op_sys>macOS 15</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>FIXED</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="Jacob Bandes-Storch">jacob</reporter>
          <assigned_to name="Alex Christensen">achristensen</assigned_to>
          <cc>achristensen</cc>
    
    <cc>alec</cc>
    
    <cc>ap</cc>
    
    <cc>cdumez</cc>
    
    <cc>darin</cc>
    
    <cc>erik</cc>
    
    <cc>webkit-bug-importer</cc>
    
    <cc>webkit</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>2064136</commentid>
    <comment_count>0</comment_count>
      <attachid>472732</attachid>
    <who name="Jacob Bandes-Storch">jacob</who>
    <bug_when>2024-09-29 16:52:00 -0700</bug_when>
    <thetext>Created attachment 472732
Test page demonstrating error after 2GB of text decoding

TextDecoder seems to crash after processing 2GB of text in streaming mode.


## Steps to reproduce:

1. Create a 3GB test file using:  truncate -s 3G test.txt
2. Open textdecoder-test.html (attached to this bug) in Safari
3. Click &quot;choose file&quot; and select the test.txt created in step 1
4. Observe the progress bar stops at 2.00GB and then an error is logged to the console: &quot;Unhandled Promise Rejection: RangeError: Bad value&quot;


## Expected behavior:

No error -- should be able to continue parsing text beyond the 2GB range.


## Notes:

Works as expected in Chrome and Firefox.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2065739</commentid>
    <comment_count>1</comment_count>
    <who name="Radar WebKit Bug Importer">webkit-bug-importer</who>
    <bug_when>2024-10-06 16:52:13 -0700</bug_when>
    <thetext>&lt;rdar://problem/137394167&gt;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2100532</commentid>
    <comment_count>2</comment_count>
    <who name="wyhaya">webkit</who>
    <bug_when>2025-03-04 22:57:20 -0800</bug_when>
    <thetext>Minimal replication:

```
const text = new TextDecoder()
const buff = new ArrayBuffer(100)
for (let i = 0; i &lt; 21474837; i++) {
    text.decode(buff)
}
```

This will see the same error. 
If you change 21474837 to 21474836, it will run normally.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2100640</commentid>
    <comment_count>3</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2025-03-05 09:09:17 -0800</bug_when>
    <thetext>There is currently code in TextDecoder that keeps track of the total number of decoded bytes passed in, and throws a range error if that total number of decoded bytes is greater than the maximum string length supported by WebKit and its JavaScript engine. I’m not sure why that check is present. The simplest way to start fixing this bug is to remove TextDecoder::m_decodedBytes and the code that checks it entirely.

Next, we have to figure out if TextDecoder handles cases where the passed in data is very large. This check may have been protecting the underlying code from being tested in various edge cases, and we’d want to fix those. But it’s possible that just removing m_decodedBytes will take care of the whole problem without requiring any additional work.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2100650</commentid>
    <comment_count>4</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2025-03-05 09:17:44 -0800</bug_when>
    <thetext>This limit was added to try to address a security problem with producing output strings that are too long. But the code change instead limited the total number of characters passed in to each codec, which is stricter than is needed. To fix this we need to correctly address the original security issue by making sure codecs can never produce a string larger than the maximum string length, and remove TextDecoder::m_decodedBytes since it will no longer be necessary.

It’s unsafe to remove TextDecoder::m_decodedBytes without addressing the underlying issue of TextCodec decode functions producing strings that are too long.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2101550</commentid>
    <comment_count>5</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2025-03-07 16:41:22 -0800</bug_when>
    <thetext>Not to &quot;try&quot; to address a security problem. It successfully addressed the security problem.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2103924</commentid>
    <comment_count>6</comment_count>
    <who name="Jacob Bandes-Storch">jacob</who>
    <bug_when>2025-03-17 21:22:55 -0700</bug_when>
    <thetext>Here is an example workaround that I ended up using for this issue – just create a new TextDecoder every so often: https://github.com/jtbandes/mbox.wtf/blob/e039291e70160700c47a6876a41db967375e631e/src/readLines.ts#L20-L32</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2109223</commentid>
    <comment_count>7</comment_count>
    <who name="Erik Zivkovic">erik</who>
    <bug_when>2025-04-05 22:49:32 -0700</bug_when>
    <thetext>We have a long running wasm application that hits this problem very often, affecting thousands of users of Safari every week.

wasm-bindgen (Rust) generates this piece code for every app using it:

```
const lTextEncoder = typeof TextEncoder === &apos;undefined&apos; ? (0, module.require)(&apos;util&apos;).TextEncoder : TextEncoder;

let cachedTextEncoder = new lTextEncoder(&apos;utf-8&apos;);


function getStringFromWasm0(ptr, len) {
    ptr = ptr &gt;&gt;&gt; 0;
    return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
}
```

And then getStringFromWasm0 gets used for everything that needs to do JS things with Rust strings.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2109227</commentid>
    <comment_count>8</comment_count>
    <who name="Erik Zivkovic">erik</who>
    <bug_when>2025-04-06 00:09:01 -0700</bug_when>
    <thetext>Sorry, I copied the wrong snippet, this is the correct one:

```
const lTextDecoder = typeof TextDecoder === &apos;undefined&apos; ? (0, module.require)(&apos;util&apos;).TextDecoder : TextDecoder;

let cachedTextDecoder = new lTextDecoder(&apos;utf-8&apos;, { ignoreBOM: true, fatal: true });

function getStringFromWasm0(ptr, len) {
    ptr = ptr &gt;&gt;&gt; 0;
    return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
}
```</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2109464</commentid>
    <comment_count>9</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2025-04-07 11:14:42 -0700</bug_when>
    <thetext>Understood. The reason this hasn’t been fixed quickly is that it’s challenging to fix this problem without reintroducing the security vulnerability.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2109476</commentid>
    <comment_count>10</comment_count>
    <who name="Alex Christensen">achristensen</who>
    <bug_when>2025-04-07 11:52:41 -0700</bug_when>
    <thetext>Pull request: https://github.com/WebKit/WebKit/pull/43753</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2109705</commentid>
    <comment_count>11</comment_count>
    <who name="EWS">ews-feeder</who>
    <bug_when>2025-04-08 07:41:04 -0700</bug_when>
    <thetext>Committed 293416@main (8c5a1e5c6db5): &lt;https://commits.webkit.org/293416@main&gt;

Reviewed commits have been landed. Closing PR #43753 and removing active labels.</thetext>
  </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="0"
              isprivate="0"
          >
            <attachid>472732</attachid>
            <date>2024-09-29 16:52:00 -0700</date>
            <delta_ts>2024-09-29 16:52:00 -0700</delta_ts>
            <desc>Test page demonstrating error after 2GB of text decoding</desc>
            <filename>textdecoder-test.html</filename>
            <type>text/html</type>
            <size>1243</size>
            <attacher name="Jacob Bandes-Storch">jacob</attacher>
            
              <data encoding="base64">PCFkb2N0eXBlIGh0bWw+CjxodG1sPgoKPGhlYWQ+CjwvaGVhZD4KCjxib2R5PgogICAgPGlucHV0
IHR5cGU9ImZpbGUiIC8+CiAgICA8cHJvZ3Jlc3MgaWQ9InByb2dyZXNzIiB2YWx1ZT0iMCI+PC9w
cm9ncmVzcz4KICAgIDxzcGFuIGlkPSJwcm9ncmVzcy10ZXh0Ij48L3NwYW4+CiAgICA8c2NyaXB0
PgogICAgICAgIGNvbnN0IHByb2dyZXNzID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInByb2dy
ZXNzIik7CiAgICAgICAgY29uc3QgcHJvZ3Jlc3NUZXh0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5
SWQoInByb2dyZXNzLXRleHQiKTsKICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCJpbnB1
dCIpLmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIGFzeW5jIChldmVudCkgPT4gewogICAgICAg
ICAgICBjb25zb2xlLmxvZygiZ290IGZpbGUiKTsKICAgICAgICAgICAgY29uc3QgZmlsZSA9IGV2
ZW50LnRhcmdldC5maWxlc1swXTsKICAgICAgICAgICAgY29uc3QgQ0hVTktfU0laRSA9IDEwMjQg
KiAxMDI0OwogICAgICAgICAgICBjb25zdCBCWVRFU19QRVJfR0IgPSAxMDI0ICogMTAyNCAqIDEw
MjQ7CiAgICAgICAgICAgIGNvbnN0IGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoKTsKICAgICAg
ICAgICAgZm9yIChsZXQgb2Zmc2V0ID0gMDsgb2Zmc2V0IDwgZmlsZS5zaXplOyBvZmZzZXQgKz0g
Q0hVTktfU0laRSkgewogICAgICAgICAgICAgICAgY29uc3QgZG9uZSA9IG9mZnNldCArIENIVU5L
X1NJWkUgPj0gZmlsZS5zaXplOwogICAgICAgICAgICAgICAgY29uc3QgY2h1bmsgPSBhd2FpdCBm
aWxlLnNsaWNlKG9mZnNldCwgb2Zmc2V0ICsgQ0hVTktfU0laRSkuYXJyYXlCdWZmZXIoKTsKICAg
ICAgICAgICAgICAgIGNvbnN0IHRleHQgPSBkZWNvZGVyLmRlY29kZShuZXcgVWludDhBcnJheShj
aHVuayksIHsgc3RyZWFtOiAhZG9uZSB9KTsKICAgICAgICAgICAgICAgIGNvbnN0IGJ5dGVzUmVh
ZCA9IG9mZnNldCArIGNodW5rLmJ5dGVMZW5ndGg7CiAgICAgICAgICAgICAgICBwcm9ncmVzcy52
YWx1ZSA9IGJ5dGVzUmVhZCAvIGZpbGUuc2l6ZTsKICAgICAgICAgICAgICAgIHByb2dyZXNzVGV4
dC50ZXh0Q29udGVudCA9IGAkeyhieXRlc1JlYWQgLyBCWVRFU19QRVJfR0IpLnRvRml4ZWQoMil9
IEdpQiAoJHsocHJvZ3Jlc3MudmFsdWUgKiAxMDApLnRvRml4ZWQoMSl9JSlgOwogICAgICAgICAg
ICB9CiAgICAgICAgfSk7CiAgICA8L3NjcmlwdD4KPC9ib2R5PgoKPC9odG1sPg==
</data>

          </attachment>
      

    </bug>

</bugzilla>