Hi!

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.

Tested on x86_64-linux and i686-linux, ok for trunk?

2025-05-12  Jakub Jelinek  <ja...@redhat.com>

        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.

--- libgfortran/m4/ifunction-s.m4.jj    2023-11-08 23:04:12.290051655 +0100
+++ libgfortran/m4/ifunction-s.m4       2025-05-12 09:43:23.347096320 +0200
@@ -421,7 +421,7 @@ s'name`'rtype_qual`_'atype_code` ('rtype
 
   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
 
   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;
--- libgfortran/generated/maxloc1_4_s1.c.jj     2025-01-02 20:54:32.772121021 
+0100
+++ libgfortran/generated/maxloc1_4_s1.c        2025-05-12 09:46:12.919771566 
+0200
@@ -457,7 +457,7 @@ smaxloc1_4_s1 (gfc_array_i4 * const rest
 
   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 rest
 
   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;
--- libgfortran/generated/maxloc1_4_s4.c.jj     2025-01-02 20:54:32.772121021 
+0100
+++ libgfortran/generated/maxloc1_4_s4.c        2025-05-12 09:44:30.763172079 
+0200
@@ -457,7 +457,7 @@ smaxloc1_4_s4 (gfc_array_i4 * const rest
 
   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 rest
 
   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;
--- libgfortran/generated/maxloc1_8_s1.c.jj     2025-01-02 20:54:32.772121021 
+0100
+++ libgfortran/generated/maxloc1_8_s1.c        2025-05-12 09:46:35.889456661 
+0200
@@ -457,7 +457,7 @@ smaxloc1_8_s1 (gfc_array_i8 * const rest
 
   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 rest
 
   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;
--- libgfortran/generated/maxloc1_8_s4.c.jj     2025-01-02 20:54:32.772121021 
+0100
+++ libgfortran/generated/maxloc1_8_s4.c        2025-05-12 09:45:02.769733285 
+0200
@@ -457,7 +457,7 @@ smaxloc1_8_s4 (gfc_array_i8 * const rest
 
   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 rest
 
   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;
--- libgfortran/generated/maxloc1_16_s1.c.jj    2025-01-02 20:54:32.771121035 
+0100
+++ libgfortran/generated/maxloc1_16_s1.c       2025-05-12 09:45:21.422477568 
+0200
@@ -457,7 +457,7 @@ smaxloc1_16_s1 (gfc_array_i16 * const re
 
   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 re
 
   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;
--- libgfortran/generated/maxloc1_16_s4.c.jj    2025-01-02 20:54:32.771121035 
+0100
+++ libgfortran/generated/maxloc1_16_s4.c       2025-05-12 09:45:31.944333322 
+0200
@@ -457,7 +457,7 @@ smaxloc1_16_s4 (gfc_array_i16 * const re
 
   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 re
 
   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;
--- libgfortran/generated/minloc1_4_s1.c.jj     2025-01-02 20:54:32.777120951 
+0100
+++ libgfortran/generated/minloc1_4_s1.c        2025-05-12 09:45:43.950168719 
+0200
@@ -457,7 +457,7 @@ sminloc1_4_s1 (gfc_array_i4 * const rest
 
   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 rest
 
   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;
--- libgfortran/generated/minloc1_4_s4.c.jj     2025-01-02 20:54:32.777120951 
+0100
+++ libgfortran/generated/minloc1_4_s4.c        2025-05-12 09:46:52.800224824 
+0200
@@ -457,7 +457,7 @@ sminloc1_4_s4 (gfc_array_i4 * const rest
 
   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 rest
 
   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;
--- libgfortran/generated/minloc1_8_s1.c.jj     2025-01-02 20:54:32.778120938 
+0100
+++ libgfortran/generated/minloc1_8_s1.c        2025-05-12 09:46:25.058605148 
+0200
@@ -457,7 +457,7 @@ sminloc1_8_s1 (gfc_array_i8 * const rest
 
   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 rest
 
   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;
--- libgfortran/generated/minloc1_8_s4.c.jj     2025-01-02 20:54:32.778120938 
+0100
+++ libgfortran/generated/minloc1_8_s4.c        2025-05-12 09:44:43.225001232 
+0200
@@ -457,7 +457,7 @@ sminloc1_8_s4 (gfc_array_i8 * const rest
 
   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 rest
 
   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;
--- libgfortran/generated/minloc1_16_s1.c.jj    2025-01-02 20:54:32.777120951 
+0100
+++ libgfortran/generated/minloc1_16_s1.c       2025-05-12 09:45:12.785595976 
+0200
@@ -457,7 +457,7 @@ sminloc1_16_s1 (gfc_array_i16 * const re
 
   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 re
 
   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;
--- libgfortran/generated/minloc1_16_s4.c.jj    2025-01-02 20:54:32.777120951 
+0100
+++ libgfortran/generated/minloc1_16_s4.c       2025-05-12 09:46:44.869333550 
+0200
@@ -457,7 +457,7 @@ sminloc1_16_s4 (gfc_array_i16 * const re
 
   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 re
 
   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;
--- gcc/testsuite/gfortran.dg/pr120191_3.f90.jj 2025-05-12 09:49:31.092054719 
+0200
+++ gcc/testsuite/gfortran.dg/pr120191_3.f90    2025-05-12 09:52:03.093970847 
+0200
@@ -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

        Jakub

Reply via email to