(root)/
bison-3.8.2/
lib/
sprintf.c
       1  /* Formatted output to strings.
       2     Copyright (C) 2004, 2006-2021 Free Software Foundation, Inc.
       3  
       4     This file is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU Lesser General Public License as
       6     published by the Free Software Foundation; either version 3 of the
       7     License, or (at your option) any later version.
       8  
       9     This file 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
      12     GNU Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  #if 1
      18  # include <config.h>
      19  #endif
      20  
      21  /* Specification.  */
      22  #include <stdio.h>
      23  
      24  #include <errno.h>
      25  #include <limits.h>
      26  #include <stdarg.h>
      27  #include <stdint.h>
      28  #include <stdlib.h>
      29  
      30  #include "vasnprintf.h"
      31  
      32  #ifndef SIZE_MAX
      33  # define SIZE_MAX ((size_t) -1)
      34  #endif
      35  
      36  /* Print formatted output to string STR.
      37     Return string length of formatted string.  On error, return a negative
      38     value.  */
      39  int
      40  sprintf (char *str, const char *format, ...)
      41  {
      42    char *output;
      43    size_t len;
      44    size_t lenbuf;
      45    va_list args;
      46  
      47    /* vasnprintf fails with EOVERFLOW when the buffer size argument is larger
      48       than INT_MAX (if that fits into a 'size_t' at all).
      49       Also note that glibc's iconv fails with E2BIG when we pass a length that
      50       is so large that str + lenbuf wraps around, i.e.
      51       (uintptr_t) (str + lenbuf) < (uintptr_t) str.
      52       Therefore set lenbuf = min (SIZE_MAX, INT_MAX, - (uintptr_t) str - 1).  */
      53    lenbuf = (SIZE_MAX < INT_MAX ? SIZE_MAX : INT_MAX);
      54    if (lenbuf > ~ (uintptr_t) str)
      55      lenbuf = ~ (uintptr_t) str;
      56  
      57    va_start (args, format);
      58    output = vasnprintf (str, &lenbuf, format, args);
      59    len = lenbuf;
      60    va_end (args);
      61  
      62    if (!output)
      63      return -1;
      64  
      65    if (output != str)
      66      {
      67        /* len is near SIZE_MAX.  */
      68        free (output);
      69        errno = EOVERFLOW;
      70        return -1;
      71      }
      72  
      73    if (len > INT_MAX)
      74      {
      75        errno = EOVERFLOW;
      76        return -1;
      77      }
      78  
      79    return len;
      80  }