(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
tree-ssa/
builtin-sprintf-warn-16.c
       1  /* PR middle-end/80364 - sanitizer detects signed integer overflow
       2     in gimple-ssa-sprintf.c
       3     { dg-do compile }
       4     { dg-options "-O2 -Wall -Wformat-overflow=1 -ftrack-macro-expansion=0" }
       5     { dg-require-effective-target int32plus } */
       6  
       7  typedef __SIZE_TYPE__  size_t;
       8  typedef __WCHAR_TYPE__ wchar_t;
       9  
      10  void sink (void*);
      11  void* get_value (void);
      12  
      13  /* Return a random width as type T.  */
      14  #define W(T) *(T*)get_value ()
      15  
      16  /* Return a random precision as type T.  */
      17  #define P(T) *(T*)get_value ()
      18  
      19  /* Return a random value as type T.  */
      20  #define V(T) *(T*)get_value ()
      21  
      22  extern char buf[1];
      23  
      24  /* Test convenience macro.  */
      25  #define T(fmt, ...)					\
      26    __builtin_sprintf (buf + 1, fmt, __VA_ARGS__);	\
      27    sink (buf)
      28  
      29  typedef signed char         schar_t;
      30  typedef unsigned char       uchar_t;
      31  typedef signed short        sshort_t;
      32  typedef unsigned short      ushort_t;
      33  typedef signed int          sint_t;
      34  typedef unsigned int        uint_t;
      35  typedef signed long         slong_t;
      36  typedef unsigned long       ulong_t;
      37  typedef signed long long    sllong_t;
      38  typedef unsigned long long  ullong_t;
      39  
      40  #if __SIZEOF_INT128__
      41  typedef __int128_t          sint128_t;
      42  typedef __uint128_t         uint128_t;
      43  #else
      44  /* When __int128_t is not available, repeat the same tests with long long.
      45     This is to avoid having to guard the tests below and to avoid making
      46     the dg-warning directives conditional.  */
      47  typedef signed long long    sint128_t;
      48  typedef unsigned long long  uint128_t;
      49  #endif
      50  
      51  const sint128_t sint128_max
      52    = (sint128_t)1 << (sizeof sint128_max * __CHAR_BIT__ - 2);
      53  const sint128_t uint128_max = (uint128_t)-1;
      54  
      55  void test_width_cst (void)
      56  {
      57    T ("%*i", W (schar_t), 1);     /* { dg-warning "between 1 and 128 " } */
      58    T ("%*i", W (uchar_t), 12);    /* { dg-warning "between 2 and 255 " } */
      59  
      60    T ("%*i", W (sshort_t), 123);  /* { dg-warning "between 3 and 32768 " } */
      61    T ("%*i", W (ushort_t), 1234); /* { dg-warning "between 4 and 65535 " } */
      62  
      63    T ("%*i", W (sint_t), 12345);  /* { dg-warning "between 5 and 2147483648 " } */
      64    T ("%*i", W (uint_t), 123456); /* { dg-warning "between 6 and 2147483648 " } */
      65  
      66    /* Exercise calls with invalid arguments (to verify there is no ICE).  */
      67    T ("%*li", W (slong_t), 1234567L);  /* { dg-warning "between 7 and 2147483648 " } */
      68    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
      69    T ("%*li", W (ulong_t), 12345678L); /* { dg-warning "between 8 and 2147483648 " } */
      70    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
      71  
      72    T ("%*lli", W (sllong_t), 123456789LL);  /* { dg-warning "between 9 and 2147483648 " } */
      73    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
      74    T ("%*lli", W (ullong_t), 1234567890LL); /* { dg-warning "between 10 and 2147483648 " } */
      75    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
      76  
      77    T ("%*i", W (sint128_t), 0);  /* { dg-warning "between 1 and 2147483648 " } */
      78    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
      79    T ("%*i", W (uint128_t), 1); /* { dg-warning "between 1 and 2147483648 " } */
      80    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
      81  
      82    {
      83      extern sint128_t si128;
      84      if (si128 < sint128_max / 2 || sint128_max - 8 < si128)
      85        si128 = sint128_max / 2;
      86  
      87      T ("%*i", si128, 0);  /* { dg-warning "between 1 and 2147483648 " } */
      88      /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
      89  
      90      extern uint128_t ui128;
      91      if (ui128 < uint128_max / 2 || uint128_max - 8 < ui128)
      92        ui128 = uint128_max / 2;
      93  
      94      T ("%*i", ui128, 0);  /* { dg-warning "between 1 and 2147483648 " } */
      95      /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
      96    }
      97  
      98    T ("%*i", W (float), 2);  /* { dg-warning "between 1 and 2147483648 " } */
      99    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     100    T ("%*i", W (double), 3); /* { dg-warning "between 1 and 2147483648 " } */
     101    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     102  }
     103  
     104  void test_width_var (void)
     105  {
     106    T ("%*i", W (schar_t), V (schar_t));     /* { dg-warning "between 1 and 128 " } */
     107    T ("%*i", W (uchar_t), V (uchar_t));    /* { dg-warning "between 1 and 255 " } */
     108  
     109    T ("%*i", W (sshort_t), V (sshort_t));  /* { dg-warning "between 1 and 32768 " } */
     110    T ("%*i", W (ushort_t), V (ushort_t)); /* { dg-warning "between 1 and 65535 " } */
     111  
     112    T ("%*i", W (sint_t), V (sint_t));  /* { dg-warning "between 1 and 2147483648 " } */
     113    T ("%*i", W (uint_t), V (uint_t)); /* { dg-warning "between 1 and 2147483648 " } */
     114  
     115    /* Exercise calls with invalid arguments (to verify there is no ICE).  */
     116    T ("%*li", W (slong_t), V (slong_t));  /* { dg-warning "between 1 and 2147483648 " } */
     117    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     118    T ("%*li", W (ulong_t), V (ulong_t)); /* { dg-warning "between 1 and 2147483648 " } */
     119    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     120  
     121    T ("%*lli", W (sllong_t), V (sllong_t));  /* { dg-warning "between 1 and 2147483648 " } */
     122    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     123    T ("%*lli", W (ullong_t), V (ullong_t)); /* { dg-warning "between 1 and 2147483648 " } */
     124    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     125  
     126    T ("%*i", W (float), V (int));  /* { dg-warning "between 1 and 2147483648 " } */
     127    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     128    T ("%*i", W (double), V (int)); /* { dg-warning "between 1 and 2147483648 " } */
     129    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     130  
     131    {
     132      /* Create an unsigned range with a lower bound greater than 1 and
     133         an upper bound in excess of INT_MAX and verify that after conversion
     134         to signed int the lower bound isn't used as the minimum output (since
     135         the excessive upper bound wraps around zero).  Passing the precision
     136         as unsigned, without the cast to signed int, is undedined.
     137         It's possible to constrain the upper bound on the output more, based
     138         on the upper bound of the width here, but not worth the trouble.  */
     139      unsigned w = W (unsigned);
     140      if (w < 5 || (unsigned)-1 - 7 < w)
     141        w = 5;
     142      int val = V (int);
     143  
     144      T ("%*u", (int)w, val);   /* { dg-warning "between 1 and 2147483648 " } */
     145    }
     146  
     147    {
     148      /* Verify that enums are correctly handled (i.e., that the warning
     149         doesn't just test for TREE_CODE(type) == INTEGER_TYPE but instead
     150         uses INTEGRAL_TYPE_P() or some equivalent.  */
     151      enum WidthEnum { e7 = 7, e9 = 9 };
     152      enum WidthEnum w = V (enum WidthEnum);
     153      if (w < e7 || e9 < w)
     154        w = e7;
     155  
     156      T ("%*hu", w, V (int));   /* { dg-warning "between 7 and 9 " } */
     157    }
     158  }
     159  
     160  void test_precision_cst (void)
     161  {
     162    T ("%.*i", P (schar_t), 1);     /* { dg-warning "between 1 and 127 " } */
     163    T ("%.*i", P (uchar_t), 12);    /* { dg-warning "between 2 and 255 " } */
     164  
     165    T ("%.*i", P (sshort_t), 123);  /* { dg-warning "between 3 and 32767 " } */
     166    T ("%.*i", P (ushort_t), 1234); /* { dg-warning "between 4 and 65535 " } */
     167  
     168    T ("%.*i", P (sint_t), 12345);  /* { dg-warning "between 5 and 2147483647 " } */
     169    T ("%.*i", P (uint_t), 123456); /* { dg-warning "between 6 and 2147483647 " } */
     170  
     171    /* Exercise calls with invalid arguments (to verify there is no ICE).  */
     172    T ("%.*li", P (slong_t), 1234567L);  /* { dg-warning "between 7 and 2147483647 " } */
     173    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     174    T ("%.*li", P (ulong_t), 12345678L); /* { dg-warning "between 8 and 2147483647 " } */
     175    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     176  
     177    T ("%.*lli", P (sllong_t), 123456789LL);  /* { dg-warning "between 9 and 2147483647 " } */
     178    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     179    T ("%.*lli", P (ullong_t), 1234567890LL); /* { dg-warning "between 10 and 2147483647 " } */
     180    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     181  
     182    T ("%.*i", P (sint128_t), 0);  /* { dg-warning "up to 2147483647 " } */
     183    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     184    T ("%.*i", P (uint128_t), 1); /* { dg-warning "between 1 and 2147483647 " } */
     185    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     186  
     187    {
     188      extern sint128_t si128;
     189      if (si128 < sint128_max / 2 || sint128_max - 8 < si128)
     190        si128 = sint128_max / 2;
     191  
     192      T ("%.*i", si128, 0);  /* { dg-warning "up to 2147483647 " } */
     193      /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     194  
     195      extern uint128_t ui128;
     196      if (ui128 < uint128_max / 2 || uint128_max - 8 < ui128)
     197        ui128 = uint128_max / 2;
     198  
     199      T ("%.*i", ui128, 0);  /* { dg-warning "up to 2147483647 " } */
     200      /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     201    }
     202  
     203    T ("%.*i", P (float), 0);  /* { dg-warning "up to 2147483647 " } */
     204    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     205    T ("%.*i", P (double), 1); /* { dg-warning "between 1 and 2147483647 " } */
     206    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     207  }
     208  
     209  void test_precision_var (void)
     210  {
     211    T ("%.*i", P (schar_t), V (schar_t));     /* { dg-warning "up to 128 " } */
     212    T ("%.*i", P (uchar_t), V (uchar_t));    /* { dg-warning "up to 255 " } */
     213  
     214    T ("%.*i", P (sshort_t), V (sshort_t));  /* { dg-warning "up to 32768 " } */
     215    T ("%.*i", P (ushort_t), V (ushort_t)); /* { dg-warning "up to 65535 " } */
     216  
     217    T ("%.*i", P (sint_t), V (sint_t));  /* { dg-warning "up to 2147483648 " } */
     218    T ("%.*i", P (uint_t), V (uint_t)); /* { dg-warning "up to 2147483648 " } */
     219  
     220    /* Exercise calls with invalid arguments (to verify there is no ICE).  */
     221    T ("%.*li", P (slong_t), V (slong_t));  /* { dg-warning "up to 2147483648 " } */
     222    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     223    T ("%.*li", P (ulong_t), V (ulong_t)); /* { dg-warning "up to 2147483648 " } */
     224    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     225  
     226    T ("%.*lli", P (sllong_t), V (sllong_t));  /* { dg-warning "up to 2147483648" } */
     227    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     228    T ("%.*lli", P (ullong_t), V (ullong_t)); /* { dg-warning "up to 2147483648" } */
     229    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     230  
     231    T ("%.*i", P (float), V (int));  /* { dg-warning "up to 2147483648 " } */
     232    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     233    T ("%.*i", P (double), V (int)); /* { dg-warning "up to 2147483648 " } */
     234    /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
     235  
     236    {
     237      /* Similar to the corresponding width case, create an unsigned range
     238         with a lower bound greater than 1 and an upper bound in excess of
     239         INT_MAX and verify that after conversion to int the lower bound isn't
     240         used as the minimum output (since the excessive upper bound wraps
     241         around zero).  Passing the precision as unsigned, without a cast to
     242         signed int, is undefined.  */
     243      unsigned p = V (unsigned);
     244      if (p < 7 || (unsigned)-1 - 9 < p)
     245        p = 7;
     246  
     247      int val = V (int);
     248  
     249      T ("%.*u", (int)p, val);   /* { dg-warning "up to 2147483647 " } */
     250    }
     251  
     252    {
     253      /* Verify that enums are correctly handled.  */
     254      enum PrecEnum { e9 = 9, e17 = 17 };
     255      enum PrecEnum p = V (enum PrecEnum);
     256      if (p < e9 || e17 < p)
     257        p = e9;
     258  
     259      T ("%.*u", p, V (int));   /* { dg-warning "between 9 and 17 " } */
     260    }
     261  }