From: Jakub Jelinek Date: Tue, 13 May 2025 12:19:25 +0000 (+0200) Subject: libfortran: Fix up _gfortran_s{max,min}loc1_{4,8,16}_s{1,4} [PR120191] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=781cfc454b8dc24952fe7f4c5c409296dca505e1;p=thirdparty%2Fgcc.git libfortran: Fix up _gfortran_s{max,min}loc1_{4,8,16}_s{1,4} [PR120191] There is a bug in _gfortran_s{max,min}loc1_{4,8,16}_s{1,4} which the following testcase shows. The functions return but then crash in the caller. Seems that is because buffer overflows, I believe those functions for if (mask == NULL || *mask) condition being false are supposed to fill in the result array with all zeros (or allocate it and fill it with zeros). My understanding is the result array in that case is integer(kind={4,8,16}) and should have the extents the character input array has. The problem is that it uses * string_len in the extent multiplication: extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len; and extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len; which is I guess fine and desirable for the extents of the character array, but not for the extents of the destination array. Yet the code uses that extent array for that purpose (and no other purposes). Here it uses it to set the dimensions for the case where it needs to allocate (as well as size): for (n = 0; n < rank; n++) { if (n == 0) str = 1; else str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1]; GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str); } Here it uses it for bounds checking of the destination: if (unlikely (compile_options.bounds_check)) { for (n=0; n < rank; n++) { index_type ret_extent; ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n); if (extent[n] != ret_extent) runtime_error ("Incorrect extent in return value of" " MAXLOC intrinsic in dimension %ld:" " is %ld, should be %ld", (long int) n + 1, (long int) ret_extent, (long int) extent[n]); } } and here to find out how many retarray elements to actually fill in each dimension: while(1) { *dest = 0; count[0]++; dest += dstride[0]; n = 0; while (count[n] == extent[n]) { /* When we get to the end of a dimension, reset it and increment the next dimension. */ count[n] = 0; /* We could precalculate these products, but this is a less frequently used path so probably not worth it. */ dest -= dstride[n] * extent[n]; Seems maxloc1s.m4 and minloc1s.m4 are the only users of ifunction-s.m4, so we can change SCALAR_ARRAY_FUNCTION in there without breaking anything else. 2025-05-13 Jakub Jelinek PR fortran/120191 * m4/ifunction-s.m4 (SCALAR_ARRAY_FUNCTION): Don't multiply GFC_DESCRIPTOR_EXTENT(array,) by string_len. * generated/maxloc1_4_s1.c: Regenerate. * generated/maxloc1_4_s4.c: Regenerate. * generated/maxloc1_8_s1.c: Regenerate. * generated/maxloc1_8_s4.c: Regenerate. * generated/maxloc1_16_s1.c: Regenerate. * generated/maxloc1_16_s4.c: Regenerate. * generated/minloc1_4_s1.c: Regenerate. * generated/minloc1_4_s4.c: Regenerate. * generated/minloc1_8_s1.c: Regenerate. * generated/minloc1_8_s4.c: Regenerate. * generated/minloc1_16_s1.c: Regenerate. * generated/minloc1_16_s4.c: Regenerate. * gfortran.dg/pr120191_3.f90: New test. --- diff --git a/gcc/testsuite/gfortran.dg/pr120191_3.f90 b/gcc/testsuite/gfortran.dg/pr120191_3.f90 new file mode 100644 index 00000000000..26e4095d9b1 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr120191_3.f90 @@ -0,0 +1,23 @@ +! PR fortran/120191 +! { dg-do run } + + character(kind=1, len=2) :: a(4, 4, 4), b(4) + logical :: l(4, 4, 4), m, n(4) + a = 'aa' + b = 'aa' + l = .false. + m = .false. + n = .false. + if (any (maxloc (a, dim=1, mask=m, kind=4, back=.false.) .ne. 0)) stop 1 + if (any (maxloc (a, 1, m, 4, .false.) .ne. 0)) stop 2 + if (any (maxloc (a, dim=1, mask=l, kind=4, back=.true.) .ne. 0)) stop 3 + if (any (maxloc (a, 1, l, 4, .true.) .ne. 0)) stop 4 + if (any (maxloc (a, dim=1, mask=m, kind=4, back=.true.) .ne. 0)) stop 5 + if (any (maxloc (a, 1, m, 4, .true.) .ne. 0)) stop 6 + if (any (minloc (a, dim=1, mask=m, kind=4, back=.false.) .ne. 0)) stop 7 + if (any (minloc (a, 1, m, 4, .false.) .ne. 0)) stop 8 + if (any (minloc (a, dim=1, mask=l, kind=4, back=.true.) .ne. 0)) stop 9 + if (any (minloc (a, 1, l, 4, .true.) .ne. 0)) stop 10 + if (any (minloc (a, dim=1, mask=m, kind=4, back=.true.) .ne. 0)) stop 11 + if (any (minloc (a, 1, m, 4, .true.) .ne. 0)) stop 12 +end diff --git a/libgfortran/generated/maxloc1_16_s1.c b/libgfortran/generated/maxloc1_16_s1.c index cbab817ca3b..21ea81a1aac 100644 --- a/libgfortran/generated/maxloc1_16_s1.c +++ b/libgfortran/generated/maxloc1_16_s1.c @@ -457,7 +457,7 @@ smaxloc1_16_s1 (gfc_array_i16 * const restrict retarray, for (n = 0; n < dim; n++) { - extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); if (extent[n] <= 0) extent[n] = 0; @@ -465,8 +465,7 @@ smaxloc1_16_s1 (gfc_array_i16 * const restrict retarray, for (n = dim; n < rank; n++) { - extent[n] = - GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1); if (extent[n] <= 0) extent[n] = 0; diff --git a/libgfortran/generated/maxloc1_16_s4.c b/libgfortran/generated/maxloc1_16_s4.c index d7d8893f801..47e14c148bd 100644 --- a/libgfortran/generated/maxloc1_16_s4.c +++ b/libgfortran/generated/maxloc1_16_s4.c @@ -457,7 +457,7 @@ smaxloc1_16_s4 (gfc_array_i16 * const restrict retarray, for (n = 0; n < dim; n++) { - extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); if (extent[n] <= 0) extent[n] = 0; @@ -465,8 +465,7 @@ smaxloc1_16_s4 (gfc_array_i16 * const restrict retarray, for (n = dim; n < rank; n++) { - extent[n] = - GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1); if (extent[n] <= 0) extent[n] = 0; diff --git a/libgfortran/generated/maxloc1_4_s1.c b/libgfortran/generated/maxloc1_4_s1.c index 51740eefe55..66ee8d0f1db 100644 --- a/libgfortran/generated/maxloc1_4_s1.c +++ b/libgfortran/generated/maxloc1_4_s1.c @@ -457,7 +457,7 @@ smaxloc1_4_s1 (gfc_array_i4 * const restrict retarray, for (n = 0; n < dim; n++) { - extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); if (extent[n] <= 0) extent[n] = 0; @@ -465,8 +465,7 @@ smaxloc1_4_s1 (gfc_array_i4 * const restrict retarray, for (n = dim; n < rank; n++) { - extent[n] = - GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1); if (extent[n] <= 0) extent[n] = 0; diff --git a/libgfortran/generated/maxloc1_4_s4.c b/libgfortran/generated/maxloc1_4_s4.c index cf04d6dbcaa..7d889c00596 100644 --- a/libgfortran/generated/maxloc1_4_s4.c +++ b/libgfortran/generated/maxloc1_4_s4.c @@ -457,7 +457,7 @@ smaxloc1_4_s4 (gfc_array_i4 * const restrict retarray, for (n = 0; n < dim; n++) { - extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); if (extent[n] <= 0) extent[n] = 0; @@ -465,8 +465,7 @@ smaxloc1_4_s4 (gfc_array_i4 * const restrict retarray, for (n = dim; n < rank; n++) { - extent[n] = - GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1); if (extent[n] <= 0) extent[n] = 0; diff --git a/libgfortran/generated/maxloc1_8_s1.c b/libgfortran/generated/maxloc1_8_s1.c index a35e55223be..d4711e2e474 100644 --- a/libgfortran/generated/maxloc1_8_s1.c +++ b/libgfortran/generated/maxloc1_8_s1.c @@ -457,7 +457,7 @@ smaxloc1_8_s1 (gfc_array_i8 * const restrict retarray, for (n = 0; n < dim; n++) { - extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); if (extent[n] <= 0) extent[n] = 0; @@ -465,8 +465,7 @@ smaxloc1_8_s1 (gfc_array_i8 * const restrict retarray, for (n = dim; n < rank; n++) { - extent[n] = - GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1); if (extent[n] <= 0) extent[n] = 0; diff --git a/libgfortran/generated/maxloc1_8_s4.c b/libgfortran/generated/maxloc1_8_s4.c index e264779dc54..dea360e35ad 100644 --- a/libgfortran/generated/maxloc1_8_s4.c +++ b/libgfortran/generated/maxloc1_8_s4.c @@ -457,7 +457,7 @@ smaxloc1_8_s4 (gfc_array_i8 * const restrict retarray, for (n = 0; n < dim; n++) { - extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); if (extent[n] <= 0) extent[n] = 0; @@ -465,8 +465,7 @@ smaxloc1_8_s4 (gfc_array_i8 * const restrict retarray, for (n = dim; n < rank; n++) { - extent[n] = - GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1); if (extent[n] <= 0) extent[n] = 0; diff --git a/libgfortran/generated/minloc1_16_s1.c b/libgfortran/generated/minloc1_16_s1.c index 82280092024..b654608a8d9 100644 --- a/libgfortran/generated/minloc1_16_s1.c +++ b/libgfortran/generated/minloc1_16_s1.c @@ -457,7 +457,7 @@ sminloc1_16_s1 (gfc_array_i16 * const restrict retarray, for (n = 0; n < dim; n++) { - extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); if (extent[n] <= 0) extent[n] = 0; @@ -465,8 +465,7 @@ sminloc1_16_s1 (gfc_array_i16 * const restrict retarray, for (n = dim; n < rank; n++) { - extent[n] = - GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1); if (extent[n] <= 0) extent[n] = 0; diff --git a/libgfortran/generated/minloc1_16_s4.c b/libgfortran/generated/minloc1_16_s4.c index e40bf54ceec..2e709a7c105 100644 --- a/libgfortran/generated/minloc1_16_s4.c +++ b/libgfortran/generated/minloc1_16_s4.c @@ -457,7 +457,7 @@ sminloc1_16_s4 (gfc_array_i16 * const restrict retarray, for (n = 0; n < dim; n++) { - extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); if (extent[n] <= 0) extent[n] = 0; @@ -465,8 +465,7 @@ sminloc1_16_s4 (gfc_array_i16 * const restrict retarray, for (n = dim; n < rank; n++) { - extent[n] = - GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1); if (extent[n] <= 0) extent[n] = 0; diff --git a/libgfortran/generated/minloc1_4_s1.c b/libgfortran/generated/minloc1_4_s1.c index 199d254d6e5..61dad5530ee 100644 --- a/libgfortran/generated/minloc1_4_s1.c +++ b/libgfortran/generated/minloc1_4_s1.c @@ -457,7 +457,7 @@ sminloc1_4_s1 (gfc_array_i4 * const restrict retarray, for (n = 0; n < dim; n++) { - extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); if (extent[n] <= 0) extent[n] = 0; @@ -465,8 +465,7 @@ sminloc1_4_s1 (gfc_array_i4 * const restrict retarray, for (n = dim; n < rank; n++) { - extent[n] = - GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1); if (extent[n] <= 0) extent[n] = 0; diff --git a/libgfortran/generated/minloc1_4_s4.c b/libgfortran/generated/minloc1_4_s4.c index 1f0174b0e55..49c25d06363 100644 --- a/libgfortran/generated/minloc1_4_s4.c +++ b/libgfortran/generated/minloc1_4_s4.c @@ -457,7 +457,7 @@ sminloc1_4_s4 (gfc_array_i4 * const restrict retarray, for (n = 0; n < dim; n++) { - extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); if (extent[n] <= 0) extent[n] = 0; @@ -465,8 +465,7 @@ sminloc1_4_s4 (gfc_array_i4 * const restrict retarray, for (n = dim; n < rank; n++) { - extent[n] = - GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1); if (extent[n] <= 0) extent[n] = 0; diff --git a/libgfortran/generated/minloc1_8_s1.c b/libgfortran/generated/minloc1_8_s1.c index 39bdb9b7c88..c0ac6e6ba7a 100644 --- a/libgfortran/generated/minloc1_8_s1.c +++ b/libgfortran/generated/minloc1_8_s1.c @@ -457,7 +457,7 @@ sminloc1_8_s1 (gfc_array_i8 * const restrict retarray, for (n = 0; n < dim; n++) { - extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); if (extent[n] <= 0) extent[n] = 0; @@ -465,8 +465,7 @@ sminloc1_8_s1 (gfc_array_i8 * const restrict retarray, for (n = dim; n < rank; n++) { - extent[n] = - GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1); if (extent[n] <= 0) extent[n] = 0; diff --git a/libgfortran/generated/minloc1_8_s4.c b/libgfortran/generated/minloc1_8_s4.c index ed74ac9c49d..29624d0f41f 100644 --- a/libgfortran/generated/minloc1_8_s4.c +++ b/libgfortran/generated/minloc1_8_s4.c @@ -457,7 +457,7 @@ sminloc1_8_s4 (gfc_array_i8 * const restrict retarray, for (n = 0; n < dim; n++) { - extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); if (extent[n] <= 0) extent[n] = 0; @@ -465,8 +465,7 @@ sminloc1_8_s4 (gfc_array_i8 * const restrict retarray, for (n = dim; n < rank; n++) { - extent[n] = - GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1); if (extent[n] <= 0) extent[n] = 0; diff --git a/libgfortran/m4/ifunction-s.m4 b/libgfortran/m4/ifunction-s.m4 index 8275f6568c4..22182e9de27 100644 --- a/libgfortran/m4/ifunction-s.m4 +++ b/libgfortran/m4/ifunction-s.m4 @@ -421,7 +421,7 @@ s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, for (n = 0; n < dim; n++) { - extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); if (extent[n] <= 0) extent[n] = 0; @@ -429,8 +429,7 @@ s'name`'rtype_qual`_'atype_code` ('rtype` * const restrict retarray, for (n = dim; n < rank; n++) { - extent[n] = - GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len; + extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1); if (extent[n] <= 0) extent[n] = 0;