From 38b97cc266f482d4fa6d4f9e869766ba2125b4ef Mon Sep 17 00:00:00 2001 From: legendecas Date: Fri, 19 Aug 2022 21:42:39 +0800 Subject: [PATCH] src: restore context default IsCodeGenerationFromStringsAllowed value Context's default IsCodeGenerationFromStringsAllowed value can be changed by v8 flag `--disallow-code-generation-from-strings`. Restore the value at runtime when delegating the code generation validation to `node::ModifyCodeGenerationFromStrings`. The context's settings are serialized in the snapshot. Reset the setting values to its default values before the serialization so that it can be correctly re-initialized after deserialization at runtime. --- src/api/environment.cc | 19 ++++++++++++++++--- src/node_snapshotable.cc | 13 +++++++++++++ ...l-disallow-code-generation-from-strings.js | 9 +++++++++ test/parallel/test-eval.js | 7 +++++++ 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 test/parallel/test-eval-disallow-code-generation-from-strings.js create mode 100644 test/parallel/test-eval.js diff --git a/src/api/environment.cc b/src/api/environment.cc index 2cecae617f07f7..53581405bac712 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -556,6 +556,19 @@ Maybe InitializeContextRuntime(Local context) { Isolate* isolate = context->GetIsolate(); HandleScope handle_scope(isolate); + // When `IsCodeGenerationFromStringsAllowed` is true, V8 takes the fast path + // and ignores the ModifyCodeGenerationFromStrings callback. Set it to false + // to delegate the code generation validation to + // node::ModifyCodeGenerationFromStrings. + // The `IsCodeGenerationFromStringsAllowed` can be refreshed by V8 according + // to the runtime flags, propagate the value to the embedder data. + bool is_code_generation_from_strings_allowed = + context->IsCodeGenerationFromStringsAllowed(); + context->AllowCodeGenerationFromStrings(false); + context->SetEmbedderData( + ContextEmbedderIndex::kAllowCodeGenerationFromStrings, + is_code_generation_from_strings_allowed ? True(isolate) : False(isolate)); + if (per_process::cli_options->disable_proto == "") { return Just(true); } @@ -648,11 +661,11 @@ Maybe InitializeMainContextForSnapshot(Local context) { Isolate* isolate = context->GetIsolate(); HandleScope handle_scope(isolate); - context->AllowCodeGenerationFromStrings(false); - context->SetEmbedderData( - ContextEmbedderIndex::kAllowCodeGenerationFromStrings, True(isolate)); + // Initialize the default values. context->SetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration, True(isolate)); + context->SetEmbedderData( + ContextEmbedderIndex::kAllowCodeGenerationFromStrings, True(isolate)); if (InitializeBaseContextForSnapshot(context).IsNothing()) { return Nothing(); diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc index 9aac5dd7f31d0c..98660f7d171209 100644 --- a/src/node_snapshotable.cc +++ b/src/node_snapshotable.cc @@ -958,6 +958,16 @@ const SnapshotData* SnapshotBuilder::GetEmbeddedSnapshotData() { )"; } +// Reset context settings that need to be initialized again after +// deserialization. +static void ResetContextSettingsBeforeSnapshot(Local context) { + // Reset the AllowCodeGenerationFromStrings flag to true (default value) so + // that it can be re-initialized with v8 flag + // --disallow-code-generation-from-strings and recognized in + // node::InitializeContextRuntime. + context->AllowCodeGenerationFromStrings(true); +} + Mutex SnapshotBuilder::snapshot_data_mutex_; const std::vector& SnapshotBuilder::CollectExternalReferences() { @@ -1053,6 +1063,7 @@ int SnapshotBuilder::Generate(SnapshotData* out, if (base_context.IsEmpty()) { return BOOTSTRAP_ERROR; } + ResetContextSettingsBeforeSnapshot(base_context); Local main_context = NewContext(isolate); if (main_context.IsEmpty()) { @@ -1121,6 +1132,8 @@ int SnapshotBuilder::Generate(SnapshotData* out, size_str.c_str()); } #endif + + ResetContextSettingsBeforeSnapshot(main_context); } // Global handles to the contexts can't be disposed before the diff --git a/test/parallel/test-eval-disallow-code-generation-from-strings.js b/test/parallel/test-eval-disallow-code-generation-from-strings.js new file mode 100644 index 00000000000000..c9c0c60b773ce8 --- /dev/null +++ b/test/parallel/test-eval-disallow-code-generation-from-strings.js @@ -0,0 +1,9 @@ +// Flags: --disallow-code-generation-from-strings +'use strict'; + +require('../common'); +const assert = require('assert'); + +// Verify that v8 option --disallow-code-generation-from-strings is still +// respected +assert.throws(() => eval('"eval"'), EvalError); diff --git a/test/parallel/test-eval.js b/test/parallel/test-eval.js new file mode 100644 index 00000000000000..46a4b7c54689b1 --- /dev/null +++ b/test/parallel/test-eval.js @@ -0,0 +1,7 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); + +// Verify that eval is allowed by default. +assert.strictEqual(eval('"eval"'), 'eval');