From b12d5a6ba64f09b9bbe57e6f49665df9b8b6fab0 Mon Sep 17 00:00:00 2001 From: Harald Anlauf Date: Tue, 30 Sep 2025 21:14:12 +0200 Subject: [PATCH] Fortran: UBSAN uninitialized stride for missing optional argument [PR122080] 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 | 9 ++++++++ .../ubsan/missing_optional_dummy_9.f90 | 22 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 gcc/testsuite/gfortran.dg/ubsan/missing_optional_dummy_9.f90 diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 0111c9566f41..db34de44401b 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -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 index 000000000000..06b0004d5738 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/ubsan/missing_optional_dummy_9.f90 @@ -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" } } -- 2.47.3