File: | projects/compiler-rt/lib/ubsan/ubsan_diag.cc |
Warning: | line 283, column 23 Dereference of null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- ubsan_diag.cc -----------------------------------------------------===// | |||
2 | // | |||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |||
4 | // See https://llvm.org/LICENSE.txt for license information. | |||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |||
6 | // | |||
7 | //===----------------------------------------------------------------------===// | |||
8 | // | |||
9 | // Diagnostic reporting for the UBSan runtime. | |||
10 | // | |||
11 | //===----------------------------------------------------------------------===// | |||
12 | ||||
13 | #include "ubsan_platform.h" | |||
14 | #if CAN_SANITIZE_UB1 | |||
15 | #include "ubsan_diag.h" | |||
16 | #include "ubsan_init.h" | |||
17 | #include "ubsan_flags.h" | |||
18 | #include "ubsan_monitor.h" | |||
19 | #include "sanitizer_common/sanitizer_placement_new.h" | |||
20 | #include "sanitizer_common/sanitizer_report_decorator.h" | |||
21 | #include "sanitizer_common/sanitizer_stacktrace.h" | |||
22 | #include "sanitizer_common/sanitizer_stacktrace_printer.h" | |||
23 | #include "sanitizer_common/sanitizer_suppressions.h" | |||
24 | #include "sanitizer_common/sanitizer_symbolizer.h" | |||
25 | #include <stdio.h> | |||
26 | ||||
27 | using namespace __ubsan; | |||
28 | ||||
29 | // UBSan is combined with runtimes that already provide this functionality | |||
30 | // (e.g., ASan) as well as runtimes that lack it (e.g., scudo). Tried to use | |||
31 | // weak linkage to resolve this issue which is not portable and breaks on | |||
32 | // Windows. | |||
33 | // TODO(yln): This is a temporary workaround. GetStackTrace functions will be | |||
34 | // removed in the future. | |||
35 | void ubsan_GetStackTrace(BufferedStackTrace *stack, uptr max_depth, | |||
36 | uptr pc, uptr bp, void *context, bool fast) { | |||
37 | uptr top = 0; | |||
38 | uptr bottom = 0; | |||
39 | if (StackTrace::WillUseFastUnwind(fast)) { | |||
40 | GetThreadStackTopAndBottom(false, &top, &bottom); | |||
41 | stack->Unwind(max_depth, pc, bp, nullptr, top, bottom, true); | |||
42 | } else | |||
43 | stack->Unwind(max_depth, pc, bp, context, 0, 0, false); | |||
44 | } | |||
45 | ||||
46 | static void MaybePrintStackTrace(uptr pc, uptr bp) { | |||
47 | // We assume that flags are already parsed, as UBSan runtime | |||
48 | // will definitely be called when we print the first diagnostics message. | |||
49 | if (!flags()->print_stacktrace) | |||
50 | return; | |||
51 | ||||
52 | BufferedStackTrace stack; | |||
53 | ubsan_GetStackTrace(&stack, kStackTraceMax, pc, bp, nullptr, | |||
54 | common_flags()->fast_unwind_on_fatal); | |||
55 | stack.Print(); | |||
56 | } | |||
57 | ||||
58 | static const char *ConvertTypeToString(ErrorType Type) { | |||
59 | switch (Type) { | |||
60 | #define UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName) \ | |||
61 | case ErrorType::Name: \ | |||
62 | return SummaryKind; | |||
63 | #include "ubsan_checks.inc" | |||
64 | #undef UBSAN_CHECK | |||
65 | } | |||
66 | UNREACHABLE("unknown ErrorType!")do { do { __sanitizer::u64 v1 = (__sanitizer::u64)((0 && "unknown ErrorType!")); __sanitizer::u64 v2 = (__sanitizer:: u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer ::CheckFailed("/build/llvm-toolchain-snapshot-9~svn362543/projects/compiler-rt/lib/ubsan/ubsan_diag.cc" , 66, "(" "(0 && \"unknown ErrorType!\")" ") " "!=" " (" "0" ")", v1, v2); } while (false); Die(); } while (0); | |||
67 | } | |||
68 | ||||
69 | static const char *ConvertTypeToFlagName(ErrorType Type) { | |||
70 | switch (Type) { | |||
71 | #define UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName) \ | |||
72 | case ErrorType::Name: \ | |||
73 | return FSanitizeFlagName; | |||
74 | #include "ubsan_checks.inc" | |||
75 | #undef UBSAN_CHECK | |||
76 | } | |||
77 | UNREACHABLE("unknown ErrorType!")do { do { __sanitizer::u64 v1 = (__sanitizer::u64)((0 && "unknown ErrorType!")); __sanitizer::u64 v2 = (__sanitizer:: u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer ::CheckFailed("/build/llvm-toolchain-snapshot-9~svn362543/projects/compiler-rt/lib/ubsan/ubsan_diag.cc" , 77, "(" "(0 && \"unknown ErrorType!\")" ") " "!=" " (" "0" ")", v1, v2); } while (false); Die(); } while (0); | |||
78 | } | |||
79 | ||||
80 | static void MaybeReportErrorSummary(Location Loc, ErrorType Type) { | |||
81 | if (!common_flags()->print_summary) | |||
82 | return; | |||
83 | if (!flags()->report_error_type) | |||
84 | Type = ErrorType::GenericUB; | |||
85 | const char *ErrorKind = ConvertTypeToString(Type); | |||
86 | if (Loc.isSourceLocation()) { | |||
87 | SourceLocation SLoc = Loc.getSourceLocation(); | |||
88 | if (!SLoc.isInvalid()) { | |||
89 | AddressInfo AI; | |||
90 | AI.file = internal_strdup(SLoc.getFilename()); | |||
91 | AI.line = SLoc.getLine(); | |||
92 | AI.column = SLoc.getColumn(); | |||
93 | AI.function = internal_strdup(""); // Avoid printing ?? as function name. | |||
94 | ReportErrorSummary(ErrorKind, AI, GetSanititizerToolName()); | |||
95 | AI.Clear(); | |||
96 | return; | |||
97 | } | |||
98 | } else if (Loc.isSymbolizedStack()) { | |||
99 | const AddressInfo &AI = Loc.getSymbolizedStack()->info; | |||
100 | ReportErrorSummary(ErrorKind, AI, GetSanititizerToolName()); | |||
101 | return; | |||
102 | } | |||
103 | ReportErrorSummary(ErrorKind, GetSanititizerToolName()); | |||
104 | } | |||
105 | ||||
106 | namespace { | |||
107 | class Decorator : public SanitizerCommonDecorator { | |||
108 | public: | |||
109 | Decorator() : SanitizerCommonDecorator() {} | |||
110 | const char *Highlight() const { return Green(); } | |||
111 | const char *Note() const { return Black(); } | |||
112 | }; | |||
113 | } | |||
114 | ||||
115 | SymbolizedStack *__ubsan::getSymbolizedLocation(uptr PC) { | |||
116 | InitAsStandaloneIfNecessary(); | |||
117 | return Symbolizer::GetOrInit()->SymbolizePC(PC); | |||
118 | } | |||
119 | ||||
120 | Diag &Diag::operator<<(const TypeDescriptor &V) { | |||
121 | return AddArg(V.getTypeName()); | |||
122 | } | |||
123 | ||||
124 | Diag &Diag::operator<<(const Value &V) { | |||
125 | if (V.getType().isSignedIntegerTy()) | |||
126 | AddArg(V.getSIntValue()); | |||
127 | else if (V.getType().isUnsignedIntegerTy()) | |||
128 | AddArg(V.getUIntValue()); | |||
129 | else if (V.getType().isFloatTy()) | |||
130 | AddArg(V.getFloatValue()); | |||
131 | else | |||
132 | AddArg("<unknown>"); | |||
133 | return *this; | |||
134 | } | |||
135 | ||||
136 | /// Hexadecimal printing for numbers too large for Printf to handle directly. | |||
137 | static void RenderHex(InternalScopedString *Buffer, UIntMax Val) { | |||
138 | #if HAVE_INT128_T0 | |||
139 | Buffer->append("0x%08x%08x%08x%08x", (unsigned int)(Val >> 96), | |||
140 | (unsigned int)(Val >> 64), (unsigned int)(Val >> 32), | |||
141 | (unsigned int)(Val)); | |||
142 | #else | |||
143 | UNREACHABLE("long long smaller than 64 bits?")do { do { __sanitizer::u64 v1 = (__sanitizer::u64)((0 && "long long smaller than 64 bits?")); __sanitizer::u64 v2 = ( __sanitizer::u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0 )) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-9~svn362543/projects/compiler-rt/lib/ubsan/ubsan_diag.cc" , 143, "(" "(0 && \"long long smaller than 64 bits?\")" ") " "!=" " (" "0" ")", v1, v2); } while (false); Die(); } while (0); | |||
144 | #endif | |||
145 | } | |||
146 | ||||
147 | static void RenderLocation(InternalScopedString *Buffer, Location Loc) { | |||
148 | switch (Loc.getKind()) { | |||
149 | case Location::LK_Source: { | |||
150 | SourceLocation SLoc = Loc.getSourceLocation(); | |||
151 | if (SLoc.isInvalid()) | |||
152 | Buffer->append("<unknown>"); | |||
153 | else | |||
154 | RenderSourceLocation(Buffer, SLoc.getFilename(), SLoc.getLine(), | |||
155 | SLoc.getColumn(), common_flags()->symbolize_vs_style, | |||
156 | common_flags()->strip_path_prefix); | |||
157 | return; | |||
158 | } | |||
159 | case Location::LK_Memory: | |||
160 | Buffer->append("%p", Loc.getMemoryLocation()); | |||
161 | return; | |||
162 | case Location::LK_Symbolized: { | |||
163 | const AddressInfo &Info = Loc.getSymbolizedStack()->info; | |||
164 | if (Info.file) | |||
165 | RenderSourceLocation(Buffer, Info.file, Info.line, Info.column, | |||
166 | common_flags()->symbolize_vs_style, | |||
167 | common_flags()->strip_path_prefix); | |||
168 | else if (Info.module) | |||
169 | RenderModuleLocation(Buffer, Info.module, Info.module_offset, | |||
170 | Info.module_arch, common_flags()->strip_path_prefix); | |||
171 | else | |||
172 | Buffer->append("%p", Info.address); | |||
173 | return; | |||
174 | } | |||
175 | case Location::LK_Null: | |||
176 | Buffer->append("<unknown>"); | |||
177 | return; | |||
178 | } | |||
179 | } | |||
180 | ||||
181 | static void RenderText(InternalScopedString *Buffer, const char *Message, | |||
182 | const Diag::Arg *Args) { | |||
183 | for (const char *Msg = Message; *Msg; ++Msg) { | |||
184 | if (*Msg != '%') { | |||
185 | Buffer->append("%c", *Msg); | |||
186 | continue; | |||
187 | } | |||
188 | const Diag::Arg &A = Args[*++Msg - '0']; | |||
189 | switch (A.Kind) { | |||
190 | case Diag::AK_String: | |||
191 | Buffer->append("%s", A.String); | |||
192 | break; | |||
193 | case Diag::AK_TypeName: { | |||
194 | if (SANITIZER_WINDOWS0) | |||
195 | // The Windows implementation demangles names early. | |||
196 | Buffer->append("'%s'", A.String); | |||
197 | else | |||
198 | Buffer->append("'%s'", Symbolizer::GetOrInit()->Demangle(A.String)); | |||
199 | break; | |||
200 | } | |||
201 | case Diag::AK_SInt: | |||
202 | // 'long long' is guaranteed to be at least 64 bits wide. | |||
203 | if (A.SInt >= INT64_MIN(-9223372036854775807LL -1) && A.SInt <= INT64_MAX(9223372036854775807LL)) | |||
204 | Buffer->append("%lld", (long long)A.SInt); | |||
205 | else | |||
206 | RenderHex(Buffer, A.SInt); | |||
207 | break; | |||
208 | case Diag::AK_UInt: | |||
209 | if (A.UInt <= UINT64_MAX(18446744073709551615ULL)) | |||
210 | Buffer->append("%llu", (unsigned long long)A.UInt); | |||
211 | else | |||
212 | RenderHex(Buffer, A.UInt); | |||
213 | break; | |||
214 | case Diag::AK_Float: { | |||
215 | // FIXME: Support floating-point formatting in sanitizer_common's | |||
216 | // printf, and stop using snprintf here. | |||
217 | char FloatBuffer[32]; | |||
218 | #if SANITIZER_WINDOWS0 | |||
219 | sprintf_s(FloatBuffer, sizeof(FloatBuffer), "%Lg", (long double)A.Float); | |||
220 | #else | |||
221 | snprintf(FloatBuffer, sizeof(FloatBuffer), "%Lg", (long double)A.Float); | |||
222 | #endif | |||
223 | Buffer->append("%s", FloatBuffer); | |||
224 | break; | |||
225 | } | |||
226 | case Diag::AK_Pointer: | |||
227 | Buffer->append("%p", A.Pointer); | |||
228 | break; | |||
229 | } | |||
230 | } | |||
231 | } | |||
232 | ||||
233 | /// Find the earliest-starting range in Ranges which ends after Loc. | |||
234 | static Range *upperBound(MemoryLocation Loc, Range *Ranges, | |||
235 | unsigned NumRanges) { | |||
236 | Range *Best = 0; | |||
237 | for (unsigned I = 0; I != NumRanges; ++I) | |||
238 | if (Ranges[I].getEnd().getMemoryLocation() > Loc && | |||
239 | (!Best || | |||
240 | Best->getStart().getMemoryLocation() > | |||
241 | Ranges[I].getStart().getMemoryLocation())) | |||
242 | Best = &Ranges[I]; | |||
243 | return Best; | |||
244 | } | |||
245 | ||||
246 | static inline uptr subtractNoOverflow(uptr LHS, uptr RHS) { | |||
247 | return (LHS < RHS) ? 0 : LHS - RHS; | |||
248 | } | |||
249 | ||||
250 | static inline uptr addNoOverflow(uptr LHS, uptr RHS) { | |||
251 | const uptr Limit = (uptr)-1; | |||
252 | return (LHS > Limit - RHS) ? Limit : LHS + RHS; | |||
253 | } | |||
254 | ||||
255 | /// Render a snippet of the address space near a location. | |||
256 | static void PrintMemorySnippet(const Decorator &Decor, MemoryLocation Loc, | |||
257 | Range *Ranges, unsigned NumRanges, | |||
258 | const Diag::Arg *Args) { | |||
259 | // Show at least the 8 bytes surrounding Loc. | |||
260 | const unsigned MinBytesNearLoc = 4; | |||
261 | MemoryLocation Min = subtractNoOverflow(Loc, MinBytesNearLoc); | |||
262 | MemoryLocation Max = addNoOverflow(Loc, MinBytesNearLoc); | |||
263 | MemoryLocation OrigMin = Min; | |||
264 | for (unsigned I = 0; I < NumRanges; ++I) { | |||
265 | Min = __sanitizer::Min(Ranges[I].getStart().getMemoryLocation(), Min); | |||
266 | Max = __sanitizer::Max(Ranges[I].getEnd().getMemoryLocation(), Max); | |||
267 | } | |||
268 | ||||
269 | // If we have too many interesting bytes, prefer to show bytes after Loc. | |||
270 | const unsigned BytesToShow = 32; | |||
271 | if (Max - Min > BytesToShow) | |||
272 | Min = __sanitizer::Min(Max - BytesToShow, OrigMin); | |||
273 | Max = addNoOverflow(Min, BytesToShow); | |||
274 | ||||
275 | if (!IsAccessibleMemoryRange(Min, Max - Min)) { | |||
276 | Printf("<memory cannot be printed>\n"); | |||
277 | return; | |||
278 | } | |||
279 | ||||
280 | // Emit data. | |||
281 | InternalScopedString Buffer(1024); | |||
282 | for (uptr P = Min; P != Max; ++P) { | |||
283 | unsigned char C = *reinterpret_cast<const unsigned char*>(P); | |||
| ||||
284 | Buffer.append("%s%02x", (P % 8 == 0) ? " " : " ", C); | |||
285 | } | |||
286 | Buffer.append("\n"); | |||
287 | ||||
288 | // Emit highlights. | |||
289 | Buffer.append(Decor.Highlight()); | |||
290 | Range *InRange = upperBound(Min, Ranges, NumRanges); | |||
291 | for (uptr P = Min; P != Max; ++P) { | |||
292 | char Pad = ' ', Byte = ' '; | |||
293 | if (InRange && InRange->getEnd().getMemoryLocation() == P) | |||
294 | InRange = upperBound(P, Ranges, NumRanges); | |||
295 | if (!InRange && P > Loc) | |||
296 | break; | |||
297 | if (InRange && InRange->getStart().getMemoryLocation() < P) | |||
298 | Pad = '~'; | |||
299 | if (InRange && InRange->getStart().getMemoryLocation() <= P) | |||
300 | Byte = '~'; | |||
301 | if (P % 8 == 0) | |||
302 | Buffer.append("%c", Pad); | |||
303 | Buffer.append("%c", Pad); | |||
304 | Buffer.append("%c", P == Loc ? '^' : Byte); | |||
305 | Buffer.append("%c", Byte); | |||
306 | } | |||
307 | Buffer.append("%s\n", Decor.Default()); | |||
308 | ||||
309 | // Go over the line again, and print names for the ranges. | |||
310 | InRange = 0; | |||
311 | unsigned Spaces = 0; | |||
312 | for (uptr P = Min; P != Max; ++P) { | |||
313 | if (!InRange || InRange->getEnd().getMemoryLocation() == P) | |||
314 | InRange = upperBound(P, Ranges, NumRanges); | |||
315 | if (!InRange) | |||
316 | break; | |||
317 | ||||
318 | Spaces += (P % 8) == 0 ? 2 : 1; | |||
319 | ||||
320 | if (InRange && InRange->getStart().getMemoryLocation() == P) { | |||
321 | while (Spaces--) | |||
322 | Buffer.append(" "); | |||
323 | RenderText(&Buffer, InRange->getText(), Args); | |||
324 | Buffer.append("\n"); | |||
325 | // FIXME: We only support naming one range for now! | |||
326 | break; | |||
327 | } | |||
328 | ||||
329 | Spaces += 2; | |||
330 | } | |||
331 | ||||
332 | Printf("%s", Buffer.data()); | |||
333 | // FIXME: Print names for anything we can identify within the line: | |||
334 | // | |||
335 | // * If we can identify the memory itself as belonging to a particular | |||
336 | // global, stack variable, or dynamic allocation, then do so. | |||
337 | // | |||
338 | // * If we have a pointer-size, pointer-aligned range highlighted, | |||
339 | // determine whether the value of that range is a pointer to an | |||
340 | // entity which we can name, and if so, print that name. | |||
341 | // | |||
342 | // This needs an external symbolizer, or (preferably) ASan instrumentation. | |||
343 | } | |||
344 | ||||
345 | Diag::~Diag() { | |||
346 | // All diagnostics should be printed under report mutex. | |||
347 | ScopedReport::CheckLocked(); | |||
348 | Decorator Decor; | |||
349 | InternalScopedString Buffer(1024); | |||
350 | ||||
351 | // Prepare a report that a monitor process can inspect. | |||
352 | if (Level == DL_Error) { | |||
| ||||
353 | RenderText(&Buffer, Message, Args); | |||
354 | UndefinedBehaviorReport UBR{ConvertTypeToString(ET), Loc, Buffer}; | |||
355 | Buffer.clear(); | |||
356 | } | |||
357 | ||||
358 | Buffer.append(Decor.Bold()); | |||
359 | RenderLocation(&Buffer, Loc); | |||
360 | Buffer.append(":"); | |||
361 | ||||
362 | switch (Level) { | |||
363 | case DL_Error: | |||
364 | Buffer.append("%s runtime error: %s%s", Decor.Warning(), Decor.Default(), | |||
365 | Decor.Bold()); | |||
366 | break; | |||
367 | ||||
368 | case DL_Note: | |||
369 | Buffer.append("%s note: %s", Decor.Note(), Decor.Default()); | |||
370 | break; | |||
371 | } | |||
372 | ||||
373 | RenderText(&Buffer, Message, Args); | |||
374 | ||||
375 | Buffer.append("%s\n", Decor.Default()); | |||
376 | Printf("%s", Buffer.data()); | |||
377 | ||||
378 | if (Loc.isMemoryLocation()) | |||
379 | PrintMemorySnippet(Decor, Loc.getMemoryLocation(), Ranges, NumRanges, Args); | |||
380 | } | |||
381 | ||||
382 | ScopedReport::Initializer::Initializer() { InitAsStandaloneIfNecessary(); } | |||
383 | ||||
384 | ScopedReport::ScopedReport(ReportOptions Opts, Location SummaryLoc, | |||
385 | ErrorType Type) | |||
386 | : Opts(Opts), SummaryLoc(SummaryLoc), Type(Type) {} | |||
387 | ||||
388 | ScopedReport::~ScopedReport() { | |||
389 | MaybePrintStackTrace(Opts.pc, Opts.bp); | |||
390 | MaybeReportErrorSummary(SummaryLoc, Type); | |||
391 | if (flags()->halt_on_error) | |||
392 | Die(); | |||
393 | } | |||
394 | ||||
395 | ALIGNED(64)__attribute__((aligned(64))) static char suppression_placeholder[sizeof(SuppressionContext)]; | |||
396 | static SuppressionContext *suppression_ctx = nullptr; | |||
397 | static const char kVptrCheck[] = "vptr_check"; | |||
398 | static const char *kSuppressionTypes[] = { | |||
399 | #define UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName) FSanitizeFlagName, | |||
400 | #include "ubsan_checks.inc" | |||
401 | #undef UBSAN_CHECK | |||
402 | kVptrCheck, | |||
403 | }; | |||
404 | ||||
405 | void __ubsan::InitializeSuppressions() { | |||
406 | CHECK_EQ(nullptr, suppression_ctx)do { __sanitizer::u64 v1 = (__sanitizer::u64)((nullptr)); __sanitizer ::u64 v2 = (__sanitizer::u64)((suppression_ctx)); if (__builtin_expect (!!(!(v1 == v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-9~svn362543/projects/compiler-rt/lib/ubsan/ubsan_diag.cc" , 406, "(" "(nullptr)" ") " "==" " (" "(suppression_ctx)" ")" , v1, v2); } while (false); | |||
407 | suppression_ctx = new (suppression_placeholder) // NOLINT | |||
408 | SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes)(sizeof(kSuppressionTypes)/sizeof((kSuppressionTypes)[0]))); | |||
409 | suppression_ctx->ParseFromFile(flags()->suppressions); | |||
410 | } | |||
411 | ||||
412 | bool __ubsan::IsVptrCheckSuppressed(const char *TypeName) { | |||
413 | InitAsStandaloneIfNecessary(); | |||
414 | CHECK(suppression_ctx)do { __sanitizer::u64 v1 = (__sanitizer::u64)((suppression_ctx )); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-9~svn362543/projects/compiler-rt/lib/ubsan/ubsan_diag.cc" , 414, "(" "(suppression_ctx)" ") " "!=" " (" "0" ")", v1, v2 ); } while (false); | |||
415 | Suppression *s; | |||
416 | return suppression_ctx->Match(TypeName, kVptrCheck, &s); | |||
417 | } | |||
418 | ||||
419 | bool __ubsan::IsPCSuppressed(ErrorType ET, uptr PC, const char *Filename) { | |||
420 | InitAsStandaloneIfNecessary(); | |||
421 | CHECK(suppression_ctx)do { __sanitizer::u64 v1 = (__sanitizer::u64)((suppression_ctx )); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-9~svn362543/projects/compiler-rt/lib/ubsan/ubsan_diag.cc" , 421, "(" "(suppression_ctx)" ") " "!=" " (" "0" ")", v1, v2 ); } while (false); | |||
422 | const char *SuppType = ConvertTypeToFlagName(ET); | |||
423 | // Fast path: don't symbolize PC if there is no suppressions for given UB | |||
424 | // type. | |||
425 | if (!suppression_ctx->HasSuppressionType(SuppType)) | |||
426 | return false; | |||
427 | Suppression *s = nullptr; | |||
428 | // Suppress by file name known to runtime. | |||
429 | if (Filename != nullptr && suppression_ctx->Match(Filename, SuppType, &s)) | |||
430 | return true; | |||
431 | // Suppress by module name. | |||
432 | if (const char *Module = Symbolizer::GetOrInit()->GetModuleNameForPc(PC)) { | |||
433 | if (suppression_ctx->Match(Module, SuppType, &s)) | |||
434 | return true; | |||
435 | } | |||
436 | // Suppress by function or source file name from debug info. | |||
437 | SymbolizedStackHolder Stack(Symbolizer::GetOrInit()->SymbolizePC(PC)); | |||
438 | const AddressInfo &AI = Stack.get()->info; | |||
439 | return suppression_ctx->Match(AI.function, SuppType, &s) || | |||
440 | suppression_ctx->Match(AI.file, SuppType, &s); | |||
441 | } | |||
442 | ||||
443 | #endif // CAN_SANITIZE_UB |