Improve error message when '=' is missing in {ASAN,...}_OPTIONS.

Summary:
It's handling isses as described here:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89832

Patch by Martin Liška.

Reviewers: kcc, vitalybuka

Reviewed By: vitalybuka

Subscribers: cryptoad, kubamracek

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

llvm-svn: 363480
This commit is contained in:
Vitaly Buka 2019-06-15 01:37:14 +00:00
parent dc2fd6a14e
commit 0b1ea8cb28
16 changed files with 49 additions and 38 deletions

View File

@ -120,12 +120,12 @@ void InitializeFlags() {
#endif
// Override from command line.
asan_parser.ParseString(GetEnv("ASAN_OPTIONS"));
asan_parser.ParseStringFromEnv("ASAN_OPTIONS");
#if CAN_SANITIZE_LEAKS
lsan_parser.ParseString(GetEnv("LSAN_OPTIONS"));
lsan_parser.ParseStringFromEnv("LSAN_OPTIONS");
#endif
#if CAN_SANITIZE_UB
ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS"));
ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");
#endif
InitializeCommonFlags();

View File

@ -372,7 +372,7 @@ void InitializeFlags() {
FlagParser cfi_parser;
RegisterCommonFlags(&cfi_parser);
cfi_parser.ParseString(GetEnv("CFI_OPTIONS"));
cfi_parser.ParseStringFromEnv("CFI_OPTIONS");
#ifdef CFI_ENABLE_DIAG
FlagParser ubsan_parser;
@ -381,7 +381,7 @@ void InitializeFlags() {
const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions();
ubsan_parser.ParseString(ubsan_default_options);
ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS"));
ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");
#endif
InitializeCommonFlags();

View File

@ -383,7 +383,7 @@ static void InitializeFlags() {
FlagParser parser;
RegisterCommonFlags(&parser);
RegisterDfsanFlags(&parser, &flags());
parser.ParseString(GetEnv("DFSAN_OPTIONS"));
parser.ParseStringFromEnv("DFSAN_OPTIONS");
InitializeCommonFlags();
if (Verbosity()) ReportUnrecognizedFlags();
if (common_flags()->help) parser.PrintFlagDescriptions();

View File

@ -129,13 +129,10 @@ static void InitializeFlags() {
ubsan_parser.ParseString(ubsan_default_options);
#endif
const char *hwasan_options = GetEnv("HWASAN_OPTIONS");
parser.ParseString(hwasan_options);
parser.ParseStringFromEnv("HWASAN_OPTIONS");
#if HWASAN_CONTAINS_UBSAN
ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS"));
ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");
#endif
VPrintf(1, "HWASAN_OPTIONS: %s\n",
hwasan_options ? hwasan_options : "<empty>");
InitializeCommonFlags();

View File

@ -76,7 +76,7 @@ static void InitializeFlags() {
// Override from user-specified string.
const char *lsan_default_options = MaybeCallLsanDefaultOptions();
parser.ParseString(lsan_default_options);
parser.ParseString(GetEnv("LSAN_OPTIONS"));
parser.ParseStringFromEnv("LSAN_OPTIONS");
SetVerbosity(common_flags()->verbosity);

View File

@ -175,12 +175,10 @@ static void InitializeFlags() {
ubsan_parser.ParseString(ubsan_default_options);
#endif
const char *msan_options = GetEnv("MSAN_OPTIONS");
parser.ParseString(msan_options);
parser.ParseStringFromEnv("MSAN_OPTIONS");
#if MSAN_CONTAINS_UBSAN
ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS"));
ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");
#endif
VPrintf(1, "MSAN_OPTIONS: %s\n", msan_options ? msan_options : "<empty>");
InitializeCommonFlags();

View File

@ -49,7 +49,7 @@ void InitializeSancovFlags() {
RegisterSancovFlags(&parser, f);
parser.ParseString(MaybeCallSancovDefaultOptions());
parser.ParseString(GetEnv("SANCOV_OPTIONS"));
parser.ParseStringFromEnv("SANCOV_OPTIONS");
ReportUnrecognizedFlags();
if (f->help) parser.PrintFlagDescriptions();

View File

@ -62,7 +62,7 @@ void FlagParser::PrintFlagDescriptions() {
}
void FlagParser::fatal_error(const char *err) {
Printf("ERROR: %s\n", err);
Printf("%s: ERROR: %s\n", SanitizerToolName, err);
Die();
}
@ -75,10 +75,17 @@ void FlagParser::skip_whitespace() {
while (is_space(buf_[pos_])) ++pos_;
}
void FlagParser::parse_flag() {
void FlagParser::parse_flag(const char *env_option_name) {
uptr name_start = pos_;
while (buf_[pos_] != 0 && buf_[pos_] != '=' && !is_space(buf_[pos_])) ++pos_;
if (buf_[pos_] != '=') fatal_error("expected '='");
if (buf_[pos_] != '=') {
if (env_option_name) {
Printf("%s: ERROR: expected '=' in %s\n", SanitizerToolName,
env_option_name);
Die();
} else
fatal_error("expected '='");
}
char *name = ll_strndup(buf_ + name_start, pos_ - name_start);
uptr value_start = ++pos_;
@ -100,11 +107,11 @@ void FlagParser::parse_flag() {
if (!res) fatal_error("Flag parsing failed.");
}
void FlagParser::parse_flags() {
void FlagParser::parse_flags(const char *env_option_name) {
while (true) {
skip_whitespace();
if (buf_[pos_] == 0) break;
parse_flag();
parse_flag(env_option_name);
}
// Do a sanity check for certain flags.
@ -112,7 +119,13 @@ void FlagParser::parse_flags() {
common_flags_dont_use.malloc_context_size = 1;
}
void FlagParser::ParseString(const char *s) {
void FlagParser::ParseStringFromEnv(const char *env_name) {
const char *env = GetEnv(env_name);
VPrintf(1, "%s: %s\n", env_name, env ? env : "<empty>");
ParseString(env, env_name);
}
void FlagParser::ParseString(const char *s, const char *env_option_name) {
if (!s) return;
// Backup current parser state to allow nested ParseString() calls.
const char *old_buf_ = buf_;
@ -120,7 +133,7 @@ void FlagParser::ParseString(const char *s) {
buf_ = s;
pos_ = 0;
parse_flags();
parse_flags(env_option_name);
buf_ = old_buf_;
pos_ = old_pos_;
@ -139,7 +152,7 @@ bool FlagParser::ParseFile(const char *path, bool ignore_missing) {
Printf("Failed to read options from '%s': error %d\n", path, err);
return false;
}
ParseString(data);
ParseString(data, path);
UnmapOrDie(data, data_mapped_size);
return true;
}

View File

@ -124,7 +124,8 @@ class FlagParser {
FlagParser();
void RegisterHandler(const char *name, FlagHandlerBase *handler,
const char *desc);
void ParseString(const char *s);
void ParseString(const char *s, const char *env_name = 0);
void ParseStringFromEnv(const char *env_name);
bool ParseFile(const char *path, bool ignore_missing);
void PrintFlagDescriptions();
@ -134,8 +135,8 @@ class FlagParser {
void fatal_error(const char *err);
bool is_space(char c);
void skip_whitespace();
void parse_flags();
void parse_flag();
void parse_flags(const char *env_option_name);
void parse_flag(const char *env_option_name);
bool run_handler(const char *name, const char *value);
char *ll_strndup(const char *s, uptr n);
};

View File

@ -68,7 +68,7 @@ void initFlags() {
ScudoParser.ParseString(getScudoDefaultOptions());
// Override from environment.
ScudoParser.ParseString(GetEnv("SCUDO_OPTIONS"));
ScudoParser.ParseStringFromEnv("SCUDO_OPTIONS");
InitializeCommonFlags();

View File

@ -83,7 +83,7 @@ static void InitializeFlags() {
FlagParser parser;
RegisterFlag(&parser, "second_deadlock_stack", "", &f->second_deadlock_stack);
RegisterCommonFlags(&parser);
parser.ParseString(GetEnv("DSAN_OPTIONS"));
parser.ParseStringFromEnv("DSAN_OPTIONS");
SetVerbosity(common_flags()->verbosity);
}

View File

@ -49,7 +49,7 @@ void RegisterTsanFlags(FlagParser *parser, Flags *f) {
&f->second_deadlock_stack);
}
void InitializeFlags(Flags *f, const char *env) {
void InitializeFlags(Flags *f, const char *env, const char *env_option_name) {
SetCommonFlagsDefaults();
{
// Override some common flags defaults.
@ -91,9 +91,9 @@ void InitializeFlags(Flags *f, const char *env) {
ubsan_parser.ParseString(ubsan_default_options);
#endif
// Override from command line.
parser.ParseString(env);
parser.ParseString(env, env_option_name);
#if TSAN_CONTAINS_UBSAN
ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS"));
ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");
#endif
// Sanity check.

View File

@ -27,7 +27,8 @@ struct Flags : DDFlags {
void ParseFromString(const char *str);
};
void InitializeFlags(Flags *flags, const char *env);
void InitializeFlags(Flags *flags, const char *env,
const char *env_option_name = nullptr);
} // namespace __tsan
#endif // TSAN_FLAGS_H

View File

@ -350,10 +350,11 @@ void Initialize(ThreadState *thr) {
SetCheckFailedCallback(TsanCheckFailed);
ctx = new(ctx_placeholder) Context;
const char *options = GetEnv(SANITIZER_GO ? "GORACE" : "TSAN_OPTIONS");
const char *env_name = SANITIZER_GO ? "GORACE" : "TSAN_OPTIONS";
const char *options = GetEnv(env_name);
CacheBinaryName();
CheckASLR();
InitializeFlags(&ctx->flags, options);
InitializeFlags(&ctx->flags, options, env_name);
AvoidCVE_2016_2143();
__sanitizer::InitializePlatformEarly();
__tsan::InitializePlatformEarly();

View File

@ -69,7 +69,7 @@ void InitializeFlags() {
// Override from user-specified string.
parser.ParseString(MaybeCallUbsanDefaultOptions());
// Override from environment variable.
parser.ParseString(GetFlag("UBSAN_OPTIONS"));
parser.ParseStringFromEnv("UBSAN_OPTIONS");
InitializeCommonFlags();
if (Verbosity()) ReportUnrecognizedFlags();

View File

@ -68,7 +68,7 @@ void initializeFlags() XRAY_NEVER_INSTRUMENT {
XRayParser.ParseString(XRayCompileFlags);
// Override from environment variables.
XRayParser.ParseString(GetEnv("XRAY_OPTIONS"));
XRayParser.ParseStringFromEnv("XRAY_OPTIONS");
// Override from command line.
InitializeCommonFlags();