Skip to content

Commit ef3889b

Browse files
committed
src: prevent URLPattern property accessors from crashing on invalid this
1 parent cadc4ed commit ef3889b

File tree

2 files changed

+63
-9
lines changed

2 files changed

+63
-9
lines changed

src/node_url_pattern.cc

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ using v8::Object;
2626
using v8::PropertyAttribute;
2727
using v8::ReadOnly;
2828
using v8::RegExp;
29+
using v8::Signature;
2930
using v8::String;
3031
using v8::Value;
3132

@@ -720,58 +721,71 @@ static void Initialize(Local<Object> target,
720721
auto prototype_template = ctor_tmpl->PrototypeTemplate();
721722
ctor_tmpl->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "URLPattern"));
722723

724+
// The signature is used to prevent the property accessors from being
725+
// called on the wrong receiver object (`this`)
726+
auto signature = Signature::New(isolate, ctor_tmpl);
727+
723728
instance_template->SetInternalFieldCount(URLPattern::kInternalFieldCount);
724729
prototype_template->SetAccessorProperty(
725730
env->protocol_string(),
726-
FunctionTemplate::New(isolate, URLPattern::Protocol),
731+
FunctionTemplate::New(
732+
isolate, URLPattern::Protocol, Local<Value>(), signature),
727733
Local<FunctionTemplate>(),
728734
attributes);
729735

730736
prototype_template->SetAccessorProperty(
731737
env->username_string(),
732-
FunctionTemplate::New(isolate, URLPattern::Username),
738+
FunctionTemplate::New(
739+
isolate, URLPattern::Username, Local<Value>(), signature),
733740
Local<FunctionTemplate>(),
734741
attributes);
735742

736743
prototype_template->SetAccessorProperty(
737744
env->password_string(),
738-
FunctionTemplate::New(isolate, URLPattern::Password),
745+
FunctionTemplate::New(
746+
isolate, URLPattern::Password, Local<Value>(), signature),
739747
Local<FunctionTemplate>(),
740748
attributes);
741749

742750
prototype_template->SetAccessorProperty(
743751
env->hostname_string(),
744-
FunctionTemplate::New(isolate, URLPattern::Hostname),
752+
FunctionTemplate::New(
753+
isolate, URLPattern::Hostname, Local<Value>(), signature),
745754
Local<FunctionTemplate>(),
746755
attributes);
747756

748757
prototype_template->SetAccessorProperty(
749758
env->port_string(),
750-
FunctionTemplate::New(isolate, URLPattern::Port),
759+
FunctionTemplate::New(
760+
isolate, URLPattern::Port, Local<Value>(), signature),
751761
Local<FunctionTemplate>(),
752762
attributes);
753763

754764
prototype_template->SetAccessorProperty(
755765
env->pathname_string(),
756-
FunctionTemplate::New(isolate, URLPattern::Pathname),
766+
FunctionTemplate::New(
767+
isolate, URLPattern::Pathname, Local<Value>(), signature),
757768
Local<FunctionTemplate>(),
758769
attributes);
759770

760771
prototype_template->SetAccessorProperty(
761772
env->search_string(),
762-
FunctionTemplate::New(isolate, URLPattern::Search),
773+
FunctionTemplate::New(
774+
isolate, URLPattern::Search, Local<Value>(), signature),
763775
Local<FunctionTemplate>(),
764776
attributes);
765777

766778
prototype_template->SetAccessorProperty(
767779
env->hash_string(),
768-
FunctionTemplate::New(isolate, URLPattern::Hash),
780+
FunctionTemplate::New(
781+
isolate, URLPattern::Hash, Local<Value>(), signature),
769782
Local<FunctionTemplate>(),
770783
attributes);
771784

772785
prototype_template->SetAccessorProperty(
773786
env->has_regexp_groups_string(),
774-
FunctionTemplate::New(isolate, URLPattern::HasRegexpGroups),
787+
FunctionTemplate::New(
788+
isolate, URLPattern::HasRegexpGroups, Local<Value>(), signature),
775789
Local<FunctionTemplate>(),
776790
attributes);
777791

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'use strict';
2+
3+
require('../common');
4+
5+
const { URLPattern } = require('url');
6+
const { throws } = require('assert');
7+
8+
const pattern = new URLPattern();
9+
const proto = Object.getPrototypeOf(pattern);
10+
11+
// Verifies that attempts to call the property getters on a URLPattern
12+
// with the incorrect `this` will not crash the process.
13+
[
14+
'protocol',
15+
'username',
16+
'password',
17+
'hostname',
18+
'port',
19+
'pathname',
20+
'search',
21+
'hash',
22+
'hasRegExpGroups',
23+
].forEach((i) => {
24+
const prop = Object.getOwnPropertyDescriptor(proto, i).get;
25+
throws(() => prop({}), {
26+
message: 'Illegal invocation',
27+
}, i);
28+
});
29+
30+
// Verifies that attempts to call the exec and test functions
31+
// with the wrong this also throw
32+
33+
const { test, exec } = pattern;
34+
35+
throws(() => test({}), {
36+
message: 'Illegal invocation',
37+
});
38+
throws(() => exec({}), {
39+
message: 'Illegal invocation',
40+
});

0 commit comments

Comments
 (0)