Skip to content

Commit f7411b5

Browse files
joyeecheungMylesBorins
authored andcommitted
src: make StreamBase prototype accessors robust
This PR makes the prototype accessors added by StreamBase::AddMethods nonenumerable and checks the signatures in the accessors so they throw instead of raising assertions when called with incompatible receivers. They could be enumerated when inspecting the prototype with util.inspect or the inspector protocol. PR-URL: #16860 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
1 parent 0d4f62c commit f7411b5

3 files changed

+57
-4
lines changed

src/stream_base-inl.h

+11-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace node {
1313

14+
using v8::AccessorSignature;
1415
using v8::External;
1516
using v8::FunctionCallbackInfo;
1617
using v8::FunctionTemplate;
@@ -31,27 +32,33 @@ void StreamBase::AddMethods(Environment* env,
3132
HandleScope scope(env->isolate());
3233

3334
enum PropertyAttribute attributes =
34-
static_cast<PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
35+
static_cast<PropertyAttribute>(
36+
v8::ReadOnly | v8::DontDelete | v8::DontEnum);
37+
Local<AccessorSignature> signature =
38+
AccessorSignature::New(env->isolate(), t);
3539
t->PrototypeTemplate()->SetAccessor(env->fd_string(),
3640
GetFD<Base>,
3741
nullptr,
3842
env->as_external(),
3943
v8::DEFAULT,
40-
attributes);
44+
attributes,
45+
signature);
4146

4247
t->PrototypeTemplate()->SetAccessor(env->external_stream_string(),
4348
GetExternal<Base>,
4449
nullptr,
4550
env->as_external(),
4651
v8::DEFAULT,
47-
attributes);
52+
attributes,
53+
signature);
4854

4955
t->PrototypeTemplate()->SetAccessor(env->bytes_read_string(),
5056
GetBytesRead<Base>,
5157
nullptr,
5258
env->as_external(),
5359
v8::DEFAULT,
54-
attributes);
60+
attributes,
61+
signature);
5562

5663
env->SetProtoMethod(t, "readStart", JSMethod<Base, &StreamBase::ReadStart>);
5764
env->SetProtoMethod(t, "readStop", JSMethod<Base, &StreamBase::ReadStop>);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
'use strict';
2+
3+
require('../common');
4+
5+
// This tests that the prototype accessors added by StreamBase::AddMethods
6+
// are not enumerable. They could be enumerated when inspecting the prototype
7+
// with util.inspect or the inspector protocol.
8+
9+
const assert = require('assert');
10+
11+
// Or anything that calls StreamBase::AddMethods when setting up its prototype
12+
const TTY = process.binding('tty_wrap').TTY;
13+
14+
{
15+
assert.strictEqual(TTY.prototype.propertyIsEnumerable('bytesRead'), false);
16+
assert.strictEqual(TTY.prototype.propertyIsEnumerable('fd'), false);
17+
assert.strictEqual(
18+
TTY.prototype.propertyIsEnumerable('_externalStream'), false);
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'use strict';
2+
3+
require('../common');
4+
5+
// This tests that the prototype accessors added by StreamBase::AddMethods
6+
// do not raise assersions when called with incompatible receivers.
7+
8+
const assert = require('assert');
9+
10+
// Or anything that calls StreamBase::AddMethods when setting up its prototype
11+
const TTY = process.binding('tty_wrap').TTY;
12+
13+
// Should throw instead of raise assertions
14+
{
15+
const msg = /TypeError: Method \w+ called on incompatible receiver/;
16+
assert.throws(() => {
17+
TTY.prototype.bytesRead;
18+
}, msg);
19+
20+
assert.throws(() => {
21+
TTY.prototype.fd;
22+
}, msg);
23+
24+
assert.throws(() => {
25+
TTY.prototype._externalStream;
26+
}, msg);
27+
}

0 commit comments

Comments
 (0)