@@ -313,7 +313,7 @@ ubsan_instrument_vla (location_t loc, tree size)
tree type = TREE_TYPE (size);
tree t, tt;
- t = fold_build2 (LE_EXPR, boolean_type_node, size, build_int_cst (type, 0));
+ t = fold_build2 (LT_EXPR, boolean_type_node, size, build_int_cst (type, 0));
if (flag_sanitize_trap & SANITIZE_VLA)
tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
else
@@ -7201,16 +7201,20 @@ grokdeclarator (const struct c_declarator *declarator,
with known value. */
this_size_varies = size_varies = true;
warn_variable_length_array (name, size);
- if (sanitize_flags_p (SANITIZE_VLA)
- && current_function_decl != NULL_TREE
- && decl_context == NORMAL)
+ if (sanitize_flags_p (SANITIZE_VLA))
{
/* Evaluate the array size only once. */
size = save_expr (size);
size = c_fully_fold (size, false, NULL);
- size = fold_build2 (COMPOUND_EXPR, TREE_TYPE (size),
- ubsan_instrument_vla (loc, size),
- size);
+ tree instr = ubsan_instrument_vla (loc, size);
+ /* We have to build this in the right order, so
+ instrumentation is done before the size can
+ be used in other parameters. */
+ if (*expr)
+ *expr = build2 (COMPOUND_EXPR, TREE_TYPE (instr),
+ *expr, instr);
+ else
+ *expr = instr;
}
}
@@ -110,9 +110,7 @@ main (void)
/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -5\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -3\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value 0\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value 0\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -6\[^\n\r]*(\n|\r\n|\r)" } */
new file mode 100644
@@ -0,0 +1,16 @@
+/* PR 98608 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=vla-bound" } */
+
+void f(int n, double (*x)[n])
+{
+ typeof(*x) y;
+}
+
+int main()
+{
+ f(-1, 0);
+}
+
+/* { dg-output "variable length array bound evaluates to non-positive value -1" } */
+
new file mode 100644
@@ -0,0 +1,27 @@
+/* { dg-do run } */
+/* { dg-options "-Wstringop-overflow=0 -fsanitize=vla-bound -fsanitize-recover=vla-bound" } */
+
+void f1(int n, char buf[n]) { }
+/* { dg-output "variable length array bound evaluates to non-positive value -1\[^\n\r]*(\n|\r\n|\r)" } */
+void f2(int n, float m[n][2]) { }
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1\[^\n\r]*(\n|\r\n|\r)" } */
+void f3(int n, int m, float x[n][m]) { }
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1\[^\n\r]*(\n|\r\n|\r)" } */
+void f4(int n) { typedef char buf[n]; }
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1\[^\n\r]*(\n|\r\n|\r)" } */
+void f5(int n) { struct { char buf[n]; } x; }
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1\[^\n\r]*(\n|\r\n|\r)" } */
+void f6(int n, struct { char buf[n]; } *p) { } /* { dg-warning "anonymous" } */
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1" } */
+
+int main()
+{
+ f1(-1, 0);
+ f2(-1, 0);
+ f3(-1, 1, 0);
+ f4(-1);
+ f5(-1);
+ f6(-1, 0);
+}
+
+
new file mode 100644
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-options "-Wstringop-overflow=0 -fsanitize=vla-bound -fsanitize-recover=vla-bound" } */
+
+void f1(int n, char buf[n]) { }
+void f2(int n, float m[n][2]) { }
+void f3(int n, int m, float x[n][m]) { }
+void f4(int n) { typedef char buf[n]; }
+void f5(int n) { struct { char buf[n]; } x; }
+void f6(int n, struct { char buf[n]; } *p) { } /* { dg-warning "anonymous" } */
+
+int main()
+{
+ f1(0, 0);
+ f2(0, 0);
+ f3(0, 1, 0);
+ f4(0);
+ f5(0);
+ f6(0, 0);
+}
+
+
new file mode 100644
@@ -0,0 +1,14 @@
+/* { dg-do run }
+ * { dg-options "-fsanitize=vla-bound" } */
+
+void foo(int n, char (*buf)[n], char p[n = 1])
+{
+}
+
+int main()
+{
+ foo(-1, 0, 0);
+}
+
+/* { dg-output "variable length array bound evaluates to non-positive value -1" } */
+