• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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