• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Flags: --expose-internals
2'use strict';
3
4const { mustNotCall } = require('../common');
5const assert = require('assert');
6
7const {
8  RegExpPrototypeExec,
9  RegExpPrototypeSymbolReplace,
10  RegExpPrototypeSymbolSearch,
11  RegExpPrototypeSymbolSplit,
12  SafeStringPrototypeSearch,
13  hardenRegExp,
14} = require('internal/test/binding').primordials;
15
16const {
17  SideEffectFreeRegExpPrototypeExec,
18  SideEffectFreeRegExpPrototypeSymbolReplace,
19  SideEffectFreeRegExpPrototypeSymbolSplit,
20} = require('internal/util');
21
22
23Object.defineProperties(RegExp.prototype, {
24  [Symbol.match]: {
25    get: mustNotCall('get %RegExp.prototype%[@@match]'),
26    set: mustNotCall('set %RegExp.prototype%[@@match]'),
27  },
28  [Symbol.matchAll]: {
29    get: mustNotCall('get %RegExp.prototype%[@@matchAll]'),
30    set: mustNotCall('set %RegExp.prototype%[@@matchAll]'),
31  },
32  [Symbol.replace]: {
33    get: mustNotCall('get %RegExp.prototype%[@@replace]'),
34    set: mustNotCall('set %RegExp.prototype%[@@replace]'),
35  },
36  [Symbol.search]: {
37    get: mustNotCall('get %RegExp.prototype%[@@search]'),
38    set: mustNotCall('set %RegExp.prototype%[@@search]'),
39  },
40  [Symbol.split]: {
41    get: mustNotCall('get %RegExp.prototype%[@@split]'),
42    set: mustNotCall('set %RegExp.prototype%[@@split]'),
43  },
44  dotAll: {
45    get: mustNotCall('get %RegExp.prototype%.dotAll'),
46    set: mustNotCall('set %RegExp.prototype%.dotAll'),
47  },
48  exec: {
49    get: mustNotCall('get %RegExp.prototype%.exec'),
50    set: mustNotCall('set %RegExp.prototype%.exec'),
51  },
52  flags: {
53    get: mustNotCall('get %RegExp.prototype%.flags'),
54    set: mustNotCall('set %RegExp.prototype%.flags'),
55  },
56  global: {
57    get: mustNotCall('get %RegExp.prototype%.global'),
58    set: mustNotCall('set %RegExp.prototype%.global'),
59  },
60  hasIndices: {
61    get: mustNotCall('get %RegExp.prototype%.hasIndices'),
62    set: mustNotCall('set %RegExp.prototype%.hasIndices'),
63  },
64  ignoreCase: {
65    get: mustNotCall('get %RegExp.prototype%.ignoreCase'),
66    set: mustNotCall('set %RegExp.prototype%.ignoreCase'),
67  },
68  multiline: {
69    get: mustNotCall('get %RegExp.prototype%.multiline'),
70    set: mustNotCall('set %RegExp.prototype%.multiline'),
71  },
72  source: {
73    get: mustNotCall('get %RegExp.prototype%.source'),
74    set: mustNotCall('set %RegExp.prototype%.source'),
75  },
76  sticky: {
77    get: mustNotCall('get %RegExp.prototype%.sticky'),
78    set: mustNotCall('set %RegExp.prototype%.sticky'),
79  },
80  test: {
81    get: mustNotCall('get %RegExp.prototype%.test'),
82    set: mustNotCall('set %RegExp.prototype%.test'),
83  },
84  toString: {
85    get: mustNotCall('get %RegExp.prototype%.toString'),
86    set: mustNotCall('set %RegExp.prototype%.toString'),
87  },
88  unicode: {
89    get: mustNotCall('get %RegExp.prototype%.unicode'),
90    set: mustNotCall('set %RegExp.prototype%.unicode'),
91  },
92});
93
94hardenRegExp(hardenRegExp(/1/));
95
96// IMO there are no valid use cases in node core to use RegExpPrototypeSymbolMatch
97// or RegExpPrototypeSymbolMatchAll, they are inherently unsafe.
98
99assert.strictEqual(RegExpPrototypeExec(/foo/, 'bar'), null);
100assert.strictEqual(RegExpPrototypeExec(hardenRegExp(/foo/), 'bar'), null);
101assert.strictEqual(SideEffectFreeRegExpPrototypeExec(/foo/, 'bar'), null);
102assert.strictEqual(SideEffectFreeRegExpPrototypeExec(hardenRegExp(/foo/), 'bar'), null);
103{
104  const expected = ['bar'];
105  Object.defineProperties(expected, {
106    index: { __proto__: null, configurable: true, writable: true, enumerable: true, value: 0 },
107    input: { __proto__: null, configurable: true, writable: true, enumerable: true, value: 'bar' },
108    groups: { __proto__: null, configurable: true, writable: true, enumerable: true },
109  });
110  const actual = SideEffectFreeRegExpPrototypeExec(/bar/, 'bar');
111
112  // assert.deepStrictEqual(actual, expected) doesn't work for cross-realm comparison.
113
114  assert.strictEqual(Array.isArray(actual), Array.isArray(expected));
115  assert.deepStrictEqual(Reflect.ownKeys(actual), Reflect.ownKeys(expected));
116  for (const key of Reflect.ownKeys(expected)) {
117    assert.deepStrictEqual(
118      Reflect.getOwnPropertyDescriptor(actual, key),
119      Reflect.getOwnPropertyDescriptor(expected, key),
120    );
121  }
122}
123{
124  const myRegex = hardenRegExp(/a/);
125  assert.strictEqual(RegExpPrototypeSymbolReplace(myRegex, 'baar', 'e'), 'bear');
126}
127{
128  const myRegex = /a/;
129  assert.strictEqual(SideEffectFreeRegExpPrototypeSymbolReplace(myRegex, 'baar', 'e'), 'bear');
130}
131{
132  const myRegex = hardenRegExp(/a/g);
133  assert.strictEqual(RegExpPrototypeSymbolReplace(myRegex, 'baar', 'e'), 'beer');
134}
135{
136  const myRegex = /a/g;
137  assert.strictEqual(SideEffectFreeRegExpPrototypeSymbolReplace(myRegex, 'baar', 'e'), 'beer');
138}
139{
140  const myRegex = hardenRegExp(/a/);
141  assert.strictEqual(RegExpPrototypeSymbolSearch(myRegex, 'baar'), 1);
142}
143{
144  const myRegex = /a/;
145  assert.strictEqual(SafeStringPrototypeSearch('baar', myRegex), 1);
146}
147{
148  const myRegex = hardenRegExp(/a/);
149  assert.deepStrictEqual(RegExpPrototypeSymbolSplit(myRegex, 'baar', 0), []);
150}
151{
152  const myRegex = /a/;
153  const expected = [];
154  const actual = SideEffectFreeRegExpPrototypeSymbolSplit(myRegex, 'baar', 0);
155
156  // assert.deepStrictEqual(actual, expected) doesn't work for cross-realm comparison.
157
158  assert.strictEqual(Array.isArray(actual), Array.isArray(expected));
159  assert.deepStrictEqual(Reflect.ownKeys(actual), Reflect.ownKeys(expected));
160  for (const key of Reflect.ownKeys(expected)) {
161    assert.deepStrictEqual(
162      Reflect.getOwnPropertyDescriptor(actual, key),
163      Reflect.getOwnPropertyDescriptor(expected, key),
164    );
165  }
166}
167{
168  const myRegex = hardenRegExp(/a/);
169  assert.deepStrictEqual(RegExpPrototypeSymbolSplit(myRegex, 'baar', 1), ['b']);
170}
171{
172  const myRegex = hardenRegExp(/a/);
173  assert.deepStrictEqual(RegExpPrototypeSymbolSplit(myRegex, 'baar'), ['b', '', 'r']);
174}
175