This fixes an out-of-array-bounds access in the case that
   nappend < ninterop

Namely, the number of interop clauses to 'dispatch' exceeds
the number of interop args accepted by the function/specified
in the append_args clause to 'declare variant'.

OpenMP does not allow this - hence, GCC diagnoses this error,
but the append code was still executed, leading to the issue.

Committed asr15-9063-gf3899e0fd3f9aa Thanks to Filip for testing with an 
ASAN-instrumentedGCC and reporting this issue! Tobias
commit f3899e0fd3f9aa6b579a21e87b50c61ea5c448df
Author: Tobias Burnus <tbur...@baylibre.com>
Date:   Mon Mar 31 11:44:26 2025 +0200

    OpenMP: modify_call_for_omp_dispatch - fix invalid memory access after 'error' [PR119541]
    
    OpenMP requires that the number of dispatch 'interop' clauses (ninterop)
    is less or equal to the number of declare variant 'append_args' interop
    objects (nappend).
    
    While 'nappend < ninterop' was diagnosed as error, the processing continues,
    which lead to an invalid out-of-bounds memory access. Solution: only
    process the first nappend 'interop' clauses.
    
    gcc/ChangeLog:
    
            PR middle-end/119541
            * gimplify.cc (modify_call_for_omp_dispatch): Limit interop claues
            processing by the number of append_args arguments.
---
 gcc/gimplify.cc | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 422ad1265a6..a8399dc8363 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -3940,47 +3940,48 @@ modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses,
       if (nappend < ninterop)
 	{
 	  error_at (OMP_CLAUSE_LOCATION (dispatch_interop),
 		    "number of list items in %<interop%> clause (%d) "
 		    "exceeds the number of %<append_args%> items (%d) for "
 		    "%<declare variant%> candidate %qD",
 		    ninterop, nappend, fndecl);
 	  inform (dispatch_append_args
 		  ? EXPR_LOCATION (TREE_PURPOSE (dispatch_append_args))
 		  : DECL_SOURCE_LOCATION (fndecl),
 		  "%<declare variant%> candidate %qD declared here",
 		  fndecl);
+	  ninterop = nappend;
 	}
     }
   if (dispatch_interop && !dispatch_device_num)
     {
       gcc_checking_assert (ninterop > 1);
       error_at (OMP_CLAUSE_LOCATION (dispatch_interop),
 		"the %<device%> clause must be present if the %<interop%> "
 		"clause has more than one list item");
     }
   else if (dispatch_append_args)
     {
       tree *buffer = XALLOCAVEC (tree, nargs + nappend);
       tree arg = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
       /* Copy the first arguments; insert then the interop objects,
 	 and then copy the rest (nargs - nfirst_args) args.  */
       int i;
       for (i = 0; i < nfirst_args; i++)
 	{
 	  arg = TREE_CHAIN (arg);
 	  buffer[i] = CALL_EXPR_ARG (expr, i);
 	}
       int j = ninterop;
-      for (tree t = dispatch_interop; t; t = TREE_CHAIN (t))
+      for (tree t = dispatch_interop; t && j > 0; t = TREE_CHAIN (t))
 	if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP)
 	  buffer[i + --j] = OMP_CLAUSE_DECL (t);
       gcc_checking_assert (j == 0);
 
       /* Do we need to create additional interop objects?  */
       if (ninterop < nappend)
 	{
 	  if (dispatch_device_num == NULL_TREE)
 	    /* Not remapping device number.  */
 	    dispatch_device_num = build_int_cst (integer_type_node,
 						 GOMP_DEVICE_DEFAULT_OMP_61);
 	  int nnew = nappend - ninterop;

Reply via email to