From 9d4c49c6dde90400279bf3d05f2b2e8873a35b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borges?= Date: Thu, 8 Oct 2020 07:24:36 +0100 Subject: [PATCH] Fix 2 bugs that stopped test262 (#812) * Fix: Add check for length in Array.prototype.map * Fix: Make Array.prototype.reduceRight work for length 1 * Refactor: Cleanup Array.prototype.map to use usize for length --- boa/src/builtins/array/mod.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/boa/src/builtins/array/mod.rs b/boa/src/builtins/array/mod.rs index f25bbd3041..eee30daa4f 100644 --- a/boa/src/builtins/array/mod.rs +++ b/boa/src/builtins/array/mod.rs @@ -581,7 +581,7 @@ impl Array { /// /// [spec]: https://tc39.es/ecma262/#sec-array.prototype.map /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map - pub(crate) fn map(this: &Value, args: &[Value], interpreter: &mut Context) -> Result { + pub(crate) fn map(this: &Value, args: &[Value], context: &mut Context) -> Result { if args.is_empty() { return Err(Value::from( "missing argument 0 when calling function Array.prototype.map", @@ -591,16 +591,20 @@ impl Array { let callback = args.get(0).cloned().unwrap_or_else(Value::undefined); let this_val = args.get(1).cloned().unwrap_or_else(Value::undefined); - let length = this.get_field("length").as_number().unwrap() as i32; + let length = this.get_field("length").to_length(context)?; - let new = Self::new_array(interpreter)?; + if length > 2usize.pow(32) - 1 { + return context.throw_range_error("Invalid array length"); + } + + let new = Self::new_array(context)?; let values: Vec = (0..length) .map(|idx| { let element = this.get_field(idx); let args = [element, Value::from(idx), new.clone()]; - interpreter + context .call(&callback, &this_val, &args) .unwrap_or_else(|_| Value::undefined()) }) @@ -1113,12 +1117,13 @@ impl Array { ); } let result = this.get_field(k); - k -= 1; + k = k.overflowing_sub(1).0; result } else { initial_value }; - loop { + // usize::MAX is bigger than the maximum array size so we can use it check for integer undeflow + while k != usize::MAX { if this.has_field(k) { let arguments = [accumulator, this.get_field(k), Value::from(k), this.clone()]; accumulator = interpreter.call(&callback, &Value::undefined(), &arguments)?; @@ -1140,7 +1145,7 @@ impl Array { if k == 0 { break; } - k -= 1; + k = k.overflowing_sub(1).0; } Ok(accumulator) }