[scudo][standalone] Restore GWP-ASan flag parsing

With D92696, the Scudo Standalone GWP-ASan flag parsing was changed to
the new GWP-ASan optional one. We do not necessarily want this, as this
duplicates flag parsing code in Scudo Standalone when using the
GWP-ASan integration.

This CL reverts the changes within Scudo Standalone, and increases
`MaxFlags` to 20 as an addionnal option got us to the current max.

Differential Revision: https://reviews.llvm.org/D95542

GitOrigin-RevId: ba379fe5276b4a922ab19eb8af9ba5bece81cdff
diff --git a/combined.h b/combined.h
index 0df7a65..11370be 100644
--- a/combined.h
+++ b/combined.h
@@ -28,7 +28,6 @@
 #ifdef GWP_ASAN_HOOKS
 #include "gwp_asan/guarded_pool_allocator.h"
 #include "gwp_asan/optional/backtrace.h"
-#include "gwp_asan/optional/options_parser.h"
 #include "gwp_asan/optional/segv_handler.h"
 #endif // GWP_ASAN_HOOKS
 
@@ -184,12 +183,17 @@
   // be functional, best called from PostInitCallback.
   void initGwpAsan() {
 #ifdef GWP_ASAN_HOOKS
+    gwp_asan::options::Options Opt;
+    Opt.Enabled = getFlags()->GWP_ASAN_Enabled;
     // Bear in mind - Scudo has its own alignment guarantees that are strictly
     // enforced. Scudo exposes the same allocation function for everything from
     // malloc() to posix_memalign, so in general this flag goes unused, as Scudo
     // will always ask GWP-ASan for an aligned amount of bytes.
-    gwp_asan::options::initOptions(getEnv("GWP_ASAN_OPTIONS"), Printf);
-    gwp_asan::options::Options Opt = gwp_asan::options::getOptions();
+    Opt.PerfectlyRightAlign = getFlags()->GWP_ASAN_PerfectlyRightAlign;
+    Opt.MaxSimultaneousAllocations =
+        getFlags()->GWP_ASAN_MaxSimultaneousAllocations;
+    Opt.SampleRate = getFlags()->GWP_ASAN_SampleRate;
+    Opt.InstallSignalHandlers = getFlags()->GWP_ASAN_InstallSignalHandlers;
     // Embedded GWP-ASan is locked through the Scudo atfork handler (via
     // Allocator::disable calling GWPASan.disable). Disable GWP-ASan's atfork
     // handler.
diff --git a/flags.cpp b/flags.cpp
index 285143a..de5153b 100644
--- a/flags.cpp
+++ b/flags.cpp
@@ -23,6 +23,13 @@
 #define SCUDO_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
 #include "flags.inc"
 #undef SCUDO_FLAG
+
+#ifdef GWP_ASAN_HOOKS
+#define GWP_ASAN_OPTION(Type, Name, DefaultValue, Description)                 \
+  GWP_ASAN_##Name = DefaultValue;
+#include "gwp_asan/options.inc"
+#undef GWP_ASAN_OPTION
+#endif // GWP_ASAN_HOOKS
 }
 
 void registerFlags(FlagParser *Parser, Flags *F) {
@@ -31,6 +38,14 @@
                        reinterpret_cast<void *>(&F->Name));
 #include "flags.inc"
 #undef SCUDO_FLAG
+
+#ifdef GWP_ASAN_HOOKS
+#define GWP_ASAN_OPTION(Type, Name, DefaultValue, Description)                 \
+  Parser->registerFlag("GWP_ASAN_" #Name, Description, FlagType::FT_##Type,    \
+                       reinterpret_cast<void *>(&F->GWP_ASAN_##Name));
+#include "gwp_asan/options.inc"
+#undef GWP_ASAN_OPTION
+#endif // GWP_ASAN_HOOKS
 }
 
 static const char *getCompileDefinitionScudoDefaultOptions() {
diff --git a/flags_parser.h b/flags_parser.h
index 32511f7..ba832ad 100644
--- a/flags_parser.h
+++ b/flags_parser.h
@@ -29,7 +29,7 @@
   void printFlagDescriptions();
 
 private:
-  static const u32 MaxFlags = 16;
+  static const u32 MaxFlags = 20;
   struct Flag {
     const char *Name;
     const char *Desc;
diff --git a/tests/flags_test.cpp b/tests/flags_test.cpp
index 45918ad..0205052 100644
--- a/tests/flags_test.cpp
+++ b/tests/flags_test.cpp
@@ -117,3 +117,18 @@
   EXPECT_TRUE(Flags.delete_size_mismatch);
   EXPECT_EQ(2048, Flags.quarantine_max_chunk_size);
 }
+
+#ifdef GWP_ASAN_HOOKS
+TEST(ScudoFlagsTest, GWPASanFlags) {
+  scudo::FlagParser Parser;
+  scudo::Flags Flags;
+  scudo::registerFlags(&Parser, &Flags);
+  Flags.setDefaults();
+  Flags.GWP_ASAN_Enabled = false;
+  Parser.parseString("GWP_ASAN_Enabled=true:GWP_ASAN_SampleRate=1:"
+                     "GWP_ASAN_InstallSignalHandlers=false");
+  EXPECT_TRUE(Flags.GWP_ASAN_Enabled);
+  EXPECT_FALSE(Flags.GWP_ASAN_InstallSignalHandlers);
+  EXPECT_EQ(1, Flags.GWP_ASAN_SampleRate);
+}
+#endif // GWP_ASAN_HOOKS