{"action":"created","issue":{"url":"https://api.github.com/repos/joyent/node/issues/7120","labels_url":"https://api.github.com/repos/joyent/node/issues/7120/labels{/name}","comments_url":"https://api.github.com/repos/joyent/node/issues/7120/comments","events_url":"https://api.github.com/repos/joyent/node/issues/7120/events","html_url":"https://github.com/joyent/node/issues/7120","id":27597986,"number":7120,"title":"vm: v8 crashing on stack overflow","user":{"login":"orangemocha","id":1625870,"avatar_url":"https://avatars.githubusercontent.com/u/1625870?v=3","gravatar_id":"","url":"https://api.github.com/users/orangemocha","html_url":"https://github.com/orangemocha","followers_url":"https://api.github.com/users/orangemocha/followers","following_url":"https://api.github.com/users/orangemocha/following{/other_user}","gists_url":"https://api.github.com/users/orangemocha/gists{/gist_id}","starred_url":"https://api.github.com/users/orangemocha/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/orangemocha/subscriptions","organizations_url":"https://api.github.com/users/orangemocha/orgs","repos_url":"https://api.github.com/users/orangemocha/repos","events_url":"https://api.github.com/users/orangemocha/events{/privacy}","received_events_url":"https://api.github.com/users/orangemocha/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/joyent/node/labels/V8","name":"V8","color":"e102d8"},{"url":"https://api.github.com/repos/joyent/node/labels/vm","name":"vm","color":"e10c02"}],"state":"open","locked":false,"assignee":{"login":"tjfontaine","id":146447,"avatar_url":"https://avatars.githubusercontent.com/u/146447?v=3","gravatar_id":"","url":"https://api.github.com/users/tjfontaine","html_url":"https://github.com/tjfontaine","followers_url":"https://api.github.com/users/tjfontaine/followers","following_url":"https://api.github.com/users/tjfontaine/following{/other_user}","gists_url":"https://api.github.com/users/tjfontaine/gists{/gist_id}","starred_url":"https://api.github.com/users/tjfontaine/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tjfontaine/subscriptions","organizations_url":"https://api.github.com/users/tjfontaine/orgs","repos_url":"https://api.github.com/users/tjfontaine/repos","events_url":"https://api.github.com/users/tjfontaine/events{/privacy}","received_events_url":"https://api.github.com/users/tjfontaine/received_events","type":"User","site_admin":false},"milestone":null,"comments":2,"created_at":"2014-02-14T14:18:34Z","updated_at":"2015-05-28T22:54:15Z","closed_at":null,"body":"This issue is the cause of unit test's test-vm-infinite-recursion.js recent failures on Windows. Note that to reproduce this failure you have to compile node/v8 passing the nosnapshot option.\r\n\r\nThe test is supposed to cause a stack overflow. In some cases, when the the stack limit is reached while creating a new context, v8 will AV instead of raising the expected RangeError exception. \r\n\r\nThis is the problematic call stack:\r\n```\r\n \tnode.exe!v8::internal::NameDictionary::FindEntry(v8::internal::Name * key)  Line 14014\tC++\r\n \tnode.exe!v8::internal::JSObject::LocalLookupRealNamedProperty(v8::internal::Name * name, v8::internal::LookupResult * result)  Line 3371 + 0x13 bytes\tC++\r\n \tnode.exe!v8::internal::JSReceiver::LocalLookup(v8::internal::Name * name, v8::internal::LookupResult * result, bool search_hidden_prototypes)  Line 6026\tC++\r\n \tnode.exe!v8::internal::JSReceiver::Lookup(v8::internal::Name * name, v8::internal::LookupResult * result)  Line 6044\tC++\r\n \tnode.exe!v8::internal::Object::Lookup(v8::internal::Name * name, v8::internal::LookupResult * result)  Line 143\tC++\r\n \tnode.exe!v8::internal::Object::GetPropertyWithReceiver(v8::internal::Object * receiver, v8::internal::Name * name, PropertyAttributes * attributes)  Line 165\tC++\r\n \tnode.exe!v8::internal::Object::GetProperty(v8::internal::Name * key)  Line 941\tC++\r\n \tnode.exe!v8::internal::Runtime::GetObjectProperty(v8::internal::Isolate * isolate, v8::internal::Handle<v8::internal::Object> object, v8::internal::Handle<v8::internal::Object> key)  Line 4899 + 0x18 bytes\tC++\r\n \tnode.exe!v8::internal::GetProperty(v8::internal::Isolate * isolate, v8::internal::Handle<v8::internal::Object> obj, v8::internal::Handle<v8::internal::Object> key)  Line 228 + 0x2b bytes\tC++\r\n>\tnode.exe!v8::internal::Isolate::StackOverflow()  Line 1098 + 0x3c bytes\tC++\r\n \tnode.exe!v8::internal::Parser::DoParseProgram(v8::internal::CompilationInfo * info, v8::internal::Handle<v8::internal::String> source)  Line 694\tC++\r\n \tnode.exe!v8::internal::Parser::ParseProgram()  Line 593 + 0x15 bytes\tC++\r\n \tnode.exe!v8::internal::Parser::Parse()  Line 5852 + 0x8 bytes\tC++\r\n \tnode.exe!v8::internal::MakeFunctionInfo(v8::internal::CompilationInfo * info)  Line 666 + 0xb bytes\tC++\r\n \tnode.exe!v8::internal::Compiler::Compile(v8::internal::Handle<v8::internal::String> source, v8::internal::Handle<v8::internal::Object> script_name, int line_offset, int column_offset, bool is_shared_cross_origin, v8::internal::Handle<v8::internal::Context> context, v8::Extension * extension, v8::internal::ScriptDataImpl * pre_data, v8::internal::Handle<v8::internal::Object> script_data, v8::internal::NativesFlag natives)  Line 813 + 0x13 bytes\tC++\r\n \tnode.exe!v8::internal::Genesis::CompileScriptCached(v8::internal::Isolate * isolate, v8::internal::Vector<char const > name, v8::internal::Handle<v8::internal::String> source, v8::internal::SourceCodeCache * cache, v8::Extension * extension, v8::internal::Handle<v8::internal::Context> top_context, bool use_runtime_context)  Line 1520 + 0x67 bytes\tC++\r\n \tnode.exe!v8::internal::Genesis::CompileNative(v8::internal::Isolate * isolate, v8::internal::Vector<char const > name, v8::internal::Handle<v8::internal::String> source)  Line 1484 + 0x2f bytes\tC++\r\n \tnode.exe!v8::internal::Genesis::CompileBuiltin(v8::internal::Isolate * isolate, int index)  Line 1451 + 0x15 bytes\tC++\r\n \tnode.exe!v8::internal::Genesis::InstallNatives()  Line 1904 + 0x15 bytes\tC++\r\n \tnode.exe!v8::internal::Genesis::Genesis(v8::internal::Isolate * isolate, v8::internal::Handle<v8::internal::Object> global_object, v8::Handle<v8::ObjectTemplate> global_template, v8::ExtensionConfiguration * extensions)  Line 2626 + 0x8 bytes\tC++\r\n \tnode.exe!v8::internal::Bootstrapper::CreateEnvironment(v8::internal::Handle<v8::internal::Object> global_object, v8::Handle<v8::ObjectTemplate> global_template, v8::ExtensionConfiguration * extensions)  Line 313 + 0x1a bytes\tC++\r\n \tnode.exe!v8::CreateEnvironment(v8::internal::Isolate * isolate, v8::ExtensionConfiguration * extensions, v8::Handle<v8::ObjectTemplate> global_template, v8::Handle<v8::Value> global_object)  Line 5179 + 0x35 bytes\tC++\r\n \tnode.exe!v8::Context::New(v8::Isolate * external_isolate, v8::ExtensionConfiguration * extensions, v8::Handle<v8::ObjectTemplate> global_template, v8::Handle<v8::Value> global_object)  Line 5208 + 0x19 bytes\tC++\r\n \tnode.exe!node::ContextifyContext::CreateV8Context(node::Environment * env)  Line 218 + 0x27 bytes\tC++\r\n```\r\nThe stack overflow is hit before the boilerplate stack overflow exception (see kStackOverflowBoilerplate) has been created and added to the builtins object. Ironically, the script we are parsing when overflowing is messages.js, which is the one that would set up the stack overflow boilerplate exception.\r\n\r\nThere are at least two places during context creation and before the stack overflow where v8 code is sort of trying to handle this scenario. The code is the same both place (Genesis::Genesis and  Genesis::CompileNative):\r\n```\r\n  // During genesis, the boilerplate for stack overflow won't work until the\r\n  // environment has been at least partially initialized. Add a stack check\r\n  // before entering JS code to catch overflow early.\r\n  StackLimitCheck check(isolate);\r\n  if (check.HasOverflowed()) return;\r\n```\r\n\r\nHowever, this code is only checking the current stack usage against the limit. The fact that we haven't overflown yet doesn't mean that we won't overflow later on.\r\n\r\nI think v8 should implement a version of StackLimitCheck that takes a reserve as argument, i.e. a number bytes to subtract from the current stack pointer before checking against the stack limit. Basically, if we know that parsing messages.js requires less than -say- 2k of stack, then we can check early if we have enough stack left to get through with compilation. \r\n\r\nI am not sure about the process for reporting bugs to v8 :) Let me know how you'd like to handle this. I could also suggest a patch to v8."},"comment":{"url":"https://api.github.com/repos/joyent/node/issues/comments/106621654","html_url":"https://github.com/joyent/node/issues/7120#issuecomment-106621654","issue_url":"https://api.github.com/repos/joyent/node/issues/7120","id":106621654,"user":{"login":"jasnell","id":439929,"avatar_url":"https://avatars.githubusercontent.com/u/439929?v=3","gravatar_id":"","url":"https://api.github.com/users/jasnell","html_url":"https://github.com/jasnell","followers_url":"https://api.github.com/users/jasnell/followers","following_url":"https://api.github.com/users/jasnell/following{/other_user}","gists_url":"https://api.github.com/users/jasnell/gists{/gist_id}","starred_url":"https://api.github.com/users/jasnell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jasnell/subscriptions","organizations_url":"https://api.github.com/users/jasnell/orgs","repos_url":"https://api.github.com/users/jasnell/repos","events_url":"https://api.github.com/users/jasnell/events{/privacy}","received_events_url":"https://api.github.com/users/jasnell/received_events","type":"User","site_admin":false},"created_at":"2015-05-28T22:54:15Z","updated_at":"2015-05-28T22:54:15Z","body":"@orangemocha ... is this still an issue for you?"}}