aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2023-12-21 11:14:55 +0100
committerJakub Jelinek <jakub@redhat.com>2023-12-21 11:16:02 +0100
commit0e7f5039c52a020c3ed5f18a2b3ee1fb42b78f62 (patch)
treec380f7ddfba0158255f7f84b5b1eb38686ee24e1
parent3d1bdbf64c2ed5be70fbff687b2927e328297b81 (diff)
downloadgcc-0e7f5039c52a020c3ed5f18a2b3ee1fb42b78f62.zip
gcc-0e7f5039c52a020c3ed5f18a2b3ee1fb42b78f62.tar.gz
gcc-0e7f5039c52a020c3ed5f18a2b3ee1fb42b78f62.tar.bz2
ubsan: Add workaround for missing bitint libubsan support for shifts [PR113092]
libubsan still doesn't support bitints, so ubsan contains a workaround and emits value 0 and TK_Unknown kind for those. If shift second operand has the large/huge _BitInt type, this results in internal errors in libubsan though, so the following patch provides a temporary workaround for that - in the rare case where the last operand has _BitInt type wider than __int128 (or long long on 32-bit arches), it will pretend the shift count has that type saturated to its range. IMHO better than crashing in the library. If the value fits into the __int128 (or long long) range, it will be printed correctly (just print that it has __int128/long long type rather than say _BitInt(255)), if it doesn't, user will at least know that it is a very large negative or very large positive value. 2023-12-21 Jakub Jelinek <jakub@redhat.com> PR sanitizer/113092 * c-ubsan.cc (ubsan_instrument_shift): Workaround for missing ubsan _BitInt support for the shift count. * gcc.dg/ubsan/bitint-4.c: New test.
-rw-r--r--gcc/c-family/c-ubsan.cc26
-rw-r--r--gcc/testsuite/gcc.dg/ubsan/bitint-4.c22
2 files changed, 48 insertions, 0 deletions
diff --git a/gcc/c-family/c-ubsan.cc b/gcc/c-family/c-ubsan.cc
index b2c58c6..a6c88dd 100644
--- a/gcc/c-family/c-ubsan.cc
+++ b/gcc/c-family/c-ubsan.cc
@@ -256,6 +256,32 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
else
{
+ if (TREE_CODE (type1) == BITINT_TYPE
+ && TYPE_PRECISION (type1) > MAX_FIXED_MODE_SIZE)
+ {
+ /* Workaround for missing _BitInt support in libsanitizer.
+ Instead of crashing in the library, pretend values above
+ maximum value of normal integral type or below minimum value
+ of that type are those extremes. */
+ tree type2 = build_nonstandard_integer_type (MAX_FIXED_MODE_SIZE,
+ TYPE_UNSIGNED (type1));
+ tree op2 = op1;
+ if (!TYPE_UNSIGNED (type1))
+ {
+ op2 = fold_build2 (LT_EXPR, boolean_type_node, unshare_expr (op1),
+ fold_convert (type1, TYPE_MIN_VALUE (type2)));
+ op2 = fold_build3 (COND_EXPR, type2, op2, TYPE_MIN_VALUE (type2),
+ fold_convert (type2, unshare_expr (op1)));
+ }
+ else
+ op2 = fold_convert (type2, op1);
+ tree op3
+ = fold_build2 (GT_EXPR, boolean_type_node, unshare_expr (op1),
+ fold_convert (type1, TYPE_MAX_VALUE (type2)));
+ op1 = fold_build3 (COND_EXPR, type2, op3, TYPE_MAX_VALUE (type2),
+ op2);
+ type1 = type2;
+ }
tree utd0 = ubsan_type_descriptor (type0, UBSAN_PRINT_FORCE_INT);
tree data = ubsan_create_data ("__ubsan_shift_data", 1, &loc, utd0,
ubsan_type_descriptor (type1), NULL_TREE,
diff --git a/gcc/testsuite/gcc.dg/ubsan/bitint-4.c b/gcc/testsuite/gcc.dg/ubsan/bitint-4.c
new file mode 100644
index 0000000..a13f70a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ubsan/bitint-4.c
@@ -0,0 +1,22 @@
+/* PR sanitizer/113092 */
+/* { dg-do run { target bitint575 } } */
+/* { dg-options "-fsanitize=shift -fsanitize-recover=shift" } */
+
+int
+main ()
+{
+ volatile _BitInt(255) bi = 12984732985743985734598574358943wb;
+ bi = 0 >> bi;
+ bi = 329847329847239847239847329847239857489657986759867549867594875984375wb;
+ bi = 0 >> bi;
+ bi = -12984732985743985734598574358943wb;
+ bi = 0 >> bi;
+ bi = -329847329847239847239847329847239857489657986759867549867594875984375wb;
+ bi = 0 >> bi;
+ return 0;
+}
+
+/* { dg-output "shift exponent \[0-9a-fx]* is too large for \[0-9]*-bit type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*shift exponent \[0-9a-fx]* is too large for \[0-9]*-bit type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*shift exponent \[0-9a-fx-]* is negative\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*shift exponent \[0-9a-fx-]* is negative" } */