Skip to content

Commit e72c094

Browse files
committed
net: add fd protection, fix #3604
1 parent be65f5f commit e72c094

File tree

4 files changed

+42
-0
lines changed

4 files changed

+42
-0
lines changed

lib/net.js

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const exceptionWithHostPort = util._exceptionWithHostPort;
2626
function noop() {}
2727

2828
function createHandle(fd) {
29+
if (TTYWrap.fdProtected(fd)) throw new Error('fd is being protected');
2930
var type = TTYWrap.guessHandleType(fd);
3031
if (type === 'PIPE') return new Pipe();
3132
if (type === 'TCP') return new TCP();

src/tty_wrap.cc

+15
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ void TTYWrap::Initialize(Local<Object> target,
4545

4646
env->SetMethod(target, "isTTY", IsTTY);
4747
env->SetMethod(target, "guessHandleType", GuessHandleType);
48+
env->SetMethod(target, "fdProtected", FdProtected);
4849

4950
target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "TTY"), t->GetFunction());
5051
env->set_tty_constructor_template(t);
@@ -78,6 +79,20 @@ void TTYWrap::GuessHandleType(const FunctionCallbackInfo<Value>& args) {
7879
args.GetReturnValue().Set(OneByteString(env->isolate(), type));
7980
}
8081

82+
void TTYWrap::FdProtected(const FunctionCallbackInfo<Value>& args) {
83+
Environment* env = Environment::GetCurrent(args);
84+
int32_t fd = args[0]->Int32Value();
85+
CHECK_GE(fd, 0);
86+
87+
uv_loop_t* loop = env->event_loop();
88+
bool ret = false;
89+
90+
if (static_cast<unsigned>(fd) < loop->nwatchers &&
91+
loop->watchers[fd] != NULL)
92+
ret = true;
93+
94+
args.GetReturnValue().Set(ret);
95+
}
8196

8297
void TTYWrap::IsTTY(const FunctionCallbackInfo<Value>& args) {
8398
int fd = args[0]->Int32Value();

src/tty_wrap.h

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class TTYWrap : public StreamWrap {
2424
bool readable);
2525

2626
static void GuessHandleType(const v8::FunctionCallbackInfo<v8::Value>& args);
27+
static void FdProtected(const v8::FunctionCallbackInfo<v8::Value>& args);
2728
static void IsTTY(const v8::FunctionCallbackInfo<v8::Value>& args);
2829
static void GetWindowSize(const v8::FunctionCallbackInfo<v8::Value>& args);
2930
static void SetRawMode(const v8::FunctionCallbackInfo<v8::Value>& args);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const net = require('net');
5+
6+
var will_throw = function() {
7+
var errors = [];
8+
[ 3, 4, 5, 6, 7, 8, 9 ].forEach(function(fd) {
9+
try {
10+
var stream = new net.Socket({
11+
fd: fd,
12+
readable: false,
13+
writable: true
14+
});
15+
stream.on('error', function() {});
16+
stream.write('might crash');
17+
} catch (e) {
18+
errors.push(e);
19+
}
20+
});
21+
throw errors;
22+
};
23+
24+
// Should throw instead of crash
25+
assert.throws(will_throw, /fd is being protected/);

0 commit comments

Comments
 (0)