168d75effSDimitry Andric //===-- asan_flags.cpp ------------------------------------------*- C++ -*-===//
268d75effSDimitry Andric //
368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668d75effSDimitry Andric //
768d75effSDimitry Andric //===----------------------------------------------------------------------===//
868d75effSDimitry Andric //
968d75effSDimitry Andric // This file is a part of AddressSanitizer, an address sanity checker.
1068d75effSDimitry Andric //
1168d75effSDimitry Andric // ASan flag parsing logic.
1268d75effSDimitry Andric //===----------------------------------------------------------------------===//
1368d75effSDimitry Andric
1468d75effSDimitry Andric #include "asan_activation.h"
1568d75effSDimitry Andric #include "asan_flags.h"
1668d75effSDimitry Andric #include "asan_interface_internal.h"
1768d75effSDimitry Andric #include "asan_stack.h"
1868d75effSDimitry Andric #include "lsan/lsan_common.h"
1968d75effSDimitry Andric #include "sanitizer_common/sanitizer_common.h"
2068d75effSDimitry Andric #include "sanitizer_common/sanitizer_flags.h"
2168d75effSDimitry Andric #include "sanitizer_common/sanitizer_flag_parser.h"
2268d75effSDimitry Andric #include "ubsan/ubsan_flags.h"
2368d75effSDimitry Andric #include "ubsan/ubsan_platform.h"
2468d75effSDimitry Andric
2568d75effSDimitry Andric namespace __asan {
2668d75effSDimitry Andric
2768d75effSDimitry Andric Flags asan_flags_dont_use_directly; // use via flags().
2868d75effSDimitry Andric
MaybeUseAsanDefaultOptionsCompileDefinition()2968d75effSDimitry Andric static const char *MaybeUseAsanDefaultOptionsCompileDefinition() {
3068d75effSDimitry Andric #ifdef ASAN_DEFAULT_OPTIONS
3168d75effSDimitry Andric return SANITIZER_STRINGIFY(ASAN_DEFAULT_OPTIONS);
3268d75effSDimitry Andric #else
3368d75effSDimitry Andric return "";
3468d75effSDimitry Andric #endif
3568d75effSDimitry Andric }
3668d75effSDimitry Andric
SetDefaults()3768d75effSDimitry Andric void Flags::SetDefaults() {
3868d75effSDimitry Andric #define ASAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
3968d75effSDimitry Andric #include "asan_flags.inc"
4068d75effSDimitry Andric #undef ASAN_FLAG
4168d75effSDimitry Andric }
4268d75effSDimitry Andric
RegisterAsanFlags(FlagParser * parser,Flags * f)4368d75effSDimitry Andric static void RegisterAsanFlags(FlagParser *parser, Flags *f) {
4468d75effSDimitry Andric #define ASAN_FLAG(Type, Name, DefaultValue, Description) \
4568d75effSDimitry Andric RegisterFlag(parser, #Name, Description, &f->Name);
4668d75effSDimitry Andric #include "asan_flags.inc"
4768d75effSDimitry Andric #undef ASAN_FLAG
4868d75effSDimitry Andric }
4968d75effSDimitry Andric
InitializeFlags()5068d75effSDimitry Andric void InitializeFlags() {
5168d75effSDimitry Andric // Set the default values and prepare for parsing ASan and common flags.
5268d75effSDimitry Andric SetCommonFlagsDefaults();
5368d75effSDimitry Andric {
5468d75effSDimitry Andric CommonFlags cf;
5568d75effSDimitry Andric cf.CopyFrom(*common_flags());
5668d75effSDimitry Andric cf.detect_leaks = cf.detect_leaks && CAN_SANITIZE_LEAKS;
5768d75effSDimitry Andric cf.external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH");
5868d75effSDimitry Andric cf.malloc_context_size = kDefaultMallocContextSize;
5968d75effSDimitry Andric cf.intercept_tls_get_addr = true;
6068d75effSDimitry Andric cf.exitcode = 1;
6168d75effSDimitry Andric OverrideCommonFlags(cf);
6268d75effSDimitry Andric }
6368d75effSDimitry Andric Flags *f = flags();
6468d75effSDimitry Andric f->SetDefaults();
6568d75effSDimitry Andric
6668d75effSDimitry Andric FlagParser asan_parser;
6768d75effSDimitry Andric RegisterAsanFlags(&asan_parser, f);
6868d75effSDimitry Andric RegisterCommonFlags(&asan_parser);
6968d75effSDimitry Andric
7068d75effSDimitry Andric // Set the default values and prepare for parsing LSan and UBSan flags
7168d75effSDimitry Andric // (which can also overwrite common flags).
7268d75effSDimitry Andric #if CAN_SANITIZE_LEAKS
7368d75effSDimitry Andric __lsan::Flags *lf = __lsan::flags();
7468d75effSDimitry Andric lf->SetDefaults();
7568d75effSDimitry Andric
7668d75effSDimitry Andric FlagParser lsan_parser;
7768d75effSDimitry Andric __lsan::RegisterLsanFlags(&lsan_parser, lf);
7868d75effSDimitry Andric RegisterCommonFlags(&lsan_parser);
7968d75effSDimitry Andric #endif
8068d75effSDimitry Andric
8168d75effSDimitry Andric #if CAN_SANITIZE_UB
8268d75effSDimitry Andric __ubsan::Flags *uf = __ubsan::flags();
8368d75effSDimitry Andric uf->SetDefaults();
8468d75effSDimitry Andric
8568d75effSDimitry Andric FlagParser ubsan_parser;
8668d75effSDimitry Andric __ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
8768d75effSDimitry Andric RegisterCommonFlags(&ubsan_parser);
8868d75effSDimitry Andric #endif
8968d75effSDimitry Andric
90*81ad6265SDimitry Andric if (SANITIZER_APPLE) {
9168d75effSDimitry Andric // Support macOS MallocScribble and MallocPreScribble:
9268d75effSDimitry Andric // <https://developer.apple.com/library/content/documentation/Performance/
9368d75effSDimitry Andric // Conceptual/ManagingMemory/Articles/MallocDebug.html>
9468d75effSDimitry Andric if (GetEnv("MallocScribble")) {
9568d75effSDimitry Andric f->max_free_fill_size = 0x1000;
9668d75effSDimitry Andric }
9768d75effSDimitry Andric if (GetEnv("MallocPreScribble")) {
9868d75effSDimitry Andric f->malloc_fill_byte = 0xaa;
9968d75effSDimitry Andric }
10068d75effSDimitry Andric }
10168d75effSDimitry Andric
10268d75effSDimitry Andric // Override from ASan compile definition.
10368d75effSDimitry Andric const char *asan_compile_def = MaybeUseAsanDefaultOptionsCompileDefinition();
10468d75effSDimitry Andric asan_parser.ParseString(asan_compile_def);
10568d75effSDimitry Andric
10668d75effSDimitry Andric // Override from user-specified string.
107e8d8bef9SDimitry Andric const char *asan_default_options = __asan_default_options();
10868d75effSDimitry Andric asan_parser.ParseString(asan_default_options);
10968d75effSDimitry Andric #if CAN_SANITIZE_UB
110e8d8bef9SDimitry Andric const char *ubsan_default_options = __ubsan_default_options();
11168d75effSDimitry Andric ubsan_parser.ParseString(ubsan_default_options);
11268d75effSDimitry Andric #endif
11368d75effSDimitry Andric #if CAN_SANITIZE_LEAKS
114e8d8bef9SDimitry Andric const char *lsan_default_options = __lsan_default_options();
11568d75effSDimitry Andric lsan_parser.ParseString(lsan_default_options);
11668d75effSDimitry Andric #endif
11768d75effSDimitry Andric
11868d75effSDimitry Andric // Override from command line.
11968d75effSDimitry Andric asan_parser.ParseStringFromEnv("ASAN_OPTIONS");
12068d75effSDimitry Andric #if CAN_SANITIZE_LEAKS
12168d75effSDimitry Andric lsan_parser.ParseStringFromEnv("LSAN_OPTIONS");
12268d75effSDimitry Andric #endif
12368d75effSDimitry Andric #if CAN_SANITIZE_UB
12468d75effSDimitry Andric ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");
12568d75effSDimitry Andric #endif
12668d75effSDimitry Andric
12768d75effSDimitry Andric InitializeCommonFlags();
12868d75effSDimitry Andric
12968d75effSDimitry Andric // TODO(eugenis): dump all flags at verbosity>=2?
13068d75effSDimitry Andric if (Verbosity()) ReportUnrecognizedFlags();
13168d75effSDimitry Andric
13268d75effSDimitry Andric if (common_flags()->help) {
13368d75effSDimitry Andric // TODO(samsonov): print all of the flags (ASan, LSan, common).
13468d75effSDimitry Andric asan_parser.PrintFlagDescriptions();
13568d75effSDimitry Andric }
13668d75effSDimitry Andric
13768d75effSDimitry Andric // Flag validation:
13868d75effSDimitry Andric if (!CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) {
13968d75effSDimitry Andric Report("%s: detect_leaks is not supported on this platform.\n",
14068d75effSDimitry Andric SanitizerToolName);
14168d75effSDimitry Andric Die();
14268d75effSDimitry Andric }
1430eae32dcSDimitry Andric // Ensure that redzone is at least ASAN_SHADOW_GRANULARITY.
1440eae32dcSDimitry Andric if (f->redzone < (int)ASAN_SHADOW_GRANULARITY)
1450eae32dcSDimitry Andric f->redzone = ASAN_SHADOW_GRANULARITY;
14668d75effSDimitry Andric // Make "strict_init_order" imply "check_initialization_order".
14768d75effSDimitry Andric // TODO(samsonov): Use a single runtime flag for an init-order checker.
14868d75effSDimitry Andric if (f->strict_init_order) {
14968d75effSDimitry Andric f->check_initialization_order = true;
15068d75effSDimitry Andric }
15168d75effSDimitry Andric CHECK_LE((uptr)common_flags()->malloc_context_size, kStackTraceMax);
15268d75effSDimitry Andric CHECK_LE(f->min_uar_stack_size_log, f->max_uar_stack_size_log);
15368d75effSDimitry Andric CHECK_GE(f->redzone, 16);
15468d75effSDimitry Andric CHECK_GE(f->max_redzone, f->redzone);
15568d75effSDimitry Andric CHECK_LE(f->max_redzone, 2048);
15668d75effSDimitry Andric CHECK(IsPowerOfTwo(f->redzone));
15768d75effSDimitry Andric CHECK(IsPowerOfTwo(f->max_redzone));
15868d75effSDimitry Andric
15968d75effSDimitry Andric // quarantine_size is deprecated but we still honor it.
16068d75effSDimitry Andric // quarantine_size can not be used together with quarantine_size_mb.
16168d75effSDimitry Andric if (f->quarantine_size >= 0 && f->quarantine_size_mb >= 0) {
16268d75effSDimitry Andric Report("%s: please use either 'quarantine_size' (deprecated) or "
16368d75effSDimitry Andric "quarantine_size_mb, but not both\n", SanitizerToolName);
16468d75effSDimitry Andric Die();
16568d75effSDimitry Andric }
16668d75effSDimitry Andric if (f->quarantine_size >= 0)
16768d75effSDimitry Andric f->quarantine_size_mb = f->quarantine_size >> 20;
16868d75effSDimitry Andric if (f->quarantine_size_mb < 0) {
16968d75effSDimitry Andric const int kDefaultQuarantineSizeMb =
17068d75effSDimitry Andric (ASAN_LOW_MEMORY) ? 1UL << 4 : 1UL << 8;
17168d75effSDimitry Andric f->quarantine_size_mb = kDefaultQuarantineSizeMb;
17268d75effSDimitry Andric }
17368d75effSDimitry Andric if (f->thread_local_quarantine_size_kb < 0) {
17468d75effSDimitry Andric const u32 kDefaultThreadLocalQuarantineSizeKb =
17568d75effSDimitry Andric // It is not advised to go lower than 64Kb, otherwise quarantine batches
17668d75effSDimitry Andric // pushed from thread local quarantine to global one will create too
17768d75effSDimitry Andric // much overhead. One quarantine batch size is 8Kb and it holds up to
17868d75effSDimitry Andric // 1021 chunk, which amounts to 1/8 memory overhead per batch when
17968d75effSDimitry Andric // thread local quarantine is set to 64Kb.
18068d75effSDimitry Andric (ASAN_LOW_MEMORY) ? 1 << 6 : FIRST_32_SECOND_64(1 << 8, 1 << 10);
18168d75effSDimitry Andric f->thread_local_quarantine_size_kb = kDefaultThreadLocalQuarantineSizeKb;
18268d75effSDimitry Andric }
18368d75effSDimitry Andric if (f->thread_local_quarantine_size_kb == 0 && f->quarantine_size_mb > 0) {
18468d75effSDimitry Andric Report("%s: thread_local_quarantine_size_kb can be set to 0 only when "
18568d75effSDimitry Andric "quarantine_size_mb is set to 0\n", SanitizerToolName);
18668d75effSDimitry Andric Die();
18768d75effSDimitry Andric }
18868d75effSDimitry Andric if (!f->replace_str && common_flags()->intercept_strlen) {
18968d75effSDimitry Andric Report("WARNING: strlen interceptor is enabled even though replace_str=0. "
19068d75effSDimitry Andric "Use intercept_strlen=0 to disable it.");
19168d75effSDimitry Andric }
19268d75effSDimitry Andric if (!f->replace_str && common_flags()->intercept_strchr) {
19368d75effSDimitry Andric Report("WARNING: strchr* interceptors are enabled even though "
19468d75effSDimitry Andric "replace_str=0. Use intercept_strchr=0 to disable them.");
19568d75effSDimitry Andric }
19668d75effSDimitry Andric if (!f->replace_str && common_flags()->intercept_strndup) {
19768d75effSDimitry Andric Report("WARNING: strndup* interceptors are enabled even though "
19868d75effSDimitry Andric "replace_str=0. Use intercept_strndup=0 to disable them.");
19968d75effSDimitry Andric }
20068d75effSDimitry Andric }
20168d75effSDimitry Andric
20268d75effSDimitry Andric } // namespace __asan
20368d75effSDimitry Andric
SANITIZER_INTERFACE_WEAK_DEF(const char *,__asan_default_options,void)20468d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(const char*, __asan_default_options, void) {
20568d75effSDimitry Andric return "";
20668d75effSDimitry Andric }
207