Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/libiberty/vprintf-support.c
Line
Count
Source (jump to first uncovered line)
1
/* Estimate the length of the string generated by a vprintf-like
2
   function.  Used by vasprintf and xvasprintf.
3
   Copyright (C) 1994-2025 Free Software Foundation, Inc.
4
5
This file is part of the libiberty library.
6
Libiberty is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Library General Public
8
License as published by the Free Software Foundation; either
9
version 2 of the License, or (at your option) any later version.
10
11
Libiberty is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
Library General Public License for more details.
15
16
You should have received a copy of the GNU Library General Public
17
License along with libiberty; see the file COPYING.LIB.  If not, write
18
to the Free Software Foundation, Inc., 51 Franklin Street - Fifth
19
Floor, Boston, MA 02110-1301, USA.  */
20
21
#ifdef HAVE_CONFIG_H
22
#include "config.h"
23
#endif
24
#include <ansidecl.h>
25
#include <stdarg.h>
26
#if !defined (va_copy) && defined (__va_copy)
27
# define va_copy(d,s)  __va_copy((d),(s))
28
#endif
29
#include <stdio.h>
30
#ifdef HAVE_STRING_H
31
#include <string.h>
32
#endif
33
#ifdef HAVE_STDLIB_H
34
#include <stdlib.h>
35
#else
36
extern unsigned long strtoul ();
37
#endif
38
#include "libiberty.h"
39
40
int
41
libiberty_vprintf_buffer_size (const char *format, va_list args)
42
2.07k
{
43
2.07k
  const char *p = format;
44
  /* Add one to make sure that it is never zero, which might cause malloc
45
     to return NULL.  */
46
2.07k
  int total_width = strlen (format) + 1;
47
2.07k
  va_list ap;
48
49
2.07k
#ifdef va_copy
50
2.07k
  va_copy (ap, args);
51
#else
52
  memcpy ((void *) &ap, (void *) &args, sizeof (va_list));
53
#endif
54
55
29.0k
  while (*p != '\0')
56
26.9k
    {
57
26.9k
      if (*p++ == '%')
58
2.07k
  {
59
2.07k
    int prec = 0;
60
2.07k
    while (strchr ("-+ #0", *p))
61
0
      ++p;
62
2.07k
    if (*p == '*')
63
0
      {
64
0
        ++p;
65
0
        total_width += abs (va_arg (ap, int));
66
0
      }
67
2.07k
    else
68
2.07k
      total_width += strtoul (p, (char **) &p, 10);
69
2.07k
    if (*p == '.')
70
0
      {
71
0
        ++p;
72
0
        if (*p == '*')
73
0
    {
74
0
      ++p;
75
0
      total_width += abs (va_arg (ap, int));
76
0
    }
77
0
        else
78
0
        total_width += strtoul (p, (char **) &p, 10);
79
0
      }
80
2.07k
    do
81
2.07k
      {
82
2.07k
        switch (*p)
83
2.07k
    {
84
0
    case 'h':
85
0
      ++p;
86
0
      continue;
87
0
    case 'l':
88
0
    case 'L':
89
0
      ++prec;
90
0
      ++p;
91
0
      continue;
92
0
    case 'z':
93
0
      prec = 3;
94
0
      ++p;
95
0
      continue;
96
0
    case 't':
97
0
      prec = 4;
98
0
      ++p;
99
0
      continue;
100
#ifdef _WIN32
101
    case 'I':
102
      if (p[1] == '6' && p[2] == '4')
103
        {
104
          prec = 2;
105
          p += 3;
106
          continue;
107
        }
108
      break;
109
#endif
110
2.07k
    default:
111
2.07k
      break;
112
2.07k
    }
113
2.07k
        break;
114
2.07k
      }
115
2.07k
    while (1);
116
117
    /* Should be big enough for any format specifier except %s and floats.  */
118
2.07k
    total_width += 30;
119
2.07k
    switch (*p)
120
2.07k
      {
121
0
      case 'd':
122
0
      case 'i':
123
0
      case 'o':
124
1.91k
      case 'u':
125
1.91k
      case 'x':
126
1.91k
      case 'X':
127
1.91k
        switch (prec)
128
1.91k
    {
129
1.91k
    case 0: (void) va_arg (ap, int); break;
130
0
    case 1: (void) va_arg (ap, long int); break;
131
0
    case 2: (void) va_arg (ap, long long int); break;
132
0
    case 3: (void) va_arg (ap, size_t); break;
133
0
    case 4: (void) va_arg (ap, ptrdiff_t); break;
134
1.91k
    }
135
1.91k
        break;
136
1.91k
      case 'c':
137
0
        (void) va_arg (ap, int);
138
0
        break;
139
0
      case 'f':
140
0
      case 'e':
141
0
      case 'E':
142
0
      case 'g':
143
0
      case 'G':
144
0
        if (!prec)
145
0
    {
146
0
      (void) va_arg (ap, double);
147
      /* Since an ieee double can have an exponent of 308, we'll
148
         make the buffer wide enough to cover the gross case. */
149
0
      total_width += 308;
150
0
    }
151
0
        else
152
0
    {
153
0
      (void) va_arg (ap, long double);
154
0
      total_width += 4932;
155
0
    }
156
0
        break;
157
160
      case 's':
158
160
        total_width += strlen (va_arg (ap, char *));
159
160
        break;
160
0
      case 'p':
161
0
      case 'n':
162
0
        (void) va_arg (ap, char *);
163
0
        break;
164
2.07k
      }
165
2.07k
    p++;
166
2.07k
  }
167
26.9k
    }
168
2.07k
#ifdef va_copy
169
2.07k
  va_end (ap);
170
2.07k
#endif
171
2.07k
  return total_width;
172
2.07k
}