Index: lib/asan/asan_flags.cc =================================================================== --- lib/asan/asan_flags.cc +++ lib/asan/asan_flags.cc @@ -120,12 +120,12 @@ #endif // Override from command line. - asan_parser.ParseString(GetEnv("ASAN_OPTIONS")); + asan_parser.ParseString(GetEnv("ASAN_OPTIONS"), "ASAN_OPTIONS"); #if CAN_SANITIZE_LEAKS - lsan_parser.ParseString(GetEnv("LSAN_OPTIONS")); + lsan_parser.ParseString(GetEnv("LSAN_OPTIONS"), "LSAN_OPTIONS"); #endif #if CAN_SANITIZE_UB - ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS")); + ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS"), "UBSAN_OPTIONS"); #endif InitializeCommonFlags(); Index: lib/lsan/lsan.cc =================================================================== --- lib/lsan/lsan.cc +++ lib/lsan/lsan.cc @@ -76,7 +76,7 @@ // Override from user-specified string. const char *lsan_default_options = MaybeCallLsanDefaultOptions(); parser.ParseString(lsan_default_options); - parser.ParseString(GetEnv("LSAN_OPTIONS")); + parser.ParseString(GetEnv("LSAN_OPTIONS"), "LSAN_OPTIONS"); SetVerbosity(common_flags()->verbosity); Index: lib/sanitizer_common/sanitizer_flag_parser.h =================================================================== --- lib/sanitizer_common/sanitizer_flag_parser.h +++ lib/sanitizer_common/sanitizer_flag_parser.h @@ -112,7 +112,7 @@ FlagParser(); void RegisterHandler(const char *name, FlagHandlerBase *handler, const char *desc); - void ParseString(const char *s); + void ParseString(const char *s, const char *env_option_name = 0); bool ParseFile(const char *path, bool ignore_missing); void PrintFlagDescriptions(); @@ -122,8 +122,8 @@ 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); }; Index: lib/sanitizer_common/sanitizer_flag_parser.cc =================================================================== --- lib/sanitizer_common/sanitizer_flag_parser.cc +++ lib/sanitizer_common/sanitizer_flag_parser.cc @@ -75,10 +75,17 @@ 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("ERROR: expected '=' in %s\n", 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 @@ 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,7 @@ common_flags_dont_use.malloc_context_size = 1; } -void FlagParser::ParseString(const char *s) { +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 +127,7 @@ buf_ = s; pos_ = 0; - parse_flags(); + parse_flags(env_option_name); buf_ = old_buf_; pos_ = old_pos_; Index: lib/tsan/rtl/tsan_flags.h =================================================================== --- lib/tsan/rtl/tsan_flags.h +++ lib/tsan/rtl/tsan_flags.h @@ -27,7 +27,7 @@ void ParseFromString(const char *str); }; -void InitializeFlags(Flags *flags, const char *env); +void InitializeFlags(Flags *flags, const char *env, const char *env_option_name); } // namespace __tsan #endif // TSAN_FLAGS_H Index: lib/tsan/rtl/tsan_flags.cc =================================================================== --- lib/tsan/rtl/tsan_flags.cc +++ lib/tsan/rtl/tsan_flags.cc @@ -49,7 +49,7 @@ &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 @@ 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.ParseString(GetEnv("UBSAN_OPTIONS"), "UBSAN_OPTIONS"); #endif // Sanity check. Index: lib/tsan/rtl/tsan_rtl.cc =================================================================== --- lib/tsan/rtl/tsan_rtl.cc +++ lib/tsan/rtl/tsan_rtl.cc @@ -350,10 +350,11 @@ 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(); Index: lib/ubsan/ubsan_flags.cc =================================================================== --- lib/ubsan/ubsan_flags.cc +++ lib/ubsan/ubsan_flags.cc @@ -69,7 +69,7 @@ // Override from user-specified string. parser.ParseString(MaybeCallUbsanDefaultOptions()); // Override from environment variable. - parser.ParseString(GetFlag("UBSAN_OPTIONS")); + parser.ParseString(GetFlag("UBSAN_OPTIONS"), "UBSAN_OPTIONS"); InitializeCommonFlags(); if (Verbosity()) ReportUnrecognizedFlags();