Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: don't set non-primitive values on templates #6228

Merged
merged 1 commit into from
Apr 18, 2016

Conversation

bnoordhuis
Copy link
Member

@bnoordhuis bnoordhuis commented Apr 15, 2016

V8 is going to disallow non-primitive values on v8::FunctionTemplate
and v8::ObjectTemplate because those can't be shared across contexts.
Hide such properties behind a getter.

Fixes: #6216

R=@nodejs/v8 @jeisinger

CI: https://ci.nodejs.org/job/node-test-pull-request/2279/

@bnoordhuis bnoordhuis added v8 engine Issues and PRs related to the V8 dependency. lib / src Issues and PRs related to general changes in the lib or src directory. dont-land-on-v5.x labels Apr 15, 2016
@bnoordhuis
Copy link
Member Author

I will say I don't really understand the point of this exercise. I can see why non-primitive values would be disallowed but I don't get why it's okay to side-step the issue through a getter.

@trevnorris
Copy link
Contributor

Spoke with @jeisinger recently who pointed me to Object::Clone(). Which does a shallow copy of the object, and is very fast to boot. Would it be instead possible to manually construct a new instance on startup, clone it, then set any different properties if needed. The operation also clones internal aligned indexed array fields. So should be able to use it with constructors like TCPWrap.

@indutny
Copy link
Member

indutny commented Apr 15, 2016

Feels really awkward, I don't understand why this is needed. However, it would be simpler to understand if the fix wouldn't be using getters. It looks like we are really trading one incorrect approach for another.

@jeisinger may I ask you to weigh in?

recv->Set(fn_name, fn);
auto getter = [](v8::Local<v8::String>,
const v8::PropertyCallbackInfo<v8::Value>& info) {
auto data = info.Data();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't really fix the issue.

Sorry if my initial description of the problem and the solution wasn't clear. I assume that the security aspect of cross-context leaks aren't much of a concern to node as node doesn't use contexts to separate different scripts that don't trust each other. The main concern here is memory leaks.

Templates are per-isolate objects, while non-primitive values are per context objects. By directly (or indirectly) putting a per-context value on a per-isolate value, you essentially disable GC for all objects in that context (as every non-primitive value keeps its context alive which in turn keeps any object in that context alive).

You might expect that instantiating a template creates a copy of all the values, but it does not, it just reuse the original value you've put in (as it's generally not possible to clean objects - think internal fields: the VM doesn't know whether it's safe to duplicate C pointers).

here, you already have a template for fn, you should can just recv->Set(fn_name, t);

when recv is instantiated, a function in the target context will be created using the t template.

@jeisinger
Copy link
Contributor

I hope my comments made the issue a bit clearer. Besides the leak there's also an correctness issue: If one context e.g. modifies the "methods" array, it'll be modified in all contexts.

The security issue is that you can get to the Array's constructor which is a function and from there to the function constructor which allows for executing arbitrary scripts in the context that the Array was created in.

Please let me know if you have further questions.

@bnoordhuis
Copy link
Member Author

Okay, that makes more sense. Updated, PTAL. CI: https://ci.nodejs.org/job/node-test-pull-request/2280/

@jeisinger
Copy link
Contributor

I don't have enough inside in the http module to assess whether the js changes are good, but the C++ parts LGTM

@bnoordhuis
Copy link
Member Author

Polished it a little. Collaborators, PTAL. CI: https://ci.nodejs.org/job/node-test-pull-request/2283/

@trevnorris
Copy link
Contributor

LGTM

@@ -937,6 +937,8 @@ void Template::Set(v8::Local<Name> name, v8::Local<Data> value,
i::Isolate* isolate = templ->GetIsolate();
ENTER_V8(isolate);
i::HandleScope scope(isolate);
auto value_obj = Utils::OpenHandle(*value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a back porting change?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I landed this in https://codereview.chromium.org/1839983002/ but then reverted it because it broke our node CI

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's from the commit drop! add v8 Template::Set check - I'm removing it before landing the PR. It might be nice to turn it into a warning so people know they'll need to update their add-ons.

@jeisinger
Copy link
Contributor

I could make it a DCHECK() first, but I'm not sure whether people run with DCHECKs enabled.

I could also introduce two new methods and deprecate Set() - one that takes a Template and one that takes a Primitive. Would that be preferable?

V8 is going to disallow non-primitive values on v8::FunctionTemplate
and v8::ObjectTemplate because those can't be shared across contexts.

Fixes: nodejs#6216
PR-URL: nodejs#6228
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
@bnoordhuis
Copy link
Member Author

Releases don't have DCHECKs enabled so that wouldn't help. The way most add-ons are built, they won't see V8 deprecation warnings today but that's something we can probably fix in node-gyp.

@bnoordhuis bnoordhuis closed this Apr 18, 2016
@bnoordhuis bnoordhuis deleted the fix6216 branch April 18, 2016 09:44
@bnoordhuis bnoordhuis merged commit 642076f into nodejs:master Apr 18, 2016
@bnoordhuis
Copy link
Member Author

PS: I filed #6232 for the Makefile changes.

@jeisinger
Copy link
Contributor

so you're saying adding the CHECK() back is good for now?

@bnoordhuis
Copy link
Member Author

If you do, are you going to cherry-pick it to v5.0? I was thinking of floating an out-of-tree patch that prints a warning and a stack trace, then give people the v6 release cycle to upgrade their add-ons.

@jeisinger
Copy link
Contributor

I won't cherry pick it. It will be part of v8 5.2

@bnoordhuis
Copy link
Member Author

That sounds fine. We wouldn't upgrade to that until v7 anyway.

@jasnell
Copy link
Member

jasnell commented Apr 20, 2016

Just FYI... looks like this broke at least one userland module that was depending on the undocumented process.binding('http_parser').HTTPParser.methods. Given that this is an undocumented private API breakage should be expected... however, there may be some other impacts down the road as well.

joelostrowski pushed a commit to joelostrowski/node that referenced this pull request Apr 25, 2016
V8 is going to disallow non-primitive values on v8::FunctionTemplate
and v8::ObjectTemplate because those can't be shared across contexts.

Fixes: nodejs#6216
PR-URL: nodejs#6228
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
jasnell pushed a commit that referenced this pull request Apr 26, 2016
V8 is going to disallow non-primitive values on v8::FunctionTemplate
and v8::ObjectTemplate because those can't be shared across contexts.

Fixes: #6216
PR-URL: #6228
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
@Qard Qard mentioned this pull request Apr 27, 2016
kkoopa pushed a commit to nodejs/nan that referenced this pull request Apr 27, 2016
See [0] and [1]: starting with node.js v6, setting non-primitive values
on FunctionTemplate and ObjectTemplate instances is discouraged; v7 will
downright disallow it.  Update `Nan::SetPrototypeMethod()`.

[0] nodejs/node#6216
[1] nodejs/node#6228
evanlucas added a commit to evanlucas/node-oniguruma that referenced this pull request Apr 28, 2016
See [0] and [1]: starting with node.js v6, setting non-primitive values
on FunctionTemplate and ObjectTemplate instances is discouraged; v7 will
downright disallow it. Update the code base.

[0] nodejs/node#6216
[1] nodejs/node#6228
amitparida added a commit to amitparida/npm-nan that referenced this pull request Oct 3, 2024
See [0] and [1]: starting with node.js v6, setting non-primitive values
on FunctionTemplate and ObjectTemplate instances is discouraged; v7 will
downright disallow it.  Update `Nan::SetPrototypeMethod()`.

[0] nodejs/node#6216
[1] nodejs/node#6228
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lib / src Issues and PRs related to general changes in the lib or src directory. v8 engine Issues and PRs related to the V8 dependency.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants