Browse Source

Fixed some extra regex panics (#1031)

pull/1036/head
Iban Eguia 4 years ago committed by GitHub
parent
commit
553ea529f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 76
      boa/src/builtins/regexp/mod.rs
  2. 4
      boa/src/object/internal_methods.rs

76
boa/src/builtins/regexp/mod.rs

@ -317,14 +317,18 @@ impl RegExp {
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.test /// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.test
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test
pub(crate) fn test(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> { pub(crate) fn test(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let mut last_index = this.get_field("lastIndex", context)?.to_index(context)?;
let result = if let Some(object) = this.as_object() {
// 3. Let string be ? ToString(S).
let arg_str = args let arg_str = args
.get(0) .get(0)
.expect("could not get argument") .cloned()
.unwrap_or_default()
.to_string(context)?; .to_string(context)?;
let mut last_index = this.get_field("lastIndex", context)?.to_index(context)?;
let result = if let Some(object) = this.as_object() { // 4. Let match be ? RegExpExec(R, string).
let object = object.borrow(); let object = object.borrow();
let regex = object.as_regexp().unwrap(); if let Some(regex) = object.as_regexp() {
let result = let result =
if let Some(m) = regex.matcher.find_from(arg_str.as_str(), last_index).next() { if let Some(m) = regex.matcher.find_from(arg_str.as_str(), last_index).next() {
if regex.use_last_index { if regex.use_last_index {
@ -337,9 +341,17 @@ impl RegExp {
} }
false false
}; };
// 5. If match is not null, return true; else return false.
Ok(Value::boolean(result)) Ok(Value::boolean(result))
} else { } else {
panic!("object is not a regexp") return context
.throw_type_error("RegExp.prototype.exec method called on incompatible value");
}
} else {
// 2. If Type(R) is not Object, throw a TypeError exception.
return context
.throw_type_error("RegExp.prototype.exec method called on incompatible value");
}; };
this.set_field("lastIndex", Value::from(last_index), context)?; this.set_field("lastIndex", Value::from(last_index), context)?;
result result
@ -358,14 +370,18 @@ impl RegExp {
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.exec /// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.exec
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec
pub(crate) fn exec(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> { pub(crate) fn exec(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let arg_str = args // 4. Return ? RegExpBuiltinExec(R, S).
.get(0)
.expect("could not get argument")
.to_string(context)?;
let mut last_index = this.get_field("lastIndex", context)?.to_index(context)?; let mut last_index = this.get_field("lastIndex", context)?.to_index(context)?;
let result = if let Some(object) = this.as_object() { let result = if let Some(object) = this.as_object() {
let object = object.borrow(); let object = object.borrow();
let regex = object.as_regexp().unwrap(); if let Some(regex) = object.as_regexp() {
// 3. Let S be ? ToString(string).
let arg_str = args
.get(0)
.cloned()
.unwrap_or_default()
.to_string(context)?;
let result = { let result = {
if let Some(m) = regex.matcher.find_from(arg_str.as_str(), last_index).next() { if let Some(m) = regex.matcher.find_from(arg_str.as_str(), last_index).next() {
if regex.use_last_index { if regex.use_last_index {
@ -384,8 +400,12 @@ impl RegExp {
} }
let result = Value::from(result); let result = Value::from(result);
result.set_property("index", DataDescriptor::new(m.start(), Attribute::all())); result.set_property(
result.set_property("input", DataDescriptor::new(arg_str, Attribute::all())); "index",
DataDescriptor::new(m.start(), Attribute::all()),
);
result
.set_property("input", DataDescriptor::new(arg_str, Attribute::all()));
result result
} else { } else {
if regex.use_last_index { if regex.use_last_index {
@ -394,10 +414,17 @@ impl RegExp {
Value::null() Value::null()
} }
}; };
Ok(result) Ok(result)
} else { } else {
panic!("object is not a regexp") // 2. Perform ? RequireInternalSlot(R, [[RegExpMatcher]]).
context
.throw_type_error("RegExp.prototype.exec method called on incompatible value")
}
} else {
return context.throw_type_error("exec method called on incompatible value");
}; };
this.set_field("lastIndex", Value::from(last_index), context)?; this.set_field("lastIndex", Value::from(last_index), context)?;
result result
} }
@ -415,10 +442,15 @@ impl RegExp {
pub(crate) fn r#match(this: &Value, arg: RcString, context: &mut Context) -> Result<Value> { pub(crate) fn r#match(this: &Value, arg: RcString, context: &mut Context) -> Result<Value> {
let (matcher, flags) = if let Some(object) = this.as_object() { let (matcher, flags) = if let Some(object) = this.as_object() {
let object = object.borrow(); let object = object.borrow();
let regex = object.as_regexp().unwrap(); if let Some(regex) = object.as_regexp() {
(regex.matcher.clone(), regex.flags.clone()) (regex.matcher.clone(), regex.flags.clone())
} else { } else {
panic!("object is not a regexp") return context
.throw_type_error("RegExp.prototype.exec method called on incompatible value");
}
} else {
return context
.throw_type_error("RegExp.prototype.match method called on incompatible value");
}; };
if flags.contains('g') { if flags.contains('g') {
let mut matches = Vec::new(); let mut matches = Vec::new();
@ -473,7 +505,7 @@ impl RegExp {
pub(crate) fn match_all(this: &Value, arg_str: String, context: &mut Context) -> Result<Value> { pub(crate) fn match_all(this: &Value, arg_str: String, context: &mut Context) -> Result<Value> {
let matches = if let Some(object) = this.as_object() { let matches = if let Some(object) = this.as_object() {
let object = object.borrow(); let object = object.borrow();
let regex = object.as_regexp().unwrap(); if let Some(regex) = object.as_regexp() {
let mut matches = Vec::new(); let mut matches = Vec::new();
for mat in regex.matcher.find_iter(&arg_str) { for mat in regex.matcher.find_iter(&arg_str) {
@ -487,7 +519,8 @@ impl RegExp {
let match_val = Value::from(match_vec); let match_val = Value::from(match_vec);
match_val.set_property("index", DataDescriptor::new(mat.start(), Attribute::all())); match_val
.set_property("index", DataDescriptor::new(mat.start(), Attribute::all()));
match_val.set_property( match_val.set_property(
"input", "input",
DataDescriptor::new(arg_str.clone(), Attribute::all()), DataDescriptor::new(arg_str.clone(), Attribute::all()),
@ -501,7 +534,14 @@ impl RegExp {
matches matches
} else { } else {
panic!("object is not a regexp") return context.throw_type_error(
"RegExp.prototype.match_all method called on incompatible value",
);
}
} else {
return context.throw_type_error(
"RegExp.prototype.match_all method called on incompatible value",
);
}; };
let length = matches.len(); let length = matches.len();

4
boa/src/object/internal_methods.rs

@ -246,6 +246,7 @@ impl GcObject {
/// ///
/// [spec]: https://tc39.es/ecma262/#table-essential-internal-methods /// [spec]: https://tc39.es/ecma262/#table-essential-internal-methods
#[inline] #[inline]
#[track_caller]
pub fn own_property_keys(&self) -> Vec<PropertyKey> { pub fn own_property_keys(&self) -> Vec<PropertyKey> {
self.borrow().keys().collect() self.borrow().keys().collect()
} }
@ -330,12 +331,14 @@ impl GcObject {
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getprototypeof /// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getprototypeof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf
#[inline] #[inline]
#[track_caller]
pub fn get_prototype_of(&self) -> Value { pub fn get_prototype_of(&self) -> Value {
self.borrow().prototype.clone() self.borrow().prototype.clone()
} }
/// Helper function for property insertion. /// Helper function for property insertion.
#[inline] #[inline]
#[track_caller]
pub(crate) fn insert<K, P>(&mut self, key: K, property: P) -> Option<PropertyDescriptor> pub(crate) fn insert<K, P>(&mut self, key: K, property: P) -> Option<PropertyDescriptor>
where where
K: Into<PropertyKey>, K: Into<PropertyKey>,
@ -346,6 +349,7 @@ impl GcObject {
/// Helper function for property removal. /// Helper function for property removal.
#[inline] #[inline]
#[track_caller]
pub(crate) fn remove(&mut self, key: &PropertyKey) -> Option<PropertyDescriptor> { pub(crate) fn remove(&mut self, key: &PropertyKey) -> Option<PropertyDescriptor> {
self.borrow_mut().remove(key) self.borrow_mut().remove(key)
} }

Loading…
Cancel
Save