Hi all, attached patch fixes an out of bounds access in the clean up code of a concatenating array constructor. A fragment like
list = [ list, something() ] lead to clean up using an offset (of the list array) that was manipulated in the loop copying the existing array elements and at the end pointing to one element past the list (after the concatenation). This fixes a 15-regression. Releases prior to 15 do not have the out of bounds access in the (non existing) clean up code. The have a memory leak instead. Regtested ok on x86_64-pc-linux-gnu / F41. Ok for mainline? The subject says, that there will be 3 patches. Only this one fixes the bug. The other fixes I found while hunting this issue and because they play in the general same area, I don't want to loose them. I therefore publish them in this context. Regards, Andre -- Andre Vehreschild * Email: vehre ad gmx dot de
From 548bcaeff9b8c8d6bb670574883f7b02878e3221 Mon Sep 17 00:00:00 2001 From: Andre Vehreschild <ve...@gcc.gnu.org> Date: Wed, 25 Jun 2025 09:12:35 +0200 Subject: [PATCH 1/3] Fortran: Fix out of bounds access in structure constructor's clean up [PR120711] A structure constructor's generated clean up code was using an offset variable, which was manipulated before the clean up was run leading to an out of bounds access. PR fortran/120711 gcc/fortran/ChangeLog: * trans-array.cc (gfc_trans_array_ctor_element): Store the value of the offset for reuse. gcc/testsuite/ChangeLog: * gfortran.dg/asan/array_constructor_1.f90: New test. --- gcc/fortran/trans-array.cc | 10 ++++---- .../gfortran.dg/asan/array_constructor_1.f90 | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/asan/array_constructor_1.f90 diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 3d274439895..7be2d7b11a6 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -1991,14 +1991,17 @@ static void gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc, tree offset, gfc_se * se, gfc_expr * expr) { - tree tmp; + tree tmp, offset_eval; gfc_conv_expr (se, expr); /* Store the value. */ tmp = build_fold_indirect_ref_loc (input_location, gfc_conv_descriptor_data_get (desc)); - tmp = gfc_build_array_ref (tmp, offset, NULL); + /* The offset may change, so get its value now and use that to free memory. + */ + offset_eval = gfc_evaluate_now (offset, &se->pre); + tmp = gfc_build_array_ref (tmp, offset_eval, NULL); if (expr->expr_type == EXPR_FUNCTION && expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp) @@ -3150,8 +3153,7 @@ finish: the reference. */ if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS) && finalblock.head != NULL_TREE) - gfc_add_block_to_block (&loop->post, &finalblock); - + gfc_prepend_expr_to_block (&loop->post, finalblock.head); } diff --git a/gcc/testsuite/gfortran.dg/asan/array_constructor_1.f90 b/gcc/testsuite/gfortran.dg/asan/array_constructor_1.f90 new file mode 100644 index 00000000000..45eafacd5a6 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/asan/array_constructor_1.f90 @@ -0,0 +1,23 @@ +!{ dg-do run } + +! Contributed by Christopher Albert <alb...@tugraz.at> + +program grow_type_array + type :: container + integer, allocatable :: arr(:) + end type container + + type(container), allocatable :: list(:) + + list = [list, new_elem(5)] + + deallocate(list) + +contains + + type(container) function new_elem(s) result(out) + integer :: s + allocate(out%arr(s)) + end function new_elem + +end program grow_type_array -- 2.49.0