Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Safe constructor for ObjectWrapped classes
New() methods should be invoked as constructors, not regular functions.
Corner cases like Script::New() may cause a SIGSEGV when the GC is run.

More details: http://groups.google.com/group/nodejs/browse_thread/thread/a7e5db68d4cd6356
  • Loading branch information
bnoordhuis authored and ry committed Sep 29, 2010
1 parent 9911629 commit 55c65cc
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 9 deletions.
16 changes: 16 additions & 0 deletions src/node.cc
Expand Up @@ -787,6 +787,22 @@ Local<Value> ErrnoException(int errorno,
} }




Handle<Value> FromConstructorTemplate(Persistent<FunctionTemplate>& t,
const Arguments& args) {
HandleScope scope;

const int argc = args.Length();
Local<Value> argv[argc];

for (int i = 0; i < argc; ++i) {
argv[i] = args[i];
}

Local<Object> instance = t->GetFunction()->NewInstance(argc, argv);
return scope.Close(instance);
}


enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) { enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
HandleScope scope; HandleScope scope;


Expand Down
9 changes: 9 additions & 0 deletions src/node.h
Expand Up @@ -65,6 +65,15 @@ ssize_t DecodeWrite(char *buf,
v8::Local<v8::Object> BuildStatsObject(struct stat * s); v8::Local<v8::Object> BuildStatsObject(struct stat * s);




/**
* Call this when your constructor is invoked as a regular function, e.g. Buffer(10) instead of new Buffer(10).
* @param constructorTemplate Constructor template to instantiate from.
* @param args The arguments object passed to your constructor.
* @see v8::Arguments::IsConstructCall
*/
v8::Handle<v8::Value> FromConstructorTemplate(v8::Persistent<v8::FunctionTemplate>& constructorTemplate, const v8::Arguments& args);


static inline v8::Persistent<v8::Function>* cb_persist( static inline v8::Persistent<v8::Function>* cb_persist(
const v8::Local<v8::Value> &v) { const v8::Local<v8::Value> &v) {
v8::Persistent<v8::Function> *fn = new v8::Persistent<v8::Function>(); v8::Persistent<v8::Function> *fn = new v8::Persistent<v8::Function>();
Expand Down
12 changes: 3 additions & 9 deletions src/node_buffer.cc
Expand Up @@ -127,18 +127,12 @@ size_t Buffer::Length(Handle<Object> obj) {




Handle<Value> Buffer::New(const Arguments &args) { Handle<Value> Buffer::New(const Arguments &args) {
HandleScope scope;

if (!args.IsConstructCall()) { if (!args.IsConstructCall()) {
Local<Value> argv[10]; return FromConstructorTemplate(constructor_template, args);
for (int i = 0; i < MIN(args.Length(), 10); i++) {
argv[i] = args[i];
}
Local<Object> instance =
constructor_template->GetFunction()->NewInstance(args.Length(), argv);
return scope.Close(instance);
} }


HandleScope scope;

Buffer *buffer; Buffer *buffer;
if (args[0]->IsInt32()) { if (args[0]->IsInt32()) {
// var buffer = new Buffer(1024); // var buffer = new Buffer(1024);
Expand Down
4 changes: 4 additions & 0 deletions src/node_cares.cc
Expand Up @@ -459,6 +459,10 @@ void Channel::Initialize(Handle<Object> target) {




Handle<Value> Channel::New(const Arguments& args) { Handle<Value> Channel::New(const Arguments& args) {
if (!args.IsConstructCall()) {
return FromConstructorTemplate(constructor_template, args);
}

HandleScope scope; HandleScope scope;


struct ares_options options; struct ares_options options;
Expand Down
4 changes: 4 additions & 0 deletions src/node_idle_watcher.cc
Expand Up @@ -77,6 +77,10 @@ void IdleWatcher::Callback(EV_P_ ev_idle *w, int revents) {
// idle.start(); // idle.start();
// //
Handle<Value> IdleWatcher::New(const Arguments& args) { Handle<Value> IdleWatcher::New(const Arguments& args) {
if (!args.IsConstructCall()) {
return FromConstructorTemplate(constructor_template, args);
}

HandleScope scope; HandleScope scope;


IdleWatcher *s = new IdleWatcher(); IdleWatcher *s = new IdleWatcher();
Expand Down
4 changes: 4 additions & 0 deletions src/node_io_watcher.cc
Expand Up @@ -68,6 +68,10 @@ void IOWatcher::Callback(EV_P_ ev_io *w, int revents) {
// io.start(); // io.start();
// //
Handle<Value> IOWatcher::New(const Arguments& args) { Handle<Value> IOWatcher::New(const Arguments& args) {
if (!args.IsConstructCall()) {
return FromConstructorTemplate(constructor_template, args);
}

HandleScope scope; HandleScope scope;
IOWatcher *s = new IOWatcher(); IOWatcher *s = new IOWatcher();
s->Wrap(args.This()); s->Wrap(args.This());
Expand Down
4 changes: 4 additions & 0 deletions src/node_script.cc
Expand Up @@ -78,6 +78,10 @@ void node::Script::Initialize (Handle<Object> target) {




Handle<Value> node::Script::New (const Arguments& args) { Handle<Value> node::Script::New (const Arguments& args) {
if (!args.IsConstructCall()) {
return FromConstructorTemplate(constructor_template, args);
}

HandleScope scope; HandleScope scope;


node::Script *t = new node::Script(); node::Script *t = new node::Script();
Expand Down
4 changes: 4 additions & 0 deletions src/node_signal_watcher.cc
Expand Up @@ -51,6 +51,10 @@ void SignalWatcher::Callback(EV_P_ ev_signal *watcher, int revents) {
} }


Handle<Value> SignalWatcher::New(const Arguments& args) { Handle<Value> SignalWatcher::New(const Arguments& args) {
if (!args.IsConstructCall()) {
return FromConstructorTemplate(constructor_template, args);
}

HandleScope scope; HandleScope scope;


if (args.Length() != 1 || !args[0]->IsInt32()) { if (args.Length() != 1 || !args[0]->IsInt32()) {
Expand Down
4 changes: 4 additions & 0 deletions src/node_stat_watcher.cc
Expand Up @@ -46,6 +46,10 @@ void StatWatcher::Callback(EV_P_ ev_stat *watcher, int revents) {




Handle<Value> StatWatcher::New(const Arguments& args) { Handle<Value> StatWatcher::New(const Arguments& args) {
if (!args.IsConstructCall()) {
return FromConstructorTemplate(constructor_template, args);
}

HandleScope scope; HandleScope scope;
StatWatcher *s = new StatWatcher(); StatWatcher *s = new StatWatcher();
s->Wrap(args.Holder()); s->Wrap(args.Holder());
Expand Down
4 changes: 4 additions & 0 deletions src/node_timer.cc
Expand Up @@ -97,6 +97,10 @@ Timer::~Timer ()
Handle<Value> Handle<Value>
Timer::New (const Arguments& args) Timer::New (const Arguments& args)
{ {
if (!args.IsConstructCall()) {
return FromConstructorTemplate(constructor_template, args);
}

HandleScope scope; HandleScope scope;


Timer *t = new Timer(); Timer *t = new Timer();
Expand Down

0 comments on commit 55c65cc

Please sign in to comment.