未验证 提交 12f48f76 编写于 作者: B Ben Konyi 提交者: GitHub

Allow for whitelisted flags to be passed to the Dart VM (#9148)

* Allow for whitelisted flags to be passed to the Dart VM

Fixed part of https://github.com/flutter/flutter/issues/32176
上级 b304dabc
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <future> #include <future>
#include <memory> #include <memory>
#include "flutter/fml/command_line.h"
#include "flutter/fml/make_copyable.h" #include "flutter/fml/make_copyable.h"
#include "flutter/fml/message_loop.h" #include "flutter/fml/message_loop.h"
#include "flutter/fml/synchronization/count_down_latch.h" #include "flutter/fml/synchronization/count_down_latch.h"
...@@ -15,6 +16,7 @@ ...@@ -15,6 +16,7 @@
#include "flutter/shell/common/platform_view.h" #include "flutter/shell/common/platform_view.h"
#include "flutter/shell/common/rasterizer.h" #include "flutter/shell/common/rasterizer.h"
#include "flutter/shell/common/shell_test.h" #include "flutter/shell/common/shell_test.h"
#include "flutter/shell/common/switches.h"
#include "flutter/shell/common/thread_host.h" #include "flutter/shell/common/thread_host.h"
#include "flutter/testing/testing.h" #include "flutter/testing/testing.h"
...@@ -274,5 +276,42 @@ TEST_F(ShellTest, SecondaryIsolateBindingsAreSetupViaShellSettings) { ...@@ -274,5 +276,42 @@ TEST_F(ShellTest, SecondaryIsolateBindingsAreSetupViaShellSettings) {
ASSERT_FALSE(DartVMRef::IsInstanceRunning()); ASSERT_FALSE(DartVMRef::IsInstanceRunning());
} }
TEST_F(ShellTest, BlacklistedDartVMFlag) {
// Run this test in a thread-safe manner, otherwise gtest will complain.
::testing::FLAGS_gtest_death_test_style = "threadsafe";
const std::vector<fml::CommandLine::Option> options = {
fml::CommandLine::Option("dart-flags", "--verify_after_gc")};
fml::CommandLine command_line("", options, std::vector<std::string>());
#if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE && \
FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_DYNAMIC_RELEASE
// Upon encountering a non-whitelisted Dart flag the process terminates.
const char* expected =
"Encountered blacklisted Dart VM flag: --verify_after_gc";
ASSERT_DEATH(flutter::SettingsFromCommandLine(command_line), expected);
#else
flutter::Settings settings = flutter::SettingsFromCommandLine(command_line);
EXPECT_EQ(settings.dart_flags.size(), 0u);
#endif
}
TEST_F(ShellTest, WhitelistedDartVMFlag) {
const std::vector<fml::CommandLine::Option> options = {
fml::CommandLine::Option("dart-flags",
"--max_profile_depth 1,--trace_service")};
fml::CommandLine command_line("", options, std::vector<std::string>());
flutter::Settings settings = flutter::SettingsFromCommandLine(command_line);
#if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE && \
FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_DYNAMIC_RELEASE
EXPECT_EQ(settings.dart_flags.size(), 2u);
EXPECT_EQ(settings.dart_flags[0], "--max_profile_depth 1");
EXPECT_EQ(settings.dart_flags[1], "--trace_service");
#else
EXPECT_EQ(settings.dart_flags.size(), 0u);
#endif
}
} // namespace testing } // namespace testing
} // namespace flutter } // namespace flutter
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "flutter/fml/native_library.h" #include "flutter/fml/native_library.h"
#include "flutter/fml/paths.h" #include "flutter/fml/paths.h"
#include "flutter/fml/size.h"
#include "flutter/fml/string_view.h" #include "flutter/fml/string_view.h"
#include "flutter/shell/version/version.h" #include "flutter/shell/version/version.h"
...@@ -36,6 +37,18 @@ struct SwitchDesc { ...@@ -36,6 +37,18 @@ struct SwitchDesc {
#define DEF_SWITCHES_END }; #define DEF_SWITCHES_END };
// clang-format on // clang-format on
#if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE && \
FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_DYNAMIC_RELEASE
// List of common and safe VM flags to allow to be passed directly to the VM.
static const std::string gDartFlagsWhitelist[] = {
"--max_profile_depth", "--profile_period", "--random_seed",
"--trace_profiler", "--trace_profiler_verbose", "--trace_service",
"--trace_service_verbose",
};
#endif
// Include again for struct definition. // Include again for struct definition.
#include "flutter/shell/common/switches.h" #include "flutter/shell/common/switches.h"
...@@ -102,6 +115,24 @@ const fml::StringView FlagForSwitch(Switch swtch) { ...@@ -102,6 +115,24 @@ const fml::StringView FlagForSwitch(Switch swtch) {
return fml::StringView(); return fml::StringView();
} }
#if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE && \
FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_DYNAMIC_RELEASE
static bool IsWhitelistedDartVMFlag(const std::string& flag) {
for (uint32_t i = 0; i < fml::size(gDartFlagsWhitelist); ++i) {
const std::string& allowed = gDartFlagsWhitelist[i];
// Check that the prefix of the flag matches one of the whitelisted flags.
// We don't need to worry about cases like "--safe --sneaky_dangerous" as
// the VM will discard these as a single unrecognized flag.
if (std::equal(allowed.begin(), allowed.end(), flag.begin())) {
return true;
}
}
return false;
}
#endif
template <typename T> template <typename T>
static bool GetSwitchValue(const fml::CommandLine& command_line, static bool GetSwitchValue(const fml::CommandLine& command_line,
Switch sw, Switch sw,
...@@ -260,18 +291,24 @@ Settings SettingsFromCommandLine(const fml::CommandLine& command_line) { ...@@ -260,18 +291,24 @@ Settings SettingsFromCommandLine(const fml::CommandLine& command_line) {
settings.use_test_fonts = settings.use_test_fonts =
command_line.HasOption(FlagForSwitch(Switch::UseTestFonts)); command_line.HasOption(FlagForSwitch(Switch::UseTestFonts));
#if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE && \
FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_DYNAMIC_RELEASE
command_line.GetOptionValue(FlagForSwitch(Switch::LogTag), &settings.log_tag); command_line.GetOptionValue(FlagForSwitch(Switch::LogTag), &settings.log_tag);
std::string all_dart_flags; std::string all_dart_flags;
if (command_line.GetOptionValue(FlagForSwitch(Switch::DartFlags), if (command_line.GetOptionValue(FlagForSwitch(Switch::DartFlags),
&all_dart_flags)) { &all_dart_flags)) {
std::stringstream stream(all_dart_flags); std::stringstream stream(all_dart_flags);
std::istream_iterator<std::string> end; std::string flag;
for (std::istream_iterator<std::string> it(stream); it != end; ++it)
settings.dart_flags.push_back(*it); // Assume that individual flags are comma separated.
while (std::getline(stream, flag, ',')) {
if (!IsWhitelistedDartVMFlag(flag)) {
FML_LOG(FATAL) << "Encountered blacklisted Dart VM flag: " << flag;
}
settings.dart_flags.push_back(flag);
}
} }
#if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE && \
FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_DYNAMIC_RELEASE
settings.trace_skia = settings.trace_skia =
command_line.HasOption(FlagForSwitch(Switch::TraceSkia)); command_line.HasOption(FlagForSwitch(Switch::TraceSkia));
settings.trace_systrace = settings.trace_systrace =
......
...@@ -312,6 +312,13 @@ public final class FlutterActivityDelegate ...@@ -312,6 +312,13 @@ public final class FlutterActivityDelegate
if (intent.getBooleanExtra("verbose-logging", false)) { if (intent.getBooleanExtra("verbose-logging", false)) {
args.add("--verbose-logging"); args.add("--verbose-logging");
} }
// NOTE: all flags provided with this argument are subject to filtering
// based on a whitelist in shell/common/switches.cc. If any flag provided
// is not present in the whitelist, the process will immediately
// terminate.
if (intent.hasExtra("dart-flags")) {
args.add("--dart-flags=" + intent.getStringExtra("dart-flags"));
}
if (!args.isEmpty()) { if (!args.isEmpty()) {
String[] argsArray = new String[args.size()]; String[] argsArray = new String[args.size()];
return args.toArray(argsArray); return args.toArray(argsArray);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册