]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ranger: Verify gimple_call_num_args for several builtins [PR123431]
authorJakub Jelinek <jakub@redhat.com>
Sat, 10 Jan 2026 10:35:30 +0000 (11:35 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sat, 10 Jan 2026 10:35:30 +0000 (11:35 +0100)
While gimple_call_combined_fn already do call
gimple_builtin_call_types_compatible_p and for most of builtins ensures
the right types of arguments, for type generic builtins it does not,
from POV of that function those functions are rettype (...).
Now, while the FE does some number of argument checking for the type
generic builtins, as the testcase below shows, it can be gamed.

So, this patch checks the number of arguments for type generic builtins
and does nothing if they have unexpected number of arguments.
Also for the returns arg verifies it can access the first argument.

2026-01-10  Jakub Jelinek  <jakub@redhat.com>

PR tree-optimization/123431
* gimple-range-op.cc (gimple_range_op_handler::maybe_builtin_call):
Punt if type-generic builtins with a single argument don't have
exactly one argument.  For returns_arg punt if call doesn't have
at least one argument.

* gcc.dg/pr123431.c: New test.

gcc/gimple-range-op.cc
gcc/testsuite/gcc.dg/pr123431.c [new file with mode: 0644]

index 4774dfca47b5f08a733a8cdc63bf0a8172b70a47..600f47b3cbe7140fae3c2f421bb498d66f00cd96 100644 (file)
@@ -1410,6 +1410,8 @@ gimple_range_op_handler::maybe_builtin_call ()
   switch (func)
     {
     case CFN_BUILT_IN_CONSTANT_P:
+      if (gimple_call_num_args (call) != 1)
+       return;
       m_op1 = gimple_call_arg (call, 0);
       if (irange::supports_p (TREE_TYPE (m_op1)))
        m_operator = &op_cfn_constant_p;
@@ -1420,21 +1422,29 @@ gimple_range_op_handler::maybe_builtin_call ()
       break;
 
     CASE_FLT_FN (CFN_BUILT_IN_SIGNBIT):
+      if (gimple_call_num_args (call) != 1)
+       return;
       m_op1 = gimple_call_arg (call, 0);
       m_operator = &op_cfn_signbit;
       break;
 
     CASE_FLT_FN (CFN_BUILT_IN_ISINF):
+      if (gimple_call_num_args (call) != 1)
+       return;
       m_op1 = gimple_call_arg (call, 0);
       m_operator = &op_cfn_isinf;
       break;
 
     case CFN_BUILT_IN_ISFINITE:
+      if (gimple_call_num_args (call) != 1)
+       return;
       m_op1 = gimple_call_arg (call, 0);
       m_operator = &op_cfn_isfinite;
       break;
 
     case CFN_BUILT_IN_ISNORMAL:
+      if (gimple_call_num_args (call) != 1)
+       return;
       m_op1 = gimple_call_arg (call, 0);
       m_operator = &op_cfn_isnormal;
       break;
@@ -1565,7 +1575,9 @@ gimple_range_op_handler::maybe_builtin_call ()
     default:
       {
        unsigned arg;
-       if (gimple_call_fnspec (call).returns_arg (&arg) && arg == 0)
+       if (gimple_call_fnspec (call).returns_arg (&arg)
+           && arg == 0
+           && gimple_call_num_args (call) > 0)
          {
            m_op1 = gimple_call_arg (call, 0);
            m_operator = &op_cfn_pass_through_arg1;
diff --git a/gcc/testsuite/gcc.dg/pr123431.c b/gcc/testsuite/gcc.dg/pr123431.c
new file mode 100644 (file)
index 0000000..369b77e
--- /dev/null
@@ -0,0 +1,19 @@
+/* PR tree-optimization/123431 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+extern void foo (int);
+
+extern inline __attribute__((always_inline)) void
+bar (int x, ...)
+{
+  if (__builtin_constant_p (__builtin_va_arg_pack ()))
+    foo (x);
+}
+
+void
+baz (int x)
+{
+  bar (1, 2);
+  bar (3, x);
+}