Refinery: Validate arguments hard in run_analyzer_main.cc.

R=ericdingle@chromium.org

Review-Url: https://codereview.chromium.org/2780513003
diff --git a/syzygy/integration_tests/instrument_integration_test.cc b/syzygy/integration_tests/instrument_integration_test.cc
index 3e37c42..c53f0e1 100644
--- a/syzygy/integration_tests/instrument_integration_test.cc
+++ b/syzygy/integration_tests/instrument_integration_test.cc
@@ -1219,6 +1219,9 @@
     // Run the symbolizer tester script to make sure that the minidump gets
     // symbolized correctly.
 
+    // The build scripts may set the wrong python path, so clear it here.
+    env->UnSetVar("PYTHONPATH");
+
     base::CommandLine cmd_line(
         ::testing::GetSrcRelativePath(L"third_party/python_26/python.exe"));
     cmd_line.AppendArgPath(::testing::GetSrcRelativePath(
diff --git a/syzygy/refinery/analyzers/run_analyzer_main.cc b/syzygy/refinery/analyzers/run_analyzer_main.cc
index dcb36af..f6c4385 100644
--- a/syzygy/refinery/analyzers/run_analyzer_main.cc
+++ b/syzygy/refinery/analyzers/run_analyzer_main.cc
@@ -111,6 +111,53 @@
   return ret;
 }
 
+const char* kLayerNames[] = {
+#define LAYER_NAME(layer_name) #layer_name "Layer",
+    PROCESS_STATE_LAYERS(LAYER_NAME)
+#undef LAYER_NAME
+};
+
+bool IsValidLayerName(const std::string& candidate) {
+  for (const auto name : kLayerNames) {
+    if (candidate == name)
+      return true;
+  }
+
+  return false;
+}
+
+std::string GetValidLayerNames() {
+  std::string ret;
+  for (const auto name : kLayerNames) {
+    if (!ret.empty())
+      ret.append(", ");
+    ret.append(name);
+  }
+
+  return ret;
+}
+
+bool IsValidAnalyzerName(const std::string& candidate) {
+  refinery::AnalyzerFactory::AnalyzerNames names;
+  refinery::StaticAnalyzerFactory factory;
+  factory.GetAnalyzerNames(&names);
+
+  for (const auto name : names) {
+    if (candidate == name)
+      return true;
+  }
+
+  return false;
+}
+
+std::string GetValidAnalyzerNames() {
+  refinery::AnalyzerFactory::AnalyzerNames names;
+  refinery::StaticAnalyzerFactory factory;
+  factory.GetAnalyzerNames(&names);
+
+  return base::JoinString(names, ", ");
+}
+
 const char kUsageFormatStr[] =
     "Usage: %ls [options] <dump files or patterns>\n"
     "\n"
@@ -254,6 +301,15 @@
                  "Must provide a non-empty analyzer list with this flag.");
       return false;
     }
+    for (const auto& analyzer_name : SplitStringList(analyzer_names_)) {
+      if (!IsValidAnalyzerName(analyzer_name)) {
+        PrintUsage(cmd_line->GetProgram(),
+                   base::StringPrintf(
+                       "Analyzer \"%s\" doesn't exist, must be one of \"%s\"",
+                       analyzer_name.c_str(), GetValidAnalyzerNames().c_str()));
+        return false;
+      }
+    }
   }
 
   static const char kOutputLayers[] = "output-layers";
@@ -265,6 +321,15 @@
                  "Must provide a non-empty output layer list with this flag.");
       return false;
     }
+    for (const auto& layer_name : SplitStringList(output_layers_)) {
+      if (!IsValidLayerName(layer_name)) {
+        PrintUsage(cmd_line->GetProgram(),
+                   base::StringPrintf(
+                       "Layer \"%s\" doesn't exist, must be one of \"%s\"",
+                       layer_name.c_str(), GetValidLayerNames().c_str()));
+        return false;
+      }
+    }
   }
 
   for (const auto& arg : cmd_line->GetArgs()) {