]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fortran: UBSAN uninitialized stride for missing optional argument [PR122080]
authorHarald Anlauf <anlauf@gmx.de>
Tue, 30 Sep 2025 19:14:12 +0000 (21:14 +0200)
committerHarald Anlauf <anlauf@gmx.de>
Wed, 1 Oct 2025 18:20:01 +0000 (20:20 +0200)
PR fortran/122080

gcc/fortran/ChangeLog:

* trans-array.cc (gfc_conv_array_parameter): Wrap the derivation of
bounds and strides for the descriptor of an optional dummy array
argument by a test on argument presence when it is supposed to be
passed to an optional argument.

gcc/testsuite/ChangeLog:

* gfortran.dg/ubsan/missing_optional_dummy_9.f90: New test.

gcc/fortran/trans-array.cc
gcc/testsuite/gfortran.dg/ubsan/missing_optional_dummy_9.f90 [new file with mode: 0644]

index 0111c9566f41d2ff7ecade835760d465ba4af67a..db34de44401b0e1636d7eb5b1da83aa28b05b892 100644 (file)
@@ -9446,6 +9446,15 @@ gfc_conv_array_parameter (gfc_se *se, gfc_expr *expr, bool g77,
 
          gfc_add_expr_to_block (&se->pre, tmp);
        }
+      else if (pass_optional && full_array_var && sym->as && sym->as->rank != 0)
+       {
+         /* Perform calculation of bounds and strides of optional array dummy
+            only if the argument is present.  */
+         tmp = build3_v (COND_EXPR, gfc_conv_expr_present (sym),
+                         gfc_finish_block (&se->pre),
+                         build_empty_stmt (input_location));
+         gfc_add_expr_to_block (&se->pre, tmp);
+       }
     }
 
   /* Deallocate the allocatable components of structures that are
diff --git a/gcc/testsuite/gfortran.dg/ubsan/missing_optional_dummy_9.f90 b/gcc/testsuite/gfortran.dg/ubsan/missing_optional_dummy_9.f90
new file mode 100644 (file)
index 0000000..06b0004
--- /dev/null
@@ -0,0 +1,22 @@
+! { dg-do compile }
+! { dg-options "-O2 -fdump-tree-original -fdump-tree-optimized -fsanitize=undefined" }
+!
+! PR fortran/122080 - UBSAN: uninitialized stride for missing actual argument
+!
+! Contributed by Henri Menke
+
+subroutine outer (optarr)
+  real, optional, intent(in) :: optarr(:,:)
+  interface
+     subroutine inner (optarr)
+       real, optional, intent(in) :: optarr(:,:)
+     end subroutine inner
+  end interface
+  call inner (optarr)
+end subroutine outer
+
+! There will be 2 remaining UBSAN checks of stride wrapped by a check
+! for argument presence:
+!
+! { dg-final { scan-tree-dump-times "if \\(optarr.0 != 0B\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "UBSAN_CHECK_SUB (.)* stride" 2 "optimized" } }