forked from OSchip/llvm-project
[scudo][standalone] Add flags & related parsers
Summary: As with other Sanitizers, and the current version of Scudo, we can provide flags in differents way: at compile time, through a weak function, through an environment variable. This change adds support for the configuration flags, and the string parsers. Those are fairly similar to the sanitizer_common way of doing things. Reviewers: morehouse, hctim, vitalybuka Reviewed By: morehouse, vitalybuka Subscribers: mgorny, delcypher, jdoerfert, #sanitizers, llvm-commits Tags: #llvm, #sanitizers Differential Revision: https://reviews.llvm.org/D59597 llvm-svn: 358011
This commit is contained in:
parent
d5173f5acf
commit
7e2b15382c
|
@ -37,6 +37,8 @@ set(SCUDO_SOURCES
|
|||
checksum.cc
|
||||
crc32_hw.cc
|
||||
common.cc
|
||||
flags.cc
|
||||
flags_parser.cc
|
||||
fuchsia.cc
|
||||
linux.cc
|
||||
report.cc
|
||||
|
@ -57,6 +59,9 @@ set(SCUDO_HEADERS
|
|||
atomic_helpers.h
|
||||
bytemap.h
|
||||
checksum.h
|
||||
flags.h
|
||||
flags_parser.h
|
||||
interface.h
|
||||
internal_defs.h
|
||||
linux.h
|
||||
list.h
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
//===-- flags.cc ------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "flags.h"
|
||||
#include "common.h"
|
||||
#include "flags_parser.h"
|
||||
#include "interface.h"
|
||||
|
||||
namespace scudo {
|
||||
|
||||
Flags *getFlags() {
|
||||
static Flags F;
|
||||
return &F;
|
||||
}
|
||||
|
||||
void Flags::setDefaults() {
|
||||
#define SCUDO_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
|
||||
#include "flags.inc"
|
||||
#undef SCUDO_FLAG
|
||||
}
|
||||
|
||||
void registerFlags(FlagParser *Parser, Flags *F) {
|
||||
#define SCUDO_FLAG(Type, Name, DefaultValue, Description) \
|
||||
Parser->registerFlag(#Name, Description, FlagType::FT_##Type, \
|
||||
reinterpret_cast<void *>(&F->Name));
|
||||
#include "flags.inc"
|
||||
#undef SCUDO_FLAG
|
||||
}
|
||||
|
||||
static const char *getCompileDefinitionScudoDefaultOptions() {
|
||||
#ifdef SCUDO_DEFAULT_OPTIONS
|
||||
return STRINGIFY(SCUDO_DEFAULT_OPTIONS);
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *getScudoDefaultOptions() {
|
||||
return (&__scudo_default_options) ? __scudo_default_options() : "";
|
||||
}
|
||||
|
||||
void initFlags() {
|
||||
Flags *F = getFlags();
|
||||
F->setDefaults();
|
||||
FlagParser Parser;
|
||||
registerFlags(&Parser, F);
|
||||
Parser.parseString(getCompileDefinitionScudoDefaultOptions());
|
||||
Parser.parseString(getScudoDefaultOptions());
|
||||
Parser.parseString(getEnv("SCUDO_OPTIONS"));
|
||||
}
|
||||
|
||||
} // namespace scudo
|
|
@ -0,0 +1,30 @@
|
|||
//===-- flags.h -------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SCUDO_FLAGS_H_
|
||||
#define SCUDO_FLAGS_H_
|
||||
|
||||
#include "internal_defs.h"
|
||||
|
||||
namespace scudo {
|
||||
|
||||
struct Flags {
|
||||
#define SCUDO_FLAG(Type, Name, DefaultValue, Description) Type Name;
|
||||
#include "flags.inc"
|
||||
#undef SCUDO_FLAG
|
||||
void setDefaults();
|
||||
};
|
||||
|
||||
Flags *getFlags();
|
||||
void initFlags();
|
||||
class FlagParser;
|
||||
void registerFlags(FlagParser *Parser, Flags *F);
|
||||
|
||||
} // namespace scudo
|
||||
|
||||
#endif // SCUDO_FLAGS_H_
|
|
@ -0,0 +1,50 @@
|
|||
//===-- flags.inc -----------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SCUDO_FLAG
|
||||
#error "Define SCUDO_FLAG prior to including this file!"
|
||||
#endif
|
||||
|
||||
SCUDO_FLAG(int, quarantine_size_kb, 0,
|
||||
"Size (in kilobytes) of quarantine used to delay the actual "
|
||||
"deallocation of chunks. Lower value may reduce memory usage but "
|
||||
"decrease the effectiveness of the mitigation.")
|
||||
|
||||
SCUDO_FLAG(int, thread_local_quarantine_size_kb, 0,
|
||||
"Size (in kilobytes) of per-thread cache used to offload the global "
|
||||
"quarantine. Lower value may reduce memory usage but might increase "
|
||||
"the contention on the global quarantine.")
|
||||
|
||||
SCUDO_FLAG(int, quarantine_max_chunk_size, 0,
|
||||
"Size (in bytes) up to which chunks will be quarantined (if lower "
|
||||
"than or equal to).")
|
||||
|
||||
SCUDO_FLAG(bool, dealloc_type_mismatch, false,
|
||||
"Terminate on a type mismatch in allocation-deallocation functions, "
|
||||
"eg: malloc/delete, new/free, new/delete[], etc.")
|
||||
|
||||
SCUDO_FLAG(bool, delete_size_mismatch, true,
|
||||
"Terminate on a size mismatch between a sized-delete and the actual "
|
||||
"size of a chunk (as provided to new/new[]).")
|
||||
|
||||
SCUDO_FLAG(bool, zero_contents, false, "Zero chunk contents on allocation.")
|
||||
|
||||
SCUDO_FLAG(int, rss_limit_mb, -1,
|
||||
"Enforce an upper limit (in megabytes) to the process RSS. The "
|
||||
"allocator will terminate or return NULL when allocations are "
|
||||
"attempted past that limit (depending on may_return_null). Negative "
|
||||
"values disable the feature.")
|
||||
|
||||
SCUDO_FLAG(bool, may_return_null, true,
|
||||
"Indicate whether the allocator should terminate instead of "
|
||||
"returning NULL in otherwise non-fatal error scenarios, eg: OOM, "
|
||||
"invalid allocation alignments, etc.")
|
||||
|
||||
SCUDO_FLAG(int, release_to_os_interval_ms, 5000,
|
||||
"Interval (in milliseconds) at which to attempt release of unused "
|
||||
"memory to the OS. Negative values disable the feature.")
|
|
@ -0,0 +1,163 @@
|
|||
//===-- flags_parser.cc -----------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "flags_parser.h"
|
||||
#include "common.h"
|
||||
#include "report.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace scudo {
|
||||
|
||||
class UnknownFlagsRegistry {
|
||||
static const u32 MaxUnknownFlags = 16;
|
||||
const char *UnknownFlagsNames[MaxUnknownFlags];
|
||||
u32 NumberOfUnknownFlags;
|
||||
|
||||
public:
|
||||
void add(const char *Name) {
|
||||
CHECK_LT(NumberOfUnknownFlags, MaxUnknownFlags);
|
||||
UnknownFlagsNames[NumberOfUnknownFlags++] = Name;
|
||||
}
|
||||
|
||||
void report() {
|
||||
if (!NumberOfUnknownFlags)
|
||||
return;
|
||||
Printf("Scudo WARNING: found %d unrecognized flag(s):\n",
|
||||
NumberOfUnknownFlags);
|
||||
for (u32 I = 0; I < NumberOfUnknownFlags; ++I)
|
||||
Printf(" %s\n", UnknownFlagsNames[I]);
|
||||
NumberOfUnknownFlags = 0;
|
||||
}
|
||||
};
|
||||
static UnknownFlagsRegistry UnknownFlags;
|
||||
|
||||
void reportUnrecognizedFlags() { UnknownFlags.report(); }
|
||||
|
||||
void FlagParser::printFlagDescriptions() {
|
||||
Printf("Available flags for Scudo:\n");
|
||||
for (u32 I = 0; I < NumberOfFlags; ++I)
|
||||
Printf("\t%s\n\t\t- %s\n", Flags[I].Name, Flags[I].Desc);
|
||||
}
|
||||
|
||||
static bool isSeparator(char C) {
|
||||
return C == ' ' || C == ',' || C == ':' || C == '\n' || C == '\t' ||
|
||||
C == '\r';
|
||||
}
|
||||
|
||||
static bool isSeparatorOrNull(char C) { return !C || isSeparator(C); }
|
||||
|
||||
void FlagParser::skipWhitespace() {
|
||||
while (isSeparator(Buffer[Pos]))
|
||||
++Pos;
|
||||
}
|
||||
|
||||
void FlagParser::parseFlag() {
|
||||
const uptr NameStart = Pos;
|
||||
while (Buffer[Pos] != '=' && !isSeparatorOrNull(Buffer[Pos]))
|
||||
++Pos;
|
||||
if (Buffer[Pos] != '=')
|
||||
reportError("expected '='");
|
||||
const char *Name = Buffer + NameStart;
|
||||
const uptr ValueStart = ++Pos;
|
||||
const char *Value;
|
||||
if (Buffer[Pos] == '\'' || Buffer[Pos] == '"') {
|
||||
const char Quote = Buffer[Pos++];
|
||||
while (Buffer[Pos] != 0 && Buffer[Pos] != Quote)
|
||||
++Pos;
|
||||
if (Buffer[Pos] == 0)
|
||||
reportError("unterminated string");
|
||||
Value = Buffer + ValueStart + 1;
|
||||
++Pos; // consume the closing quote
|
||||
} else {
|
||||
while (!isSeparatorOrNull(Buffer[Pos]))
|
||||
++Pos;
|
||||
Value = Buffer + ValueStart;
|
||||
}
|
||||
if (!runHandler(Name, Value))
|
||||
reportError("flag parsing failed.");
|
||||
}
|
||||
|
||||
void FlagParser::parseFlags() {
|
||||
while (true) {
|
||||
skipWhitespace();
|
||||
if (Buffer[Pos] == 0)
|
||||
break;
|
||||
parseFlag();
|
||||
}
|
||||
}
|
||||
|
||||
void FlagParser::parseString(const char *S) {
|
||||
if (!S)
|
||||
return;
|
||||
// Backup current parser state to allow nested parseString() calls.
|
||||
const char *OldBuffer = Buffer;
|
||||
const uptr OldPos = Pos;
|
||||
Buffer = S;
|
||||
Pos = 0;
|
||||
|
||||
parseFlags();
|
||||
|
||||
Buffer = OldBuffer;
|
||||
Pos = OldPos;
|
||||
}
|
||||
|
||||
INLINE bool parseBool(const char *Value, bool *b) {
|
||||
if (strncmp(Value, "0", 1) == 0 || strncmp(Value, "no", 2) == 0 ||
|
||||
strncmp(Value, "false", 5) == 0) {
|
||||
*b = false;
|
||||
return true;
|
||||
}
|
||||
if (strncmp(Value, "1", 1) == 0 || strncmp(Value, "yes", 3) == 0 ||
|
||||
strncmp(Value, "true", 4) == 0) {
|
||||
*b = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FlagParser::runHandler(const char *Name, const char *Value) {
|
||||
for (u32 I = 0; I < NumberOfFlags; ++I) {
|
||||
const uptr Len = strlen(Flags[I].Name);
|
||||
if (strncmp(Name, Flags[I].Name, Len) != 0 || Name[Len] != '=')
|
||||
continue;
|
||||
bool Ok = false;
|
||||
switch (Flags[I].Type) {
|
||||
case FlagType::FT_bool:
|
||||
Ok = parseBool(Value, reinterpret_cast<bool *>(Flags[I].Var));
|
||||
if (!Ok)
|
||||
reportInvalidFlag("bool", Value);
|
||||
break;
|
||||
case FlagType::FT_int:
|
||||
char *ValueEnd;
|
||||
*reinterpret_cast<int *>(Flags[I].Var) =
|
||||
static_cast<int>(strtol(Value, &ValueEnd, 10));
|
||||
Ok =
|
||||
*ValueEnd == '"' || *ValueEnd == '\'' || isSeparatorOrNull(*ValueEnd);
|
||||
if (!Ok)
|
||||
reportInvalidFlag("int", Value);
|
||||
break;
|
||||
}
|
||||
return Ok;
|
||||
}
|
||||
// Unrecognized flag. This is not a fatal error, we may print a warning later.
|
||||
UnknownFlags.add(Name);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FlagParser::registerFlag(const char *Name, const char *Desc, FlagType Type,
|
||||
void *Var) {
|
||||
CHECK_LT(NumberOfFlags, MaxFlags);
|
||||
Flags[NumberOfFlags].Name = Name;
|
||||
Flags[NumberOfFlags].Desc = Desc;
|
||||
Flags[NumberOfFlags].Type = Type;
|
||||
Flags[NumberOfFlags].Var = Var;
|
||||
++NumberOfFlags;
|
||||
}
|
||||
|
||||
} // namespace scudo
|
|
@ -0,0 +1,56 @@
|
|||
//===-- flags_parser.h ------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SCUDO_FLAGS_PARSER_H_
|
||||
#define SCUDO_FLAGS_PARSER_H_
|
||||
|
||||
#include "report.h"
|
||||
#include "string_utils.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace scudo {
|
||||
|
||||
enum class FlagType : u8 {
|
||||
FT_bool,
|
||||
FT_int,
|
||||
};
|
||||
|
||||
class FlagParser {
|
||||
public:
|
||||
void registerFlag(const char *Name, const char *Desc, FlagType Type,
|
||||
void *Var);
|
||||
void parseString(const char *S);
|
||||
void printFlagDescriptions();
|
||||
|
||||
private:
|
||||
static const u32 MaxFlags = 12;
|
||||
struct Flag {
|
||||
const char *Name;
|
||||
const char *Desc;
|
||||
FlagType Type;
|
||||
void *Var;
|
||||
} Flags[MaxFlags];
|
||||
|
||||
u32 NumberOfFlags = 0;
|
||||
const char *Buffer = nullptr;
|
||||
uptr Pos = 0;
|
||||
|
||||
void reportFatalError(const char *Error);
|
||||
void skipWhitespace();
|
||||
void parseFlags();
|
||||
void parseFlag();
|
||||
bool runHandler(const char *Name, const char *Value);
|
||||
};
|
||||
|
||||
void reportUnrecognizedFlags();
|
||||
|
||||
} // namespace scudo
|
||||
|
||||
#endif // SCUDO_FLAGS_PARSER_H_
|
|
@ -0,0 +1,29 @@
|
|||
//===-- interface.h ---------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SCUDO_INTERFACE_H_
|
||||
#define SCUDO_INTERFACE_H_
|
||||
|
||||
#include "internal_defs.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
WEAK INTERFACE const char *__scudo_default_options();
|
||||
|
||||
// Post-allocation & pre-deallocation hooks.
|
||||
// They must be thread-safe and not use heap related functions.
|
||||
WEAK INTERFACE void __scudo_allocate_hook(void *ptr, size_t size);
|
||||
WEAK INTERFACE void __scudo_deallocate_hook(void *ptr);
|
||||
|
||||
WEAK INTERFACE void __scudo_print_stats(void);
|
||||
|
||||
typedef void (*iterate_callback)(uintptr_t base, size_t size, void *arg);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif // SCUDO_INTERFACE_H_
|
|
@ -52,6 +52,7 @@ set(SCUDO_UNIT_TEST_SOURCES
|
|||
atomic_test.cc
|
||||
bytemap_test.cc
|
||||
checksum_test.cc
|
||||
flags_test.cc
|
||||
list_test.cc
|
||||
map_test.cc
|
||||
mutex_test.cc
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
//===-- flags_test.cc -------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "flags.h"
|
||||
#include "flags_parser.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static const char FlagName[] = "flag_name";
|
||||
static const char FlagDesc[] = "flag description";
|
||||
|
||||
template <typename T>
|
||||
static void testFlag(scudo::FlagType Type, T StartValue, const char *Env,
|
||||
T FinalValue) {
|
||||
scudo::FlagParser Parser;
|
||||
T Flag = StartValue;
|
||||
Parser.registerFlag(FlagName, FlagDesc, Type, &Flag);
|
||||
Parser.parseString(Env);
|
||||
EXPECT_EQ(FinalValue, Flag);
|
||||
// Reporting unrecognized flags is needed to reset them.
|
||||
scudo::reportUnrecognizedFlags();
|
||||
}
|
||||
|
||||
TEST(ScudoFlagsTest, BooleanFlags) {
|
||||
testFlag(scudo::FlagType::FT_bool, false, "flag_name=1", true);
|
||||
testFlag(scudo::FlagType::FT_bool, false, "flag_name=yes", true);
|
||||
testFlag(scudo::FlagType::FT_bool, false, "flag_name='yes'", true);
|
||||
testFlag(scudo::FlagType::FT_bool, false, "flag_name=true", true);
|
||||
testFlag(scudo::FlagType::FT_bool, true, "flag_name=0", false);
|
||||
testFlag(scudo::FlagType::FT_bool, true, "flag_name=\"0\"", false);
|
||||
testFlag(scudo::FlagType::FT_bool, true, "flag_name=no", false);
|
||||
testFlag(scudo::FlagType::FT_bool, true, "flag_name=false", false);
|
||||
testFlag(scudo::FlagType::FT_bool, true, "flag_name='false'", false);
|
||||
}
|
||||
|
||||
TEST(ScudoFlagsDeathTest, BooleanFlags) {
|
||||
EXPECT_DEATH(testFlag(scudo::FlagType::FT_bool, false, "flag_name", true),
|
||||
"expected '='");
|
||||
EXPECT_DEATH(testFlag(scudo::FlagType::FT_bool, false, "flag_name=", true),
|
||||
"invalid value for bool option: ''");
|
||||
EXPECT_DEATH(testFlag(scudo::FlagType::FT_bool, false, "flag_name=2", true),
|
||||
"invalid value for bool option: '2'");
|
||||
EXPECT_DEATH(testFlag(scudo::FlagType::FT_bool, false, "flag_name=-1", true),
|
||||
"invalid value for bool option: '-1'");
|
||||
EXPECT_DEATH(testFlag(scudo::FlagType::FT_bool, false, "flag_name=on", true),
|
||||
"invalid value for bool option: 'on'");
|
||||
}
|
||||
|
||||
TEST(ScudoFlagsTest, IntFlags) {
|
||||
testFlag(scudo::FlagType::FT_int, -11, nullptr, -11);
|
||||
testFlag(scudo::FlagType::FT_int, -11, "flag_name=0", 0);
|
||||
testFlag(scudo::FlagType::FT_int, -11, "flag_name='0'", 0);
|
||||
testFlag(scudo::FlagType::FT_int, -11, "flag_name=42", 42);
|
||||
testFlag(scudo::FlagType::FT_int, -11, "flag_name=-42", -42);
|
||||
testFlag(scudo::FlagType::FT_int, -11, "flag_name=\"-42\"", -42);
|
||||
|
||||
// Unrecognized flags are ignored.
|
||||
testFlag(scudo::FlagType::FT_int, -11, "--flag_name=42", -11);
|
||||
testFlag(scudo::FlagType::FT_int, -11, "zzzzzzz=42", -11);
|
||||
}
|
||||
|
||||
TEST(ScudoFlagsDeathTest, IntFlags) {
|
||||
EXPECT_DEATH(testFlag(scudo::FlagType::FT_int, -11, "flag_name", 0),
|
||||
"expected '='");
|
||||
EXPECT_DEATH(testFlag(scudo::FlagType::FT_int, -11, "flag_name=42U", 0),
|
||||
"invalid value for int option");
|
||||
}
|
||||
|
||||
static void testTwoFlags(const char *Env, bool ExpectedFlag1,
|
||||
const int ExpectedFlag2, const char *Name1 = "flag1",
|
||||
const char *Name2 = "flag2") {
|
||||
scudo::FlagParser Parser;
|
||||
bool Flag1 = !ExpectedFlag1;
|
||||
int Flag2;
|
||||
Parser.registerFlag(Name1, FlagDesc, scudo::FlagType::FT_bool, &Flag1);
|
||||
Parser.registerFlag(Name2, FlagDesc, scudo::FlagType::FT_int, &Flag2);
|
||||
Parser.parseString(Env);
|
||||
EXPECT_EQ(ExpectedFlag1, Flag1);
|
||||
EXPECT_EQ(Flag2, ExpectedFlag2);
|
||||
// Reporting unrecognized flags is needed to reset them.
|
||||
scudo::reportUnrecognizedFlags();
|
||||
}
|
||||
|
||||
TEST(ScudoFlagsTest, MultipleFlags) {
|
||||
testTwoFlags("flag1=1 flag2=42", true, 42);
|
||||
testTwoFlags("flag2=-1 flag1=0", false, -1);
|
||||
testTwoFlags("flag1=false:flag2=1337", false, 1337);
|
||||
testTwoFlags("flag2=42:flag1=yes", true, 42);
|
||||
testTwoFlags("flag2=42\nflag1=yes", true, 42);
|
||||
testTwoFlags("flag2=42\r\nflag1=yes", true, 42);
|
||||
testTwoFlags("flag2=42\tflag1=yes", true, 42);
|
||||
}
|
||||
|
||||
TEST(ScudoFlagsTest, CommonSuffixFlags) {
|
||||
testTwoFlags("flag=1 other_flag=42", true, 42, "flag", "other_flag");
|
||||
testTwoFlags("other_flag=42 flag=1", true, 42, "flag", "other_flag");
|
||||
}
|
||||
|
||||
TEST(ScudoFlagsTest, AllocatorFlags) {
|
||||
scudo::FlagParser Parser;
|
||||
scudo::Flags Flags;
|
||||
scudo::registerFlags(&Parser, &Flags);
|
||||
Flags.setDefaults();
|
||||
Flags.dealloc_type_mismatch = false;
|
||||
Flags.delete_size_mismatch = false;
|
||||
Flags.quarantine_max_chunk_size = 1024;
|
||||
Parser.parseString("dealloc_type_mismatch=true:delete_size_mismatch=true:"
|
||||
"quarantine_max_chunk_size=2048");
|
||||
EXPECT_TRUE(Flags.dealloc_type_mismatch);
|
||||
EXPECT_TRUE(Flags.delete_size_mismatch);
|
||||
EXPECT_EQ(2048, Flags.quarantine_max_chunk_size);
|
||||
}
|
Loading…
Reference in New Issue