Skip to content

Commit 5169d9d

Browse files
zhenghaozAaron1011
authored andcommitted
avm2: Fix multiply with overflow in string_to_f64
1 parent 95057ee commit 5169d9d

File tree

3 files changed

+19
-2
lines changed

3 files changed

+19
-2
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ jpegxr = { git = "https://github.com/ruffle-rs/jpegxr", branch = "ruffle", optio
6363
image = { version = "0.24.8", default-features = false, features = ["tiff", "dxt"] }
6464
enum-map = "2.7.3"
6565
ttf-parser = "0.20"
66+
num-bigint = "0.4"
6667

6768
[target.'cfg(not(target_family = "wasm"))'.dependencies.futures]
6869
version = "0.3.30"

core/src/avm2/value.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ use crate::avm2::Namespace;
1111
use crate::ecma_conversions::{f64_to_wrapping_i32, f64_to_wrapping_u32};
1212
use crate::string::{AvmAtom, AvmString, WStr};
1313
use gc_arena::{Collect, GcCell, Mutation};
14+
use num_bigint::BigInt;
15+
use num_traits::{ToPrimitive, Zero};
1416
use std::cell::Ref;
1517
use std::mem::size_of;
1618
use swf::avm2::types::{DefaultValue as AbcDefaultValue, Index};
@@ -383,7 +385,7 @@ pub fn string_to_f64(mut s: &WStr, swf_version: u8, strict: bool) -> Option<f64>
383385
// Finally, calculate the result.
384386
let mut result = if total_digits > 15 {
385387
// With more than 15 digits, avmplus uses integer arithmetic to avoid rounding errors.
386-
let mut result: i64 = 0;
388+
let mut result: BigInt = Zero::zero();
387389
let mut decimal_digits = -1;
388390
for c in s {
389391
if let Some(digit) = to_decimal_digit(c) {
@@ -408,7 +410,7 @@ pub fn string_to_f64(mut s: &WStr, swf_version: u8, strict: bool) -> Option<f64>
408410
result *= i64::pow(10, exponent as u32);
409411
}
410412

411-
result as f64
413+
result.to_f64().unwrap_or(f64::NAN)
412414
} else {
413415
let mut result = 0.0;
414416
let mut decimal_digits = -1;
@@ -1330,3 +1332,16 @@ impl<'gc> Value<'gc> {
13301332
Ok(Some(num_self < num_other))
13311333
}
13321334
}
1335+
1336+
#[cfg(test)]
1337+
mod tests {
1338+
use super::*;
1339+
1340+
#[test]
1341+
fn test_string_to_f64() {
1342+
assert_eq!(
1343+
string_to_f64(WStr::from_units(b"350000000000000000000"), 0, true),
1344+
Some(3.5e20)
1345+
);
1346+
}
1347+
}

0 commit comments

Comments
 (0)