From 0f4e98ba2c8b6c6daffa0ebba912432e79ce4b23 Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Sun, 28 Aug 2022 23:36:46 +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. PR-URL: https://github.com/nodejs/node/pull/44324 Fixes: https://github.com/nodejs/node/issues/44287 Reviewed-By: Joyee Cheung Reviewed-By: James M Snell --- 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 17aba6665ad05c..e37fa8cb133704 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -549,6 +549,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); } @@ -641,11 +654,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 8ed7ec2895a056..a28bdc9ed5c4d7 100644 --- a/src/node_snapshotable.cc +++ b/src/node_snapshotable.cc @@ -855,6 +855,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() { @@ -944,6 +954,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()) { @@ -1012,6 +1023,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');