1 //===-- sanitizer_flags.cc ------------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "sanitizer_flags.h"
15
16 #include "sanitizer_common.h"
17 #include "sanitizer_libc.h"
18
19 namespace __sanitizer {
20
21 CommonFlags common_flags_dont_use_directly;
22
ParseCommonFlagsFromString(const char * str)23 void ParseCommonFlagsFromString(const char *str) {
24 CommonFlags *f = common_flags();
25 ParseFlag(str, &f->malloc_context_size, "malloc_context_size");
26 ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");
27 ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal");
28 ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc");
29 ParseFlag(str, &f->symbolize, "symbolize");
30 ParseFlag(str, &f->handle_ioctl, "handle_ioctl");
31 ParseFlag(str, &f->log_path, "log_path");
32 ParseFlag(str, &f->detect_leaks, "detect_leaks");
33 ParseFlag(str, &f->leak_check_at_exit, "leak_check_at_exit");
34 }
35
GetFlagValue(const char * env,const char * name,const char ** value,int * value_length)36 static bool GetFlagValue(const char *env, const char *name,
37 const char **value, int *value_length) {
38 if (env == 0)
39 return false;
40 const char *pos = 0;
41 for (;;) {
42 pos = internal_strstr(env, name);
43 if (pos == 0)
44 return false;
45 if (pos != env && ((pos[-1] >= 'a' && pos[-1] <= 'z') || pos[-1] == '_')) {
46 // Seems to be middle of another flag name or value.
47 env = pos + 1;
48 continue;
49 }
50 break;
51 }
52 pos += internal_strlen(name);
53 const char *end;
54 if (pos[0] != '=') {
55 end = pos;
56 } else {
57 pos += 1;
58 if (pos[0] == '"') {
59 pos += 1;
60 end = internal_strchr(pos, '"');
61 } else if (pos[0] == '\'') {
62 pos += 1;
63 end = internal_strchr(pos, '\'');
64 } else {
65 // Read until the next space or colon.
66 end = pos + internal_strcspn(pos, " :");
67 }
68 if (end == 0)
69 end = pos + internal_strlen(pos);
70 }
71 *value = pos;
72 *value_length = end - pos;
73 return true;
74 }
75
StartsWith(const char * flag,int flag_length,const char * value)76 static bool StartsWith(const char *flag, int flag_length, const char *value) {
77 if (!flag || !value)
78 return false;
79 int value_length = internal_strlen(value);
80 return (flag_length >= value_length) &&
81 (0 == internal_strncmp(flag, value, value_length));
82 }
83
ParseFlag(const char * env,bool * flag,const char * name)84 void ParseFlag(const char *env, bool *flag, const char *name) {
85 const char *value;
86 int value_length;
87 if (!GetFlagValue(env, name, &value, &value_length))
88 return;
89 if (StartsWith(value, value_length, "0") ||
90 StartsWith(value, value_length, "no") ||
91 StartsWith(value, value_length, "false"))
92 *flag = false;
93 if (StartsWith(value, value_length, "1") ||
94 StartsWith(value, value_length, "yes") ||
95 StartsWith(value, value_length, "true"))
96 *flag = true;
97 }
98
ParseFlag(const char * env,int * flag,const char * name)99 void ParseFlag(const char *env, int *flag, const char *name) {
100 const char *value;
101 int value_length;
102 if (!GetFlagValue(env, name, &value, &value_length))
103 return;
104 *flag = static_cast<int>(internal_atoll(value));
105 }
106
107 static LowLevelAllocator allocator_for_flags;
108
ParseFlag(const char * env,const char ** flag,const char * name)109 void ParseFlag(const char *env, const char **flag, const char *name) {
110 const char *value;
111 int value_length;
112 if (!GetFlagValue(env, name, &value, &value_length))
113 return;
114 // Copy the flag value. Don't use locks here, as flags are parsed at
115 // tool startup.
116 char *value_copy = (char*)(allocator_for_flags.Allocate(value_length + 1));
117 internal_memcpy(value_copy, value, value_length);
118 value_copy[value_length] = '\0';
119 *flag = value_copy;
120 }
121
122 } // namespace __sanitizer
123