[compiler-rt] r338287 - [compiler-rt][ubsan] Implicit Conversion Sanitizer - integer truncation - compiler-rt part

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 30 11:58:30 PDT 2018


Author: lebedevri
Date: Mon Jul 30 11:58:30 2018
New Revision: 338287

URL: http://llvm.org/viewvc/llvm-project?rev=338287&view=rev
Log:
[compiler-rt][ubsan] Implicit Conversion Sanitizer - integer truncation  - compiler-rt part

Summary:
This is a compiler-rt part.
The clang part is D48958.

See [[ https://bugs.llvm.org/show_bug.cgi?id=21530 | PR21530 ]], https://github.com/google/sanitizers/issues/940.

Reviewers: #sanitizers, samsonov, vsk, rsmith, pcc, eugenis, kcc, filcab

Reviewed By: #sanitizers, vsk, filcab

Subscribers: llvm-commits, eugenis, filcab, kubamracek, dberris, #sanitizers, regehr

Tags: #sanitizers

Differential Revision: https://reviews.llvm.org/D48959

Added:
    compiler-rt/trunk/test/fuzzer/ImplicitIntegerTruncationTest.cpp
    compiler-rt/trunk/test/fuzzer/fuzzer-implicit-integer-truncation.test
    compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/
    compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/integer-truncation-blacklist.c
    compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/integer-truncation-summary.cpp
    compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/integer-truncation.c
    compiler-rt/trunk/test/ubsan_minimal/TestCases/implicit-integer-truncation.c
Modified:
    compiler-rt/trunk/lib/ubsan/ubsan_checks.inc
    compiler-rt/trunk/lib/ubsan/ubsan_diag.h
    compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc
    compiler-rt/trunk/lib/ubsan/ubsan_handlers.h
    compiler-rt/trunk/lib/ubsan/ubsan_interface.inc
    compiler-rt/trunk/lib/ubsan_minimal/ubsan_minimal_handlers.cc

Modified: compiler-rt/trunk/lib/ubsan/ubsan_checks.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_checks.inc?rev=338287&r1=338286&r2=338287&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_checks.inc (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_checks.inc Mon Jul 30 11:58:30 2018
@@ -30,6 +30,8 @@ UBSAN_CHECK(IntegerDivideByZero, "intege
             "integer-divide-by-zero")
 UBSAN_CHECK(FloatDivideByZero, "float-divide-by-zero", "float-divide-by-zero")
 UBSAN_CHECK(InvalidBuiltin, "invalid-builtin-use", "invalid-builtin-use")
+UBSAN_CHECK(ImplicitIntegerTruncation, "implicit-integer-truncation",
+            "implicit-integer-truncation")
 UBSAN_CHECK(InvalidShiftBase, "invalid-shift-base", "shift-base")
 UBSAN_CHECK(InvalidShiftExponent, "invalid-shift-exponent", "shift-exponent")
 UBSAN_CHECK(OutOfBoundsIndex, "out-of-bounds-index", "bounds")

Modified: compiler-rt/trunk/lib/ubsan/ubsan_diag.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_diag.h?rev=338287&r1=338286&r2=338287&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_diag.h (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_diag.h Mon Jul 30 11:58:30 2018
@@ -178,7 +178,7 @@ public:
   };
 
 private:
-  static const unsigned MaxArgs = 5;
+  static const unsigned MaxArgs = 8;
   static const unsigned MaxRanges = 1;
 
   /// The arguments which have been added to this diagnostic so far.

Modified: compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc?rev=338287&r1=338286&r2=338287&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc Mon Jul 30 11:58:30 2018
@@ -451,6 +451,49 @@ void __ubsan::__ubsan_handle_load_invali
   Die();
 }
 
+static void handleImplicitConversion(ImplicitConversionData *Data,
+                                     ReportOptions Opts, ValueHandle Src,
+                                     ValueHandle Dst) {
+  SourceLocation Loc = Data->Loc.acquire();
+  ErrorType ET = ErrorType::GenericUB;
+
+  switch (Data->Kind) {
+  case ICCK_IntegerTruncation:
+    ET = ErrorType::ImplicitIntegerTruncation;
+    break;
+  }
+
+  if (ignoreReport(Loc, Opts, ET))
+    return;
+
+  const TypeDescriptor &SrcTy = Data->FromType;
+  const TypeDescriptor &DstTy = Data->ToType;
+
+  ScopedReport R(Opts, Loc, ET);
+
+  // FIXME: is it possible to dump the values as hex with fixed width?
+
+  Diag(Loc, DL_Error, ET,
+       "implicit conversion from type %0 of value %1 (%2-bit, %3signed) to "
+       "type %4 changed the value to %5 (%6-bit, %7signed)")
+      << SrcTy << Value(SrcTy, Src) << SrcTy.getIntegerBitWidth()
+      << (SrcTy.isSignedIntegerTy() ? "" : "un") << DstTy << Value(DstTy, Dst)
+      << DstTy.getIntegerBitWidth() << (DstTy.isSignedIntegerTy() ? "" : "un");
+}
+
+void __ubsan::__ubsan_handle_implicit_conversion(ImplicitConversionData *Data,
+                                                 ValueHandle Src,
+                                                 ValueHandle Dst) {
+  GET_REPORT_OPTIONS(false);
+  handleImplicitConversion(Data, Opts, Src, Dst);
+}
+void __ubsan::__ubsan_handle_implicit_conversion_abort(
+    ImplicitConversionData *Data, ValueHandle Src, ValueHandle Dst) {
+  GET_REPORT_OPTIONS(true);
+  handleImplicitConversion(Data, Opts, Src, Dst);
+  Die();
+}
+
 static void handleInvalidBuiltin(InvalidBuiltinData *Data, ReportOptions Opts) {
   SourceLocation Loc = Data->Loc.acquire();
   ErrorType ET = ErrorType::InvalidBuiltin;

Modified: compiler-rt/trunk/lib/ubsan/ubsan_handlers.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_handlers.h?rev=338287&r1=338286&r2=338287&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_handlers.h (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_handlers.h Mon Jul 30 11:58:30 2018
@@ -122,6 +122,23 @@ struct InvalidValueData {
 /// \brief Handle a load of an invalid value for the type.
 RECOVERABLE(load_invalid_value, InvalidValueData *Data, ValueHandle Val)
 
+/// Known implicit conversion check kinds.
+/// Keep in sync with the enum of the same name in CGExprScalar.cpp
+enum ImplicitConversionCheckKind : unsigned char {
+  ICCK_IntegerTruncation = 0,
+};
+
+struct ImplicitConversionData {
+  SourceLocation Loc;
+  const TypeDescriptor &FromType;
+  const TypeDescriptor &ToType;
+  /* ImplicitConversionCheckKind */ unsigned char Kind;
+};
+
+/// \brief Implict conversion that changed the value.
+RECOVERABLE(implicit_conversion, ImplicitConversionData *Data, ValueHandle Src,
+            ValueHandle Dst)
+
 /// Known builtin check kinds.
 /// Keep in sync with the enum of the same name in CodeGenFunction.h
 enum BuiltinCheckKind : unsigned char {

Modified: compiler-rt/trunk/lib/ubsan/ubsan_interface.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_interface.inc?rev=338287&r1=338286&r2=338287&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_interface.inc (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_interface.inc Mon Jul 30 11:58:30 2018
@@ -22,6 +22,8 @@ INTERFACE_FUNCTION(__ubsan_handle_float_
 INTERFACE_FUNCTION(__ubsan_handle_float_cast_overflow_abort)
 INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch)
 INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_abort)
+INTERFACE_FUNCTION(__ubsan_handle_implicit_conversion)
+INTERFACE_FUNCTION(__ubsan_handle_implicit_conversion_abort)
 INTERFACE_FUNCTION(__ubsan_handle_invalid_builtin)
 INTERFACE_FUNCTION(__ubsan_handle_invalid_builtin_abort)
 INTERFACE_FUNCTION(__ubsan_handle_load_invalid_value)

Modified: compiler-rt/trunk/lib/ubsan_minimal/ubsan_minimal_handlers.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan_minimal/ubsan_minimal_handlers.cc?rev=338287&r1=338286&r2=338287&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan_minimal/ubsan_minimal_handlers.cc (original)
+++ compiler-rt/trunk/lib/ubsan_minimal/ubsan_minimal_handlers.cc Mon Jul 30 11:58:30 2018
@@ -109,6 +109,7 @@ HANDLER(float_cast_overflow, "float-cast
 HANDLER(load_invalid_value, "load-invalid-value")
 HANDLER(invalid_builtin, "invalid-builtin")
 HANDLER(function_type_mismatch, "function-type-mismatch")
+HANDLER(implicit_conversion, "implicit-conversion")
 HANDLER(nonnull_arg, "nonnull-arg")
 HANDLER(nonnull_return, "nonnull-return")
 HANDLER(nullability_arg, "nullability-arg")

Added: compiler-rt/trunk/test/fuzzer/ImplicitIntegerTruncationTest.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/fuzzer/ImplicitIntegerTruncationTest.cpp?rev=338287&view=auto
==============================================================================
--- compiler-rt/trunk/test/fuzzer/ImplicitIntegerTruncationTest.cpp (added)
+++ compiler-rt/trunk/test/fuzzer/ImplicitIntegerTruncationTest.cpp Mon Jul 30 11:58:30 2018
@@ -0,0 +1,27 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test for signed-integer-overflow.
+#include <assert.h>
+#include <climits>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+
+static volatile int Sink;
+static unsigned char Large = UINT8_MAX;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+  assert(Data);
+  if (Size > 0 && Data[0] == 'H') {
+    Sink = 1;
+    if (Size > 1 && Data[1] == 'i') {
+      Sink = 2;
+      if (Size > 2 && Data[2] == '!') {
+        Large = Large + 1;  // 'char overflow'.
+      }
+    }
+  }
+  return 0;
+}

Added: compiler-rt/trunk/test/fuzzer/fuzzer-implicit-integer-truncation.test
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/fuzzer/fuzzer-implicit-integer-truncation.test?rev=338287&view=auto
==============================================================================
--- compiler-rt/trunk/test/fuzzer/fuzzer-implicit-integer-truncation.test (added)
+++ compiler-rt/trunk/test/fuzzer/fuzzer-implicit-integer-truncation.test Mon Jul 30 11:58:30 2018
@@ -0,0 +1,5 @@
+RUN: rm -f %t-ImplicitIntegerTruncationTest-Ubsan
+RUN: %cpp_compiler -fsanitize=implicit-integer-truncation -fno-sanitize-recover=all %S/ImplicitIntegerTruncationTest.cpp -o %t-ImplicitIntegerTruncationTest-Ubsan
+RUN: not %run %t-ImplicitIntegerTruncationTest-Ubsan 2>&1 | FileCheck %s
+CHECK: runtime error: implicit conversion from type 'int' of value 256 (32-bit, signed) to type 'unsigned char' changed the value to 0 (8-bit, unsigned)
+CHECK: Test unit written to ./crash-

Added: compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/integer-truncation-blacklist.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/integer-truncation-blacklist.c?rev=338287&view=auto
==============================================================================
--- compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/integer-truncation-blacklist.c (added)
+++ compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/integer-truncation-blacklist.c Mon Jul 30 11:58:30 2018
@@ -0,0 +1,15 @@
+// RUN: rm -f %tmp
+// RUN: echo "[implicit-integer-truncation]" >> %tmp
+// RUN: echo "fun:*implicitTruncation*" >> %tmp
+// RUN: %clang -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-integer-truncation -fsanitize-blacklist=%tmp -O0 %s -o %t && not %run %t 2>&1
+// RUN: %clang -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-integer-truncation -fsanitize-blacklist=%tmp -O1 %s -o %t && not %run %t 2>&1
+// RUN: %clang -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-integer-truncation -fsanitize-blacklist=%tmp -O2 %s -o %t && not %run %t 2>&1
+// RUN: %clang -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-integer-truncation -fsanitize-blacklist=%tmp -O3 %s -o %t && not %run %t 2>&1
+
+unsigned char implicitTruncation(unsigned int argc) {
+  return argc; // BOOM
+}
+
+int main(int argc, char **argv) {
+  return implicitTruncation(~0U);
+}

Added: compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/integer-truncation-summary.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/integer-truncation-summary.cpp?rev=338287&view=auto
==============================================================================
--- compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/integer-truncation-summary.cpp (added)
+++ compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/integer-truncation-summary.cpp Mon Jul 30 11:58:30 2018
@@ -0,0 +1,13 @@
+// RUN: %clangxx -fsanitize=implicit-integer-truncation %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NOTYPE
+// RUN: %env_ubsan_opts=report_error_type=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TYPE
+// REQUIRES: !ubsan-standalone && !ubsan-standalone-static
+
+#include <stdint.h>
+
+int main() {
+  uint8_t t0 = (~(uint32_t(0)));
+  // CHECK-NOTYPE: SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior {{.*}}summary.cpp:[[@LINE-1]]:16
+  // CHECK-TYPE: SUMMARY: UndefinedBehaviorSanitizer: implicit-integer-truncation {{.*}}summary.cpp:[[@LINE-2]]:16
+  return 0;
+}

Added: compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/integer-truncation.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/integer-truncation.c?rev=338287&view=auto
==============================================================================
--- compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/integer-truncation.c (added)
+++ compiler-rt/trunk/test/ubsan/TestCases/ImplicitCast/integer-truncation.c Mon Jul 30 11:58:30 2018
@@ -0,0 +1,63 @@
+// RUN: %clang   -x c   -fsanitize=implicit-integer-truncation %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK
+// RUN: %clangxx -x c++ -fsanitize=implicit-integer-truncation %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK
+
+#include <stdint.h>
+
+#if !defined(__cplusplus)
+#define bool _Bool
+#endif
+
+int main() {
+// CHECK-NOT: integer-truncation.c
+
+  // Negative tests. Even if they produce unexpected results, this sanitizer does not care.
+  int8_t n0 = (~((uint32_t)0)); // ~0 -> -1, but do not warn.
+  uint8_t n2 = 128;
+  uint8_t n3 = 255;
+  // Bools do not count
+  bool b0 = (~((uint32_t)0));
+  bool b1 = 255;
+
+  // Explicit and-ing of bits will silence it.
+  uint8_t nc0 = (~((uint32_t)0)) & 255;
+
+  // Explicit casts
+  uint8_t i0 = (uint8_t)(~((uint32_t)0));
+
+#if defined(__cplusplus)
+  uint8_t i1 = uint8_t(~(uint32_t(0)));
+  uint8_t i2 = static_cast<uint8_t>(~(uint32_t(0)));
+#endif
+
+  // Positive tests.
+
+  uint8_t t_b0 = (~((uint16_t)(0)));
+// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:18: runtime error: implicit conversion from type 'int' of value -1 (32-bit, signed) to type 'uint8_t' (aka 'unsigned char') changed the value to 255 (8-bit, unsigned)
+
+  uint8_t t_b1 = (~((uint32_t)0));
+// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:18: runtime error: implicit conversion from type 'uint32_t' (aka 'unsigned int') of value 4294967295 (32-bit, unsigned) to type 'uint8_t' (aka 'unsigned char') changed the value to 255 (8-bit, unsigned)
+  uint16_t t_b2 = (~((uint32_t)0));
+// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:19: runtime error: implicit conversion from type 'uint32_t' (aka 'unsigned int') of value 4294967295 (32-bit, unsigned) to type 'uint16_t' (aka 'unsigned short') changed the value to 65535 (16-bit, unsigned)
+
+  uint8_t t_b3 = ~((uint64_t)0);
+// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:18: runtime error: implicit conversion from type 'uint64_t' (aka 'unsigned long{{[^']*}}') of value 18446744073709551615 (64-bit, unsigned) to type 'uint8_t' (aka 'unsigned char') changed the value to 255 (8-bit, unsigned)
+  uint16_t t_b4 = ~((uint64_t)0);
+// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:19: runtime error: implicit conversion from type 'uint64_t' (aka 'unsigned long{{[^']*}}') of value 18446744073709551615 (64-bit, unsigned) to type 'uint16_t' (aka 'unsigned short') changed the value to 65535 (16-bit, unsigned)
+  uint32_t t_b5 = ~((uint64_t)0);
+// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:19: runtime error: implicit conversion from type 'uint64_t' (aka 'unsigned long{{[^']*}}') of value 18446744073709551615 (64-bit, unsigned) to type 'uint32_t' (aka 'unsigned int') changed the value to 4294967295 (32-bit, unsigned)
+
+  int8_t t1 = 255;
+// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:15: runtime error: implicit conversion from type 'int' of value 255 (32-bit, signed) to type 'int8_t' (aka 'signed char') changed the value to -1 (8-bit, signed)
+  uint8_t t2 = 256;
+// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:16: runtime error: implicit conversion from type 'int' of value 256 (32-bit, signed) to type 'uint8_t' (aka 'unsigned char') changed the value to 0 (8-bit, unsigned)
+  int8_t t3 = 256;
+// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:15: runtime error: implicit conversion from type 'int' of value 256 (32-bit, signed) to type 'int8_t' (aka 'signed char') changed the value to 0 (8-bit, signed)
+  uint8_t t4 = 257;
+// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:16: runtime error: implicit conversion from type 'int' of value 257 (32-bit, signed) to type 'uint8_t' (aka 'unsigned char') changed the value to 1 (8-bit, unsigned)
+  int8_t t5 = 257;
+// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:15: runtime error: implicit conversion from type 'int' of value 257 (32-bit, signed) to type 'int8_t' (aka 'signed char') changed the value to 1 (8-bit, signed)
+  int8_t t6 = 128;
+// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:15: runtime error: implicit conversion from type 'int' of value 128 (32-bit, signed) to type 'int8_t' (aka 'signed char') changed the value to -128 (8-bit, signed)
+
+  return 0;
+}

Added: compiler-rt/trunk/test/ubsan_minimal/TestCases/implicit-integer-truncation.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/ubsan_minimal/TestCases/implicit-integer-truncation.c?rev=338287&view=auto
==============================================================================
--- compiler-rt/trunk/test/ubsan_minimal/TestCases/implicit-integer-truncation.c (added)
+++ compiler-rt/trunk/test/ubsan_minimal/TestCases/implicit-integer-truncation.c Mon Jul 30 11:58:30 2018
@@ -0,0 +1,24 @@
+// RUN: %clang -fsanitize=implicit-integer-truncation %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK
+
+#include <stdint.h>
+
+int main() {
+// CHECK-NOT: integer-truncation.c
+
+  // Negative tests. Even if they produce unexpected results, this sanitizer does not care.
+  int8_t n0 = (~((uint32_t)(0))); // ~0 -> -1, but do not warn.
+  uint8_t n2 = 128;
+  uint8_t n3 = 255;
+  // Bools do not count
+  _Bool b0 = (~((uint32_t)(0)));
+  _Bool b1 = 255;
+
+  // Explicit and-ing of bits will silence it.
+  uint8_t nc0 = ((~((uint32_t)(0))) & 255);
+
+  // Positive tests.
+  uint8_t t0 = (~((uint32_t)(0)));
+// CHECK: implicit-conversion
+
+  return 0;
+}




More information about the llvm-commits mailing list