(root)/
glibc-2.38/
stdio-common/
tst-printf.c
       1  /* Copyright (C) 1991-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #ifdef	BSD
      19  #include </usr/include/stdio.h>
      20  #define EXIT_SUCCESS 0
      21  #else
      22  #include <limits.h>
      23  #include <stdio.h>
      24  #include <stdlib.h>
      25  #include <string.h>
      26  #endif
      27  
      28  #include <float.h>
      29  #include <libc-diag.h>
      30  
      31  /* This whole file is picayune tests of corner cases of printf format strings.
      32     The compiler warnings are not useful here.  */
      33  DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wformat");
      34  
      35  #if __GNUC_PREREQ (7, 0)
      36  /* Compiler warnings about snprintf output truncation should also be
      37     ignored.  */
      38  DIAG_IGNORE_NEEDS_COMMENT (7.0, "-Wformat-truncation");
      39  #endif
      40  
      41  static void rfg1 (void);
      42  static void rfg2 (void);
      43  static void rfg3 (void);
      44  
      45  
      46  static void
      47  fmtchk (const char *fmt)
      48  {
      49    (void) fputs(fmt, stdout);
      50    (void) printf(":\t`");
      51    (void) printf(fmt, 0x12);
      52    (void) printf("'\n");
      53  }
      54  
      55  static void
      56  fmtst1chk (const char *fmt)
      57  {
      58    (void) fputs(fmt, stdout);
      59    (void) printf(":\t`");
      60    (void) printf(fmt, 4, 0x12);
      61    (void) printf("'\n");
      62  }
      63  
      64  static void
      65  fmtst2chk (const char *fmt)
      66  {
      67    (void) fputs(fmt, stdout);
      68    (void) printf(":\t`");
      69    (void) printf(fmt, 4, 4, 0x12);
      70    (void) printf("'\n");
      71  }
      72  
      73  static int
      74  do_test (void)
      75  {
      76    static char shortstr[] = "Hi, Z.";
      77    static char longstr[] = "Good morning, Doctor Chandra.  This is Hal.  \
      78  I am ready for my first lesson today.";
      79    int result = 0;
      80  
      81    fmtchk("%.4x");
      82    fmtchk("%04x");
      83    fmtchk("%4.4x");
      84    fmtchk("%04.4x");
      85    fmtchk("%4.3x");
      86    fmtchk("%04.3x");
      87  
      88    fmtst1chk("%.*x");
      89    fmtst1chk("%0*x");
      90    fmtst2chk("%*.*x");
      91    fmtst2chk("%0*.*x");
      92  
      93  #ifndef	BSD
      94    printf("bad format:\t\"%v\"\n");
      95    printf("nil pointer (padded):\t\"%10p\"\n", (void *) NULL);
      96  #endif
      97  
      98    printf("decimal negative:\t\"%d\"\n", -2345);
      99    printf("octal negative:\t\"%o\"\n", -2345);
     100    printf("hex negative:\t\"%x\"\n", -2345);
     101    printf("long decimal number:\t\"%ld\"\n", -123456L);
     102    printf("long octal negative:\t\"%lo\"\n", -2345L);
     103    printf("long unsigned decimal number:\t\"%lu\"\n", -123456L);
     104    printf("zero-padded LDN:\t\"%010ld\"\n", -123456L);
     105    printf("left-adjusted ZLDN:\t\"%-010ld\"\n", -123456L);
     106    printf("space-padded LDN:\t\"%10ld\"\n", -123456L);
     107    printf("left-adjusted SLDN:\t\"%-10ld\"\n", -123456L);
     108  
     109    printf("zero-padded string:\t\"%010s\"\n", shortstr);
     110    printf("left-adjusted Z string:\t\"%-010s\"\n", shortstr);
     111    printf("space-padded string:\t\"%10s\"\n", shortstr);
     112    printf("left-adjusted S string:\t\"%-10s\"\n", shortstr);
     113    /* GCC 9 warns about the NULL format argument; this is deliberately
     114       tested here.  */
     115    DIAG_PUSH_NEEDS_COMMENT;
     116  #if __GNUC_PREREQ (7, 0)
     117    DIAG_IGNORE_NEEDS_COMMENT (9, "-Wformat-overflow=");
     118  #endif
     119    printf("null string:\t\"%s\"\n", (char *)NULL);
     120    DIAG_POP_NEEDS_COMMENT;
     121    printf("limited string:\t\"%.22s\"\n", longstr);
     122  
     123    printf("a-style max:\t\"%a\"\n", DBL_MAX);
     124    printf("a-style -max:\t\"%a\"\n", -DBL_MAX);
     125    printf("e-style >= 1:\t\"%e\"\n", 12.34);
     126    printf("e-style >= .1:\t\"%e\"\n", 0.1234);
     127    printf("e-style < .1:\t\"%e\"\n", 0.001234);
     128    printf("e-style big:\t\"%.60e\"\n", 1e20);
     129    printf ("e-style == .1:\t\"%e\"\n", 0.1);
     130    printf("f-style == 0:\t\"%f\"\n", 0.0);
     131    printf("f-style >= 1:\t\"%f\"\n", 12.34);
     132    printf("f-style >= .1:\t\"%f\"\n", 0.1234);
     133    printf("f-style < .1:\t\"%f\"\n", 0.001234);
     134    printf("g-style == 0:\t\"%g\"\n", 0.0);
     135    printf("g-style >= 1:\t\"%g\"\n", 12.34);
     136    printf("g-style >= .1:\t\"%g\"\n", 0.1234);
     137    printf("g-style < .1:\t\"%g\"\n", 0.001234);
     138    printf("g-style big:\t\"%.60g\"\n", 1e20);
     139  
     140    printf("Lf-style == 0:\t\"%Lf\"\n", (long double) 0.0);
     141    printf("Lf-style >= 1:\t\"%Lf\"\n", (long double) 12.34);
     142    printf("Lf-style >= .1:\t\"%Lf\"\n", (long double) 0.1234);
     143    printf("Lf-style < .1:\t\"%Lf\"\n", (long double) 0.001234);
     144    printf("Lg-style == 0:\t\"%Lg\"\n", (long double) 0.0);
     145    printf("Lg-style >= 1:\t\"%Lg\"\n", (long double) 12.34);
     146    printf("Lg-style >= .1:\t\"%Lg\"\n", (long double) 0.1234);
     147    printf("Lg-style < .1:\t\"%Lg\"\n", (long double) 0.001234);
     148    printf("Lg-style big:\t\"%.60Lg\"\n", (long double) 1e20);
     149  
     150    printf (" %6.5f\n", .099999999860301614);
     151    printf (" %6.5f\n", .1);
     152    printf ("x%5.4fx\n", .5);
     153  
     154    printf (" %6.5Lf\n", (long double) .099999999860301614);
     155    printf (" %6.5Lf\n", (long double) .1);
     156    printf ("x%5.4Lfx\n", (long double) .5);
     157  
     158    printf ("%#03x\n", 1);
     159  
     160    printf ("something really insane: %.10000f\n", 1.0);
     161    printf ("something really insane (long double): %.10000Lf\n",
     162  	  (long double) 1.0);
     163  
     164    {
     165      double d = FLT_MIN;
     166      int niter = 17;
     167  
     168      while (niter-- != 0)
     169        printf ("%.17e\n", d / 2);
     170      fflush (stdout);
     171    }
     172  
     173    printf ("%15.5e\n", 4.9406564584124654e-324);
     174  
     175  #define FORMAT "|%12.4f|%12.4e|%12.4g|%12.4Lf|%12.4Lg|\n"
     176    printf (FORMAT, 0.0, 0.0, 0.0,
     177  	  (long double) 0.0, (long double) 0.0);
     178    printf (FORMAT, 1.0, 1.0, 1.0,
     179  	  (long double) 1.0, (long double) 1.0);
     180    printf (FORMAT, -1.0, -1.0, -1.0,
     181  	  (long double) -1.0, (long double) -1.0);
     182    printf (FORMAT, 100.0, 100.0, 100.0,
     183  	  (long double) 100.0, (long double) 100.0);
     184    printf (FORMAT, 1000.0, 1000.0, 1000.0,
     185  	  (long double) 1000.0, (long double) 1000.0);
     186    printf (FORMAT, 10000.0, 10000.0, 10000.0,
     187  	  (long double) 10000.0, (long double) 10000.0);
     188    printf (FORMAT, 12345.0, 12345.0, 12345.0,
     189  	  (long double) 12345.0, (long double) 12345.0);
     190    printf (FORMAT, 100000.0, 100000.0, 100000.0,
     191  	  (long double) 100000.0, (long double) 100000.0);
     192    printf (FORMAT, 123456.0, 123456.0, 123456.0,
     193  	  (long double) 123456.0, (long double) 123456.0);
     194  #undef	FORMAT
     195  
     196    {
     197      char buf[20];
     198      char buf2[512];
     199      printf ("snprintf (\"%%30s\", \"foo\") == %d, \"%.*s\"\n",
     200  	    snprintf (buf, sizeof (buf), "%30s", "foo"), (int) sizeof (buf),
     201  	    buf);
     202      printf ("snprintf (\"%%.999999u\", 10) == %d\n",
     203  	    snprintf (buf2, sizeof (buf2), "%.999999u", 10));
     204    }
     205  
     206    printf("%.8f\n", DBL_MAX);
     207    printf("%.8f\n", -DBL_MAX);
     208    printf ("%e should be 1.234568e+06\n", 1234567.8);
     209    printf ("%f should be 1234567.800000\n", 1234567.8);
     210    printf ("%g should be 1.23457e+06\n", 1234567.8);
     211    printf ("%g should be 123.456\n", 123.456);
     212    printf ("%g should be 1e+06\n", 1000000.0);
     213    printf ("%g should be 10\n", 10.0);
     214    printf ("%g should be 0.02\n", 0.02);
     215  
     216  #if 0
     217    /* This test rather checks the way the compiler handles constant
     218       folding.  gcc behavior wrt to this changed in 3.2 so it is not a
     219       portable test.  */
     220    {
     221      double x=1.0;
     222      printf("%.17f\n",(1.0/x/10.0+1.0)*x-x);
     223    }
     224  #endif
     225  
     226    {
     227      char buf[200];
     228  
     229      sprintf(buf,"%*s%*s%*s",-1,"one",-20,"two",-30,"three");
     230  
     231      result |= strcmp (buf,
     232  		      "onetwo                 three                         ");
     233  
     234      puts (result != 0 ? "Test failed!" : "Test ok.");
     235    }
     236  
     237    {
     238      char buf[200];
     239  
     240      sprintf (buf, "%07Lo", 040000000000ll);
     241      printf ("sprintf (buf, \"%%07Lo\", 040000000000ll) = %s", buf);
     242  
     243      if (strcmp (buf, "40000000000") != 0)
     244        {
     245  	result = 1;
     246  	fputs ("\tFAILED", stdout);
     247        }
     248      puts ("");
     249    }
     250  
     251    printf ("printf (\"%%hhu\", %u) = %hhu\n", UCHAR_MAX + 2, UCHAR_MAX + 2);
     252    printf ("printf (\"%%hu\", %u) = %hu\n", USHRT_MAX + 2, USHRT_MAX + 2);
     253    printf ("printf (\"%%hhi\", %i) = %hhi\n", UCHAR_MAX + 2, UCHAR_MAX + 2);
     254    printf ("printf (\"%%hi\", %i) = %hi\n", USHRT_MAX + 2, USHRT_MAX + 2);
     255  
     256    printf ("printf (\"%%1$hhu\", %2$u) = %1$hhu\n",
     257  	  UCHAR_MAX + 2, UCHAR_MAX + 2);
     258    printf ("printf (\"%%1$hu\", %2$u) = %1$hu\n", USHRT_MAX + 2, USHRT_MAX + 2);
     259    printf ("printf (\"%%1$hhi\", %2$i) = %1$hhi\n",
     260  	  UCHAR_MAX + 2, UCHAR_MAX + 2);
     261    printf ("printf (\"%%1$hi\", %2$i) = %1$hi\n", USHRT_MAX + 2, USHRT_MAX + 2);
     262  
     263    puts ("--- Should be no further output. ---");
     264    rfg1 ();
     265    rfg2 ();
     266    rfg3 ();
     267  
     268    {
     269      char bytes[7];
     270      char buf[20];
     271  
     272      memset (bytes, '\xff', sizeof bytes);
     273      sprintf (buf, "foo%hhn\n", &bytes[3]);
     274      if (bytes[0] != '\xff' || bytes[1] != '\xff' || bytes[2] != '\xff'
     275  	|| bytes[4] != '\xff' || bytes[5] != '\xff' || bytes[6] != '\xff')
     276        {
     277  	puts ("%hhn overwrite more bytes");
     278  	result = 1;
     279        }
     280      if (bytes[3] != 3)
     281        {
     282  	puts ("%hhn wrote incorrect value");
     283  	result = 1;
     284        }
     285    }
     286  
     287    return result != 0;
     288  }
     289  
     290  static void
     291  rfg1 (void)
     292  {
     293    char buf[100];
     294  
     295    sprintf (buf, "%5.s", "xyz");
     296    if (strcmp (buf, "     ") != 0)
     297      printf ("got: '%s', expected: '%s'\n", buf, "     ");
     298    sprintf (buf, "%5.f", 33.3);
     299    if (strcmp (buf, "   33") != 0)
     300      printf ("got: '%s', expected: '%s'\n", buf, "   33");
     301    sprintf (buf, "%5.Lf", (long double) 33.3);
     302    if (strcmp (buf, "   33") != 0)
     303      printf ("got: '%s', expected: '%s'\n", buf, "   33");
     304    sprintf (buf, "%8.e", 33.3e7);
     305    if (strcmp (buf, "   3e+08") != 0)
     306      printf ("got: '%s', expected: '%s'\n", buf, "   3e+08");
     307    sprintf (buf, "%8.E", 33.3e7);
     308    if (strcmp (buf, "   3E+08") != 0)
     309      printf ("got: '%s', expected: '%s'\n", buf, "   3E+08");
     310    sprintf (buf, "%.g", 33.3);
     311    if (strcmp (buf, "3e+01") != 0)
     312      printf ("got: '%s', expected: '%s'\n", buf, "3e+01");
     313    sprintf (buf, "%.Lg", (long double) 33.3);
     314    if (strcmp (buf, "3e+01") != 0)
     315      printf ("got: '%s', expected: '%s'\n", buf, "3e+01");
     316    sprintf (buf, "%.G", 33.3);
     317    if (strcmp (buf, "3E+01") != 0)
     318      printf ("got: '%s', expected: '%s'\n", buf, "3E+01");
     319  }
     320  
     321  static void
     322  rfg2 (void)
     323  {
     324    int prec;
     325    char buf[100];
     326  
     327    prec = 0;
     328    sprintf (buf, "%.*g", prec, 3.3);
     329    if (strcmp (buf, "3") != 0)
     330      printf ("got: '%s', expected: '%s'\n", buf, "3");
     331    prec = 0;
     332    sprintf (buf, "%.*G", prec, 3.3);
     333    if (strcmp (buf, "3") != 0)
     334      printf ("got: '%s', expected: '%s'\n", buf, "3");
     335    prec = 0;
     336    sprintf (buf, "%7.*G", prec, 3.33);
     337    if (strcmp (buf, "      3") != 0)
     338      printf ("got: '%s', expected: '%s'\n", buf, "      3");
     339    prec = 0;
     340    sprintf (buf, "%.*Lg", prec, (long double) 3.3);
     341    if (strcmp (buf, "3") != 0)
     342      printf ("got: '%s', expected: '%s'\n", buf, "3");
     343    prec = 0;
     344    sprintf (buf, "%.*LG", prec, (long double) 3.3);
     345    if (strcmp (buf, "3") != 0)
     346      printf ("got: '%s', expected: '%s'\n", buf, "3");
     347    prec = 0;
     348    sprintf (buf, "%7.*LG", prec, (long double) 3.33);
     349    if (strcmp (buf, "      3") != 0)
     350      printf ("got: '%s', expected: '%s'\n", buf, "      3");
     351    prec = 3;
     352    sprintf (buf, "%04.*o", prec, 33);
     353    if (strcmp (buf, " 041") != 0)
     354      printf ("got: '%s', expected: '%s'\n", buf, " 041");
     355    prec = 7;
     356    sprintf (buf, "%09.*u", prec, 33);
     357    if (strcmp (buf, "  0000033") != 0)
     358      printf ("got: '%s', expected: '%s'\n", buf, "  0000033");
     359    prec = 3;
     360    sprintf (buf, "%04.*x", prec, 33);
     361    if (strcmp (buf, " 021") != 0)
     362      printf ("got: '%s', expected: '%s'\n", buf, " 021");
     363    prec = 3;
     364    sprintf (buf, "%04.*X", prec, 33);
     365    if (strcmp (buf, " 021") != 0)
     366      printf ("got: '%s', expected: '%s'\n", buf, " 021");
     367  }
     368  
     369  static void
     370  rfg3 (void)
     371  {
     372    char buf[100];
     373    double g = 5.0000001;
     374    unsigned long l = 1234567890;
     375    double d = 321.7654321;
     376    const char s[] = "test-string";
     377    int i = 12345;
     378    int h = 1234;
     379  
     380    sprintf (buf,
     381  	   "%1$*5$d %2$*6$hi %3$*7$lo %4$*8$f %9$*12$e %10$*13$g %11$*14$s",
     382  	   i, h, l, d, 8, 5, 14, 14, d, g, s, 14, 3, 14);
     383    if (strcmp (buf,
     384  	      "   12345  1234    11145401322     321.765432   3.217654e+02   5    test-string") != 0)
     385      printf ("got: '%s', expected: '%s'\n", buf,
     386  	    "   12345  1234    11145401322     321.765432   3.217654e+02   5    test-string");
     387  }
     388  
     389  #define TEST_FUNCTION do_test ()
     390  #include "../test-skeleton.c"