Browse Source

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
v0.7.4-release
Ben Noordhuis 14 years ago
committed by Ryan Dahl
parent
commit
55c65cc2d5
  1. 16
      src/node.cc
  2. 9
      src/node.h
  3. 12
      src/node_buffer.cc
  4. 4
      src/node_cares.cc
  5. 4
      src/node_idle_watcher.cc
  6. 4
      src/node_io_watcher.cc
  7. 4
      src/node_script.cc
  8. 4
      src/node_signal_watcher.cc
  9. 4
      src/node_stat_watcher.cc
  10. 4
      src/node_timer.cc

16
src/node.cc

@ -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;

9
src/node.h

@ -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>();

12
src/node_buffer.cc

@ -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);

4
src/node_cares.cc

@ -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;

4
src/node_idle_watcher.cc

@ -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();

4
src/node_io_watcher.cc

@ -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());

4
src/node_script.cc

@ -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();

4
src/node_signal_watcher.cc

@ -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()) {

4
src/node_stat_watcher.cc

@ -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());

4
src/node_timer.cc

@ -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();

Loading…
Cancel
Save