1 //===-- nsan.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 // NumericalStabilitySanitizer runtime.
10 //
11 // This implements:
12 // - The public nsan interface (include/sanitizer/nsan_interface.h).
13 // - The private nsan interface (./nsan.h).
14 // - The internal instrumentation interface. These are function emitted by the
15 // instrumentation pass:
16 // * __nsan_get_shadow_ptr_for_{float,double,longdouble}_load
17 // These return the shadow memory pointer for loading the shadow value,
18 // after checking that the types are consistent. If the types are not
19 // consistent, returns nullptr.
20 // * __nsan_get_shadow_ptr_for_{float,double,longdouble}_store
21 // Sets the shadow types appropriately and returns the shadow memory
22 // pointer for storing the shadow value.
23 // * __nsan_internal_check_{float,double,long double}_{f,d,l} checks the
24 // accuracy of a value against its shadow and emits a warning depending
25 // on the runtime configuration. The middle part indicates the type of
26 // the application value, the suffix (f,d,l) indicates the type of the
27 // shadow, and depends on the instrumentation configuration.
28 // * __nsan_fcmp_fail_* emits a warning for a fcmp instruction whose
29 // corresponding shadow fcmp result differs.
30 //
31 //===----------------------------------------------------------------------===//
32
33 #include "nsan.h"
34 #include "nsan_flags.h"
35 #include "nsan_stats.h"
36 #include "nsan_suppressions.h"
37 #include "nsan_thread.h"
38
39 #include <assert.h>
40 #include <math.h>
41 #include <stdint.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44
45 #include "sanitizer_common/sanitizer_atomic.h"
46 #include "sanitizer_common/sanitizer_common.h"
47 #include "sanitizer_common/sanitizer_libc.h"
48 #include "sanitizer_common/sanitizer_report_decorator.h"
49 #include "sanitizer_common/sanitizer_stacktrace.h"
50 #include "sanitizer_common/sanitizer_symbolizer.h"
51
52 using namespace __sanitizer;
53 using namespace __nsan;
54
55 constexpr int kMaxVectorWidth = 8;
56
57 // When copying application memory, we also copy its shadow and shadow type.
58 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_copy_values(const void * daddr,const void * saddr,uptr size)59 __nsan_copy_values(const void *daddr, const void *saddr, uptr size) {
60 internal_memmove(GetShadowTypeAddrFor(daddr), GetShadowTypeAddrFor(saddr),
61 size);
62 internal_memmove(GetShadowAddrFor(daddr), GetShadowAddrFor(saddr),
63 size * kShadowScale);
64 }
65
66 #define NSAN_COPY_VALUES_N(N) \
67 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_copy_##N( \
68 const u8 *daddr, const u8 *saddr) { \
69 __builtin_memmove(GetShadowTypeAddrFor(daddr), \
70 GetShadowTypeAddrFor(saddr), N); \
71 __builtin_memmove(GetShadowAddrFor(daddr), GetShadowAddrFor(saddr), \
72 N *kShadowScale); \
73 }
74
75 NSAN_COPY_VALUES_N(4)
76 NSAN_COPY_VALUES_N(8)
77 NSAN_COPY_VALUES_N(16)
78
79 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_set_value_unknown(const void * addr,uptr size)80 __nsan_set_value_unknown(const void *addr, uptr size) {
81 internal_memset(GetShadowTypeAddrFor(addr), 0, size);
82 }
83
84 #define NSAN_SET_VALUE_UNKNOWN_N(N) \
85 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_set_value_unknown_##N( \
86 const u8 *daddr) { \
87 __builtin_memset(GetShadowTypeAddrFor(daddr), 0, N); \
88 }
89
90 NSAN_SET_VALUE_UNKNOWN_N(4)
91 NSAN_SET_VALUE_UNKNOWN_N(8)
92 NSAN_SET_VALUE_UNKNOWN_N(16)
93
94 const char *FTInfo<float>::kCppTypeName = "float";
95 const char *FTInfo<double>::kCppTypeName = "double";
96 const char *FTInfo<long double>::kCppTypeName = "long double";
97 const char *FTInfo<__float128>::kCppTypeName = "__float128";
98
99 const char FTInfo<float>::kTypePattern[sizeof(float)];
100 const char FTInfo<double>::kTypePattern[sizeof(double)];
101 const char FTInfo<long double>::kTypePattern[sizeof(long double)];
102
103 // Helper for __nsan_dump_shadow_mem: Reads the value at address `ptr`,
104 // identified by its type id.
105 template <typename ShadowFT>
ReadShadowInternal(const u8 * ptr)106 static __float128 ReadShadowInternal(const u8 *ptr) {
107 ShadowFT Shadow;
108 __builtin_memcpy(&Shadow, ptr, sizeof(Shadow));
109 return Shadow;
110 }
111
ReadShadow(const u8 * ptr,const char ShadowTypeId)112 static __float128 ReadShadow(const u8 *ptr, const char ShadowTypeId) {
113 switch (ShadowTypeId) {
114 case 'd':
115 return ReadShadowInternal<double>(ptr);
116 case 'l':
117 return ReadShadowInternal<long double>(ptr);
118 case 'q':
119 return ReadShadowInternal<__float128>(ptr);
120 default:
121 return 0.0;
122 }
123 }
124
125 namespace {
126 class Decorator : public __sanitizer::SanitizerCommonDecorator {
127 public:
Decorator()128 Decorator() : SanitizerCommonDecorator() {}
Warning()129 const char *Warning() { return Red(); }
Name()130 const char *Name() { return Green(); }
End()131 const char *End() { return Default(); }
132 };
133
134 // Workaround for the fact that Printf() does not support floats.
135 struct PrintBuffer {
136 char Buffer[64];
137 };
138 template <typename FT> struct FTPrinter {};
139
140 template <> struct FTPrinter<double> {
dec__anon36c45c920111::FTPrinter141 static PrintBuffer dec(double value) {
142 PrintBuffer result;
143 snprintf(result.Buffer, sizeof(result.Buffer) - 1, "%.20f", value);
144 return result;
145 }
hex__anon36c45c920111::FTPrinter146 static PrintBuffer hex(double value) {
147 PrintBuffer result;
148 snprintf(result.Buffer, sizeof(result.Buffer) - 1, "%.20a", value);
149 return result;
150 }
151 };
152
153 template <> struct FTPrinter<float> : FTPrinter<double> {};
154
155 template <> struct FTPrinter<long double> {
dec__anon36c45c920111::FTPrinter156 static PrintBuffer dec(long double value) {
157 PrintBuffer result;
158 snprintf(result.Buffer, sizeof(result.Buffer) - 1, "%.20Lf", value);
159 return result;
160 }
hex__anon36c45c920111::FTPrinter161 static PrintBuffer hex(long double value) {
162 PrintBuffer result;
163 snprintf(result.Buffer, sizeof(result.Buffer) - 1, "%.20La", value);
164 return result;
165 }
166 };
167
168 // FIXME: print with full precision.
169 template <> struct FTPrinter<__float128> : FTPrinter<long double> {};
170
171 // This is a template so that there are no implicit conversions.
172 template <typename FT> inline FT ftAbs(FT v);
173
ftAbs(long double v)174 template <> inline long double ftAbs(long double v) { return fabsl(v); }
ftAbs(double v)175 template <> inline double ftAbs(double v) { return fabs(v); }
176
177 // We don't care about nans.
178 // std::abs(__float128) code is suboptimal and generates a function call to
179 // __getf2().
ftAbs(FT v)180 template <typename FT> inline FT ftAbs(FT v) { return v >= FT{0} ? v : -v; }
181
182 template <typename FT1, typename FT2, bool Enable> struct LargestFTImpl {
183 using type = FT2;
184 };
185
186 template <typename FT1, typename FT2> struct LargestFTImpl<FT1, FT2, true> {
187 using type = FT1;
188 };
189
190 template <typename FT1, typename FT2>
191 using LargestFT =
192 typename LargestFTImpl<FT1, FT2, (sizeof(FT1) > sizeof(FT2))>::type;
193
max(T a,T b)194 template <typename T> T max(T a, T b) { return a < b ? b : a; }
195
196 } // end anonymous namespace
197
UnwindImpl(uptr pc,uptr bp,void * context,bool request_fast,u32 max_depth)198 void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp,
199 void *context,
200 bool request_fast,
201 u32 max_depth) {
202 using namespace __nsan;
203 NsanThread *t = GetCurrentThread();
204 if (!t || !StackTrace::WillUseFastUnwind(request_fast))
205 return Unwind(max_depth, pc, bp, context, t ? t->stack_top() : 0,
206 t ? t->stack_bottom() : 0, false);
207 if (StackTrace::WillUseFastUnwind(request_fast))
208 Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), true);
209 else
210 Unwind(max_depth, pc, 0, context, 0, 0, false);
211 }
212
__nsan_print_accumulated_stats()213 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_print_accumulated_stats() {
214 if (nsan_stats)
215 nsan_stats->Print();
216 }
217
NsanAtexit()218 static void NsanAtexit() {
219 Printf("Numerical Sanitizer exit stats:\n");
220 __nsan_print_accumulated_stats();
221 nsan_stats = nullptr;
222 }
223
224 // The next three functions return a pointer for storing a shadow value for `n`
225 // values, after setting the shadow types. We return the pointer instead of
226 // storing ourselves because it avoids having to rely on the calling convention
227 // around long double being the same for nsan and the target application.
228 // We have to have 3 versions because we need to know which type we are storing
229 // since we are setting the type shadow memory.
getShadowPtrForStore(u8 * store_addr,uptr n)230 template <typename FT> static u8 *getShadowPtrForStore(u8 *store_addr, uptr n) {
231 unsigned char *shadow_type = GetShadowTypeAddrFor(store_addr);
232 for (uptr i = 0; i < n; ++i) {
233 __builtin_memcpy(shadow_type + i * sizeof(FT), FTInfo<FT>::kTypePattern,
234 sizeof(FTInfo<FT>::kTypePattern));
235 }
236 return GetShadowAddrFor(store_addr);
237 }
238
239 extern "C" SANITIZER_INTERFACE_ATTRIBUTE u8 *
__nsan_get_shadow_ptr_for_float_store(u8 * store_addr,uptr n)240 __nsan_get_shadow_ptr_for_float_store(u8 *store_addr, uptr n) {
241 return getShadowPtrForStore<float>(store_addr, n);
242 }
243
244 extern "C" SANITIZER_INTERFACE_ATTRIBUTE u8 *
__nsan_get_shadow_ptr_for_double_store(u8 * store_addr,uptr n)245 __nsan_get_shadow_ptr_for_double_store(u8 *store_addr, uptr n) {
246 return getShadowPtrForStore<double>(store_addr, n);
247 }
248
249 extern "C" SANITIZER_INTERFACE_ATTRIBUTE u8 *
__nsan_get_shadow_ptr_for_longdouble_store(u8 * store_addr,uptr n)250 __nsan_get_shadow_ptr_for_longdouble_store(u8 *store_addr, uptr n) {
251 return getShadowPtrForStore<long double>(store_addr, n);
252 }
253
IsValidShadowType(const u8 * shadow_type)254 template <typename FT> static bool IsValidShadowType(const u8 *shadow_type) {
255 return __builtin_memcmp(shadow_type, FTInfo<FT>::kTypePattern, sizeof(FT)) ==
256 0;
257 }
258
IsZero(const T * ptr)259 template <int kSize, typename T> static bool IsZero(const T *ptr) {
260 constexpr const char kZeros[kSize] = {}; // Zero initialized.
261 return __builtin_memcmp(ptr, kZeros, kSize) == 0;
262 }
263
IsUnknownShadowType(const u8 * shadow_type)264 template <typename FT> static bool IsUnknownShadowType(const u8 *shadow_type) {
265 return IsZero<sizeof(FTInfo<FT>::kTypePattern)>(shadow_type);
266 }
267
268 // The three folowing functions check that the address stores a complete
269 // shadow value of the given type and return a pointer for loading.
270 // They return nullptr if the type of the value is unknown or incomplete.
271 template <typename FT>
getShadowPtrForLoad(const u8 * load_addr,uptr n)272 static const u8 *getShadowPtrForLoad(const u8 *load_addr, uptr n) {
273 const u8 *const shadow_type = GetShadowTypeAddrFor(load_addr);
274 for (uptr i = 0; i < n; ++i) {
275 if (!IsValidShadowType<FT>(shadow_type + i * sizeof(FT))) {
276 // If loadtracking stats are enabled, log loads with invalid types
277 // (tampered with through type punning).
278 if (flags().enable_loadtracking_stats) {
279 if (IsUnknownShadowType<FT>(shadow_type + i * sizeof(FT))) {
280 // Warn only if the value is non-zero. Zero is special because
281 // applications typically initialize large buffers to zero in an
282 // untyped way.
283 if (!IsZero<sizeof(FT)>(load_addr)) {
284 GET_CALLER_PC_BP;
285 nsan_stats->AddUnknownLoadTrackingEvent(pc, bp);
286 }
287 } else {
288 GET_CALLER_PC_BP;
289 nsan_stats->AddInvalidLoadTrackingEvent(pc, bp);
290 }
291 }
292 return nullptr;
293 }
294 }
295 return GetShadowAddrFor(load_addr);
296 }
297
298 extern "C" SANITIZER_INTERFACE_ATTRIBUTE const u8 *
__nsan_get_shadow_ptr_for_float_load(const u8 * load_addr,uptr n)299 __nsan_get_shadow_ptr_for_float_load(const u8 *load_addr, uptr n) {
300 return getShadowPtrForLoad<float>(load_addr, n);
301 }
302
303 extern "C" SANITIZER_INTERFACE_ATTRIBUTE const u8 *
__nsan_get_shadow_ptr_for_double_load(const u8 * load_addr,uptr n)304 __nsan_get_shadow_ptr_for_double_load(const u8 *load_addr, uptr n) {
305 return getShadowPtrForLoad<double>(load_addr, n);
306 }
307
308 extern "C" SANITIZER_INTERFACE_ATTRIBUTE const u8 *
__nsan_get_shadow_ptr_for_longdouble_load(const u8 * load_addr,uptr n)309 __nsan_get_shadow_ptr_for_longdouble_load(const u8 *load_addr, uptr n) {
310 return getShadowPtrForLoad<long double>(load_addr, n);
311 }
312
313 // Returns the raw shadow pointer. The returned pointer should be considered
314 // opaque.
315 extern "C" SANITIZER_INTERFACE_ATTRIBUTE u8 *
__nsan_internal_get_raw_shadow_ptr(const u8 * addr)316 __nsan_internal_get_raw_shadow_ptr(const u8 *addr) {
317 return GetShadowAddrFor(addr);
318 }
319
320 // Returns the raw shadow type pointer. The returned pointer should be
321 // considered opaque.
322 extern "C" SANITIZER_INTERFACE_ATTRIBUTE u8 *
__nsan_internal_get_raw_shadow_type_ptr(const u8 * addr)323 __nsan_internal_get_raw_shadow_type_ptr(const u8 *addr) {
324 return reinterpret_cast<u8 *>(GetShadowTypeAddrFor(addr));
325 }
326
getValueType(u8 c)327 static ValueType getValueType(u8 c) { return static_cast<ValueType>(c & 0x3); }
328
getValuePos(u8 c)329 static int getValuePos(u8 c) { return c >> kValueSizeSizeBits; }
330
331 // Checks the consistency of the value types at the given type pointer.
332 // If the value is inconsistent, returns ValueType::kUnknown. Else, return the
333 // consistent type.
334 template <typename FT>
checkValueConsistency(const u8 * shadow_type)335 static bool checkValueConsistency(const u8 *shadow_type) {
336 const int pos = getValuePos(*shadow_type);
337 // Check that all bytes from the start of the value are ordered.
338 for (uptr i = 0; i < sizeof(FT); ++i) {
339 const u8 T = *(shadow_type - pos + i);
340 if (!(getValueType(T) == FTInfo<FT>::kValueType && getValuePos(T) == i))
341 return false;
342 }
343 return true;
344 }
345
346 // The instrumentation automatically appends `shadow_value_type_ids`, see
347 // maybeAddSuffixForNsanInterface.
348 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_dump_shadow_mem(const u8 * addr,size_t size_bytes,size_t bytes_per_line,size_t shadow_value_type_ids)349 __nsan_dump_shadow_mem(const u8 *addr, size_t size_bytes, size_t bytes_per_line,
350 size_t shadow_value_type_ids) {
351 const u8 *const shadow_type = GetShadowTypeAddrFor(addr);
352 const u8 *const shadow = GetShadowAddrFor(addr);
353
354 constexpr int kMaxNumDecodedValues = 16;
355 __float128 decoded_values[kMaxNumDecodedValues];
356 int num_decoded_values = 0;
357 if (bytes_per_line > 4 * kMaxNumDecodedValues)
358 bytes_per_line = 4 * kMaxNumDecodedValues;
359
360 // We keep track of the current type and position as we go.
361 ValueType LastValueTy = kUnknownValueType;
362 int LastPos = -1;
363 size_t Offset = 0;
364 for (size_t R = 0; R < (size_bytes + bytes_per_line - 1) / bytes_per_line;
365 ++R) {
366 printf("%p: ", (void *)(addr + R * bytes_per_line));
367 for (size_t C = 0; C < bytes_per_line && Offset < size_bytes; ++C) {
368 const ValueType ValueTy = getValueType(shadow_type[Offset]);
369 const int pos = getValuePos(shadow_type[Offset]);
370 if (ValueTy == LastValueTy && pos == LastPos + 1) {
371 ++LastPos;
372 } else {
373 LastValueTy = ValueTy;
374 LastPos = pos == 0 ? 0 : -1;
375 }
376
377 switch (ValueTy) {
378 case kUnknownValueType:
379 printf("__ ");
380 break;
381 case kFloatValueType:
382 printf("f%x ", pos);
383 if (LastPos == sizeof(float) - 1) {
384 decoded_values[num_decoded_values] =
385 ReadShadow(shadow + kShadowScale * (Offset + 1 - sizeof(float)),
386 static_cast<char>(shadow_value_type_ids & 0xff));
387 ++num_decoded_values;
388 }
389 break;
390 case kDoubleValueType:
391 printf("d%x ", pos);
392 if (LastPos == sizeof(double) - 1) {
393 decoded_values[num_decoded_values] = ReadShadow(
394 shadow + kShadowScale * (Offset + 1 - sizeof(double)),
395 static_cast<char>((shadow_value_type_ids >> 8) & 0xff));
396 ++num_decoded_values;
397 }
398 break;
399 case kFp80ValueType:
400 printf("l%x ", pos);
401 if (LastPos == sizeof(long double) - 1) {
402 decoded_values[num_decoded_values] = ReadShadow(
403 shadow + kShadowScale * (Offset + 1 - sizeof(long double)),
404 static_cast<char>((shadow_value_type_ids >> 16) & 0xff));
405 ++num_decoded_values;
406 }
407 break;
408 }
409 ++Offset;
410 }
411 for (int i = 0; i < num_decoded_values; ++i) {
412 printf(" (%s)", FTPrinter<__float128>::dec(decoded_values[i]).Buffer);
413 }
414 num_decoded_values = 0;
415 printf("\n");
416 }
417 }
418
419 alignas(64) SANITIZER_INTERFACE_ATTRIBUTE
420 thread_local uptr __nsan_shadow_ret_tag = 0;
421
422 alignas(64) SANITIZER_INTERFACE_ATTRIBUTE
423 thread_local char __nsan_shadow_ret_ptr[kMaxVectorWidth *
424 sizeof(__float128)];
425
426 alignas(64) SANITIZER_INTERFACE_ATTRIBUTE
427 thread_local uptr __nsan_shadow_args_tag = 0;
428
429 // Maximum number of args. This should be enough for anyone (tm). An alternate
430 // scheme is to have the generated code create an alloca and make
431 // __nsan_shadow_args_ptr point ot the alloca.
432 constexpr const int kMaxNumArgs = 128;
433 alignas(64) SANITIZER_INTERFACE_ATTRIBUTE
434 thread_local char __nsan_shadow_args_ptr[kMaxVectorWidth * kMaxNumArgs *
435 sizeof(__float128)];
436
437 enum ContinuationType { // Keep in sync with instrumentation pass.
438 kContinueWithShadow = 0,
439 kResumeFromValue = 1,
440 };
441
442 // Checks the consistency between application and shadow value. Returns true
443 // when the instrumented code should resume computations from the original value
444 // rather than the shadow value. This prevents one error to propagate to all
445 // subsequent operations. This behaviour is tunable with flags.
446 template <typename FT, typename ShadowFT>
checkFT(const FT value,ShadowFT Shadow,CheckTypeT CheckType,uptr CheckArg)447 int32_t checkFT(const FT value, ShadowFT Shadow, CheckTypeT CheckType,
448 uptr CheckArg) {
449 // We do all comparisons in the InternalFT domain, which is the largest FT
450 // type.
451 using InternalFT = LargestFT<FT, ShadowFT>;
452 const InternalFT check_value = value;
453 const InternalFT check_shadow = Shadow;
454
455 // We only check for NaNs in the value, not the shadow.
456 if (flags().check_nan && isnan(value)) {
457 GET_CALLER_PC_BP;
458 BufferedStackTrace stack;
459 stack.Unwind(pc, bp, nullptr, false);
460 if (GetSuppressionForStack(&stack, CheckKind::Consistency)) {
461 // FIXME: optionally print.
462 return flags().resume_after_suppression ? kResumeFromValue
463 : kContinueWithShadow;
464 }
465 Decorator D;
466 Printf("%s", D.Warning());
467 Printf("WARNING: NumericalStabilitySanitizer: NaN detected\n");
468 Printf("%s", D.Default());
469 stack.Print();
470 if (flags().halt_on_error) {
471 if (common_flags()->abort_on_error)
472 Printf("ABORTING\n");
473 else
474 Printf("Exiting\n");
475 Die();
476 }
477 // Performing other tests for NaN values is meaningless when dealing with numbers.
478 return kResumeFromValue;
479 }
480
481 // See this article for an interesting discussion of how to compare floats:
482 // https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
483 static constexpr const FT Eps = FTInfo<FT>::kEpsilon;
484
485 const InternalFT abs_err = ftAbs(check_value - check_shadow);
486
487 if (flags().enable_check_stats) {
488 GET_CALLER_PC_BP;
489 // We are re-computing `largest` here because this is a cold branch, and we
490 // want to avoid having to move the computation of `largest` before the
491 // absolute value check when this branch is not taken.
492 const InternalFT largest = max(ftAbs(check_value), ftAbs(check_shadow));
493 nsan_stats->AddCheck(CheckType, pc, bp, abs_err / largest);
494 }
495
496 // Note: writing the comparison that way ensures that when `abs_err` is Nan
497 // (value and shadow are inf or -inf), we pass the test.
498 if (!(abs_err >= flags().cached_absolute_error_threshold))
499 return kContinueWithShadow;
500
501 const InternalFT largest = max(ftAbs(check_value), ftAbs(check_shadow));
502 if (abs_err * (1ull << flags().log2_max_relative_error) <= largest)
503 return kContinueWithShadow; // No problem here.
504
505 if (!flags().disable_warnings) {
506 GET_CALLER_PC_BP;
507 UNINITIALIZED BufferedStackTrace stack;
508 stack.Unwind(pc, bp, nullptr, false);
509 if (GetSuppressionForStack(&stack, CheckKind::Consistency)) {
510 // FIXME: optionally print.
511 return flags().resume_after_suppression ? kResumeFromValue
512 : kContinueWithShadow;
513 }
514
515 Decorator D;
516 Printf("%s", D.Warning());
517 // Printf does not support float formatting.
518 char RelErrBuf[64] = "inf";
519 if (largest > Eps) {
520 snprintf(RelErrBuf, sizeof(RelErrBuf) - 1, "%.20Lf%% (2^%.0Lf epsilons)",
521 static_cast<long double>(100.0 * abs_err / largest),
522 log2l(static_cast<long double>(abs_err / largest / Eps)));
523 }
524 char ulp_err_buf[128] = "";
525 const double shadow_ulp_diff = GetULPDiff(check_value, check_shadow);
526 if (shadow_ulp_diff != kMaxULPDiff) {
527 // This is the ULP diff in the internal domain. The user actually cares
528 // about that in the original domain.
529 const double ulp_diff =
530 shadow_ulp_diff / (u64{1} << (FTInfo<InternalFT>::kMantissaBits -
531 FTInfo<FT>::kMantissaBits));
532 snprintf(ulp_err_buf, sizeof(ulp_err_buf) - 1,
533 "(%.0f ULPs == %.1f digits == %.1f bits)", ulp_diff,
534 log10(ulp_diff), log2(ulp_diff));
535 }
536 Printf("WARNING: NumericalStabilitySanitizer: inconsistent shadow results");
537 switch (CheckType) {
538 case CheckTypeT::kUnknown:
539 case CheckTypeT::kFcmp:
540 case CheckTypeT::kMaxCheckType:
541 break;
542 case CheckTypeT::kRet:
543 Printf(" while checking return value");
544 break;
545 case CheckTypeT::kArg:
546 Printf(" while checking call argument #%d", static_cast<int>(CheckArg));
547 break;
548 case CheckTypeT::kLoad:
549 Printf(
550 " while checking load from address 0x%lx. This is due to incorrect "
551 "shadow memory tracking, typically due to uninstrumented code "
552 "writing to memory.",
553 CheckArg);
554 break;
555 case CheckTypeT::kStore:
556 Printf(" while checking store to address 0x%lx", CheckArg);
557 break;
558 case CheckTypeT::kInsert:
559 Printf(" while checking vector insert");
560 break;
561 case CheckTypeT::kUser:
562 Printf(" in user-initiated check");
563 break;
564 }
565 using ValuePrinter = FTPrinter<FT>;
566 using ShadowPrinter = FTPrinter<ShadowFT>;
567 Printf("%s", D.Default());
568
569 Printf("\n"
570 "%-12s precision (native): dec: %s hex: %s\n"
571 "%-12s precision (shadow): dec: %s hex: %s\n"
572 "shadow truncated to %-12s: dec: %s hex: %s\n"
573 "Relative error: %s\n"
574 "Absolute error: %s\n"
575 "%s\n",
576 FTInfo<FT>::kCppTypeName, ValuePrinter::dec(value).Buffer,
577 ValuePrinter::hex(value).Buffer, FTInfo<ShadowFT>::kCppTypeName,
578 ShadowPrinter::dec(Shadow).Buffer, ShadowPrinter::hex(Shadow).Buffer,
579 FTInfo<FT>::kCppTypeName, ValuePrinter::dec(Shadow).Buffer,
580 ValuePrinter::hex(Shadow).Buffer, RelErrBuf,
581 ValuePrinter::hex(abs_err).Buffer, ulp_err_buf);
582 stack.Print();
583 }
584
585 if (flags().enable_warning_stats) {
586 GET_CALLER_PC_BP;
587 nsan_stats->AddWarning(CheckType, pc, bp, abs_err / largest);
588 }
589
590 if (flags().halt_on_error) {
591 if (common_flags()->abort_on_error)
592 Printf("ABORTING\n");
593 else
594 Printf("Exiting\n");
595 Die();
596 }
597 return flags().resume_after_warning ? kResumeFromValue : kContinueWithShadow;
598 }
599
__nsan_internal_check_float_d(float value,double shadow,int32_t check_type,uptr check_arg)600 extern "C" SANITIZER_INTERFACE_ATTRIBUTE int32_t __nsan_internal_check_float_d(
601 float value, double shadow, int32_t check_type, uptr check_arg) {
602 return checkFT(value, shadow, static_cast<CheckTypeT>(check_type), check_arg);
603 }
604
__nsan_internal_check_double_l(double value,long double shadow,int32_t check_type,uptr check_arg)605 extern "C" SANITIZER_INTERFACE_ATTRIBUTE int32_t __nsan_internal_check_double_l(
606 double value, long double shadow, int32_t check_type, uptr check_arg) {
607 return checkFT(value, shadow, static_cast<CheckTypeT>(check_type), check_arg);
608 }
609
__nsan_internal_check_double_q(double value,__float128 shadow,int32_t check_type,uptr check_arg)610 extern "C" SANITIZER_INTERFACE_ATTRIBUTE int32_t __nsan_internal_check_double_q(
611 double value, __float128 shadow, int32_t check_type, uptr check_arg) {
612 return checkFT(value, shadow, static_cast<CheckTypeT>(check_type), check_arg);
613 }
614
615 extern "C" SANITIZER_INTERFACE_ATTRIBUTE int32_t
__nsan_internal_check_longdouble_q(long double value,__float128 shadow,int32_t check_type,uptr check_arg)616 __nsan_internal_check_longdouble_q(long double value, __float128 shadow,
617 int32_t check_type, uptr check_arg) {
618 return checkFT(value, shadow, static_cast<CheckTypeT>(check_type), check_arg);
619 }
620
GetTruthValueName(bool v)621 static const char *GetTruthValueName(bool v) { return v ? "true" : "false"; }
622
623 // This uses the same values as CmpInst::Predicate.
GetPredicateName(int v)624 static const char *GetPredicateName(int v) {
625 switch (v) {
626 case 0:
627 return "(false)";
628 case 1:
629 return "==";
630 case 2:
631 return ">";
632 case 3:
633 return ">=";
634 case 4:
635 return "<";
636 case 5:
637 return "<=";
638 case 6:
639 return "!=";
640 case 7:
641 return "(ordered)";
642 case 8:
643 return "(unordered)";
644 case 9:
645 return "==";
646 case 10:
647 return ">";
648 case 11:
649 return ">=";
650 case 12:
651 return "<";
652 case 13:
653 return "<=";
654 case 14:
655 return "!=";
656 case 15:
657 return "(true)";
658 }
659 return "??";
660 }
661
662 template <typename FT, typename ShadowFT>
fCmpFailFT(const FT Lhs,const FT Rhs,ShadowFT LhsShadow,ShadowFT RhsShadow,int Predicate,bool result,bool ShadowResult)663 void fCmpFailFT(const FT Lhs, const FT Rhs, ShadowFT LhsShadow,
664 ShadowFT RhsShadow, int Predicate, bool result,
665 bool ShadowResult) {
666 if (result == ShadowResult) {
667 // When a vector comparison fails, we fail each element of the comparison
668 // to simplify instrumented code. Skip elements where the shadow comparison
669 // gave the same result as the original one.
670 return;
671 }
672
673 GET_CALLER_PC_BP;
674 UNINITIALIZED BufferedStackTrace stack;
675 stack.Unwind(pc, bp, nullptr, false);
676
677 if (GetSuppressionForStack(&stack, CheckKind::Fcmp)) {
678 // FIXME: optionally print.
679 return;
680 }
681
682 if (flags().enable_warning_stats)
683 nsan_stats->AddWarning(CheckTypeT::kFcmp, pc, bp, 0.0);
684
685 if (flags().disable_warnings || !flags().check_cmp)
686 return;
687
688 // FIXME: ideally we would print the shadow value as FP128. Right now because
689 // we truncate to long double we can sometimes see stuff like:
690 // shadow <value> == <value> (false)
691 using ValuePrinter = FTPrinter<FT>;
692 using ShadowPrinter = FTPrinter<ShadowFT>;
693 Decorator D;
694 const char *const PredicateName = GetPredicateName(Predicate);
695 Printf("%s", D.Warning());
696 Printf("WARNING: NumericalStabilitySanitizer: floating-point comparison "
697 "results depend on precision\n");
698 Printf("%s", D.Default());
699 Printf("%-12s precision dec (native): %s %s %s (%s)\n"
700 "%-12s precision dec (shadow): %s %s %s (%s)\n"
701 "%-12s precision hex (native): %s %s %s (%s)\n"
702 "%-12s precision hex (shadow): %s %s %s (%s)\n"
703 "%s",
704 // Native, decimal.
705 FTInfo<FT>::kCppTypeName, ValuePrinter::dec(Lhs).Buffer, PredicateName,
706 ValuePrinter::dec(Rhs).Buffer, GetTruthValueName(result),
707 // Shadow, decimal
708 FTInfo<ShadowFT>::kCppTypeName, ShadowPrinter::dec(LhsShadow).Buffer,
709 PredicateName, ShadowPrinter::dec(RhsShadow).Buffer,
710 GetTruthValueName(ShadowResult),
711 // Native, hex.
712 FTInfo<FT>::kCppTypeName, ValuePrinter::hex(Lhs).Buffer, PredicateName,
713 ValuePrinter::hex(Rhs).Buffer, GetTruthValueName(result),
714 // Shadow, hex
715 FTInfo<ShadowFT>::kCppTypeName, ShadowPrinter::hex(LhsShadow).Buffer,
716 PredicateName, ShadowPrinter::hex(RhsShadow).Buffer,
717 GetTruthValueName(ShadowResult), D.End());
718 stack.Print();
719 if (flags().halt_on_error) {
720 Printf("Exiting\n");
721 Die();
722 }
723 }
724
725 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_fcmp_fail_float_d(float lhs,float rhs,double lhs_shadow,double rhs_shadow,int predicate,bool result,bool shadow_result)726 __nsan_fcmp_fail_float_d(float lhs, float rhs, double lhs_shadow,
727 double rhs_shadow, int predicate, bool result,
728 bool shadow_result) {
729 fCmpFailFT(lhs, rhs, lhs_shadow, rhs_shadow, predicate, result,
730 shadow_result);
731 }
732
733 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_fcmp_fail_double_q(double lhs,double rhs,__float128 lhs_shadow,__float128 rhs_shadow,int predicate,bool result,bool shadow_result)734 __nsan_fcmp_fail_double_q(double lhs, double rhs, __float128 lhs_shadow,
735 __float128 rhs_shadow, int predicate, bool result,
736 bool shadow_result) {
737 fCmpFailFT(lhs, rhs, lhs_shadow, rhs_shadow, predicate, result,
738 shadow_result);
739 }
740
741 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_fcmp_fail_double_l(double lhs,double rhs,long double lhs_shadow,long double rhs_shadow,int predicate,bool result,bool shadow_result)742 __nsan_fcmp_fail_double_l(double lhs, double rhs, long double lhs_shadow,
743 long double rhs_shadow, int predicate, bool result,
744 bool shadow_result) {
745 fCmpFailFT(lhs, rhs, lhs_shadow, rhs_shadow, predicate, result,
746 shadow_result);
747 }
748
749 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_fcmp_fail_longdouble_q(long double lhs,long double rhs,__float128 lhs_shadow,__float128 rhs_shadow,int predicate,bool result,bool shadow_result)750 __nsan_fcmp_fail_longdouble_q(long double lhs, long double rhs,
751 __float128 lhs_shadow, __float128 rhs_shadow,
752 int predicate, bool result, bool shadow_result) {
753 fCmpFailFT(lhs, rhs, lhs_shadow, rhs_shadow, predicate, result,
754 shadow_result);
755 }
756
checkFTFromShadowStack(const FT value)757 template <typename FT> void checkFTFromShadowStack(const FT value) {
758 // Get the shadow 2FT value from the shadow stack. Note that
759 // __nsan_check_{float,double,long double} is a function like any other, so
760 // the instrumentation will have placed the shadow value on the shadow stack.
761 using ShadowFT = typename FTInfo<FT>::shadow_type;
762 ShadowFT Shadow;
763 __builtin_memcpy(&Shadow, __nsan_shadow_args_ptr, sizeof(ShadowFT));
764 checkFT(value, Shadow, CheckTypeT::kUser, 0);
765 }
766
767 // FIXME: Add suffixes and let the instrumentation pass automatically add
768 // suffixes.
__nsan_check_float(float value)769 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_check_float(float value) {
770 assert(__nsan_shadow_args_tag == (uptr)&__nsan_check_float &&
771 "__nsan_check_float called from non-instrumented function");
772 checkFTFromShadowStack(value);
773 }
774
775 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_check_double(double value)776 __nsan_check_double(double value) {
777 assert(__nsan_shadow_args_tag == (uptr)&__nsan_check_double &&
778 "__nsan_check_double called from non-instrumented function");
779 checkFTFromShadowStack(value);
780 }
781
782 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_check_longdouble(long double value)783 __nsan_check_longdouble(long double value) {
784 assert(__nsan_shadow_args_tag == (uptr)&__nsan_check_longdouble &&
785 "__nsan_check_longdouble called from non-instrumented function");
786 checkFTFromShadowStack(value);
787 }
788
dumpFTFromShadowStack(const FT value)789 template <typename FT> static void dumpFTFromShadowStack(const FT value) {
790 // Get the shadow 2FT value from the shadow stack. Note that
791 // __nsan_dump_{float,double,long double} is a function like any other, so
792 // the instrumentation will have placed the shadow value on the shadow stack.
793 using ShadowFT = typename FTInfo<FT>::shadow_type;
794 ShadowFT shadow;
795 __builtin_memcpy(&shadow, __nsan_shadow_args_ptr, sizeof(ShadowFT));
796 using ValuePrinter = FTPrinter<FT>;
797 using ShadowPrinter = FTPrinter<typename FTInfo<FT>::shadow_type>;
798 printf("value dec:%s hex:%s\n"
799 "shadow dec:%s hex:%s\n",
800 ValuePrinter::dec(value).Buffer, ValuePrinter::hex(value).Buffer,
801 ShadowPrinter::dec(shadow).Buffer, ShadowPrinter::hex(shadow).Buffer);
802 }
803
__nsan_dump_float(float value)804 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_dump_float(float value) {
805 assert(__nsan_shadow_args_tag == (uptr)&__nsan_dump_float &&
806 "__nsan_dump_float called from non-instrumented function");
807 dumpFTFromShadowStack(value);
808 }
809
__nsan_dump_double(double value)810 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_dump_double(double value) {
811 assert(__nsan_shadow_args_tag == (uptr)&__nsan_dump_double &&
812 "__nsan_dump_double called from non-instrumented function");
813 dumpFTFromShadowStack(value);
814 }
815
816 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_dump_longdouble(long double value)817 __nsan_dump_longdouble(long double value) {
818 assert(__nsan_shadow_args_tag == (uptr)&__nsan_dump_longdouble &&
819 "__nsan_dump_longdouble called from non-instrumented function");
820 dumpFTFromShadowStack(value);
821 }
822
__nsan_dump_shadow_ret()823 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_dump_shadow_ret() {
824 printf("ret tag: %lx\n", __nsan_shadow_ret_tag);
825 double v;
826 __builtin_memcpy(&v, __nsan_shadow_ret_ptr, sizeof(double));
827 printf("double value: %f\n", v);
828 // FIXME: float128 value.
829 }
830
__nsan_dump_shadow_args()831 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_dump_shadow_args() {
832 printf("args tag: %lx\n", __nsan_shadow_args_tag);
833 }
834
835 bool __nsan::nsan_initialized;
836 bool __nsan::nsan_init_is_running;
837
__nsan_init()838 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_init() {
839 CHECK(!nsan_init_is_running);
840 if (nsan_initialized)
841 return;
842 nsan_init_is_running = true;
843 SanitizerToolName = "NumericalStabilitySanitizer";
844
845 InitializeFlags();
846 InitializeSuppressions();
847 InitializePlatformEarly();
848
849 DisableCoreDumperIfNecessary();
850
851 if (!MmapFixedNoReserve(TypesAddr(), AllocatorAddr() - TypesAddr()))
852 Die();
853
854 InitializeInterceptors();
855 NsanTSDInit(NsanTSDDtor);
856 NsanAllocatorInit();
857
858 NsanThread *main_thread = NsanThread::Create(nullptr, nullptr);
859 SetCurrentThread(main_thread);
860 main_thread->Init();
861
862 InitializeStats();
863 if (flags().print_stats_on_exit)
864 Atexit(NsanAtexit);
865
866 nsan_init_is_running = false;
867 nsan_initialized = true;
868 }
869