From 83c29bd8d785da029759dc354fc13810d44eb9c1 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sun, 7 Feb 2021 23:07:46 +0100 Subject: [PATCH] LibJS: Don't assume match for each capture group in RegExp.prototype.exec() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was not implementing the following part of the spec correctly: 27. For each integer i such that i ≥ 1 and i ≤ n, do a. Let captureI be ith element of r's captures List. b. If captureI is undefined, let capturedValue be undefined. Expecting a capture group match to exist for each of the RegExp's capture groups would assert in Vector's operator[] if that's not the case, for example: /(foo)(bar)?/.exec("foo") Append undefined instead. Fixes #5256. --- Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp | 8 ++++++-- .../Tests/builtins/RegExp/RegExp.prototype.exec.js | 10 ++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp index c1f6b2b5ad..a23174112b 100644 --- a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp @@ -190,8 +190,12 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::exec) array->indexed_properties().put(array, 0, js_string(vm, match.view.to_string())); for (size_t i = 0; i < result.n_capture_groups; ++i) { - auto& capture = result.capture_group_matches[0][i]; - array->indexed_properties().put(array, i + 1, js_string(vm, capture.view.to_string())); + auto capture_value = js_undefined(); + if (result.capture_group_matches[0].size() > i) { + auto& capture = result.capture_group_matches[0][i]; + capture_value = js_string(vm, capture.view.to_string()); + } + array->indexed_properties().put(array, i + 1, capture_value); } Value groups = js_undefined(); diff --git a/Userland/Libraries/LibJS/Tests/builtins/RegExp/RegExp.prototype.exec.js b/Userland/Libraries/LibJS/Tests/builtins/RegExp/RegExp.prototype.exec.js index 7fcbf3582a..5747ae487e 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/RegExp/RegExp.prototype.exec.js +++ b/Userland/Libraries/LibJS/Tests/builtins/RegExp/RegExp.prototype.exec.js @@ -18,6 +18,16 @@ test("basic unnamed captures", () => { expect(res[1]).toBe("ooooo"); expect(res.groups).toBe(undefined); expect(res.index).toBe(0); + + re = /(foo)(bar)?/; + res = re.exec("foo"); + + expect(res.length).toBe(3); + expect(res[0]).toBe("foo"); + expect(res[1]).toBe("foo"); + expect(res[2]).toBe(undefined); + expect(res.groups).toBe(undefined); + expect(res.index).toBe(0); }); test("basic named captures", () => {