}
else if (TREE_CODE (*tp) == ARRAY_REF)
ubsan_maybe_instrument_array_ref (tp, false);
+ else if (TREE_CODE (*tp) == MODIFY_EXPR)
+ {
+ /* Since r7-1900, we gimplify RHS before LHS. Consider
+ a[b] |= c;
+ wherein we can have a single shared tree a[b] in both LHS and RHS.
+ If we only instrument the LHS and the access is invalid, the program
+ could crash before emitting a UBSan error. So instrument the RHS
+ first. */
+ *walk_subtrees = 0;
+ walk_tree (&TREE_OPERAND (*tp, 1), ubsan_walk_array_refs_r, pset, pset);
+ walk_tree (&TREE_OPERAND (*tp, 0), ubsan_walk_array_refs_r, pset, pset);
+ }
return NULL_TREE;
}
--- /dev/null
+/* PR sanitizer/108060 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds" } */
+/* { dg-skip-if "" { *-*-* } "-flto" } */
+/* { dg-shouldfail "ubsan" } */
+
+int a[8];
+int c;
+
+int
+main ()
+{
+ int b = -32768;
+ a[b] |= c;
+}
+
+/* { dg-output "index -32768 out of bounds for type 'int \\\[8\\\]'" } */
--- /dev/null
+/* PR sanitizer/108060 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds" } */
+/* { dg-skip-if "" { *-*-* } "-flto" } */
+/* { dg-shouldfail "ubsan" } */
+
+int a[8];
+int c;
+
+int
+main ()
+{
+ int b = -32768;
+ a[b] = a[b] | c;
+}
+
+/* { dg-output "index -32768 out of bounds for type 'int \\\[8\\\]'" } */
--- /dev/null
+/* PR sanitizer/108060 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds" } */
+/* { dg-skip-if "" { *-*-* } "-flto" } */
+/* { dg-shouldfail "ubsan" } */
+
+int a[8];
+int a2[18];
+int c;
+
+int
+main ()
+{
+ int b = 0;
+ a[0] = (a2[b], b = -32768, a[0] | c);
+ b = 0;
+ a[b] = (a[b], b = -32768, a[0] | c);
+}
+
+/* { dg-output "index -32768 out of bounds for type 'int \\\[8\\\]'" } */
--- /dev/null
+/* PR sanitizer/109050 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds -fno-sanitize-recover=all" } */
+/* { dg-shouldfail "ubsan" } */
+
+long a;
+int b;
+int
+main ()
+{
+ int c[4] = {0, 1, 2, 3};
+ a = 0;
+ c[a - 9806816] |= b;
+}
+
+/* { dg-output "index -9806816 out of bounds for type 'int \\\[4\\\]'" } */
--- /dev/null
+/* PR sanitizer/109050 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds -fno-sanitize-recover=all" } */
+
+int i;
+int foo (void) { return ++i; }
+
+int
+main ()
+{
+ char a[10] = { };
+ a[foo ()] = a[foo()] | 'a';
+ if (i != 2)
+ __builtin_abort ();
+ a[foo()] |= 'a';
+ if (i != 3)
+ __builtin_abort ();
+}