emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Problem report #106: base/src/emacs/src/doprnt.c (doprnt1); OVERRUN_STAT


From: Dan Nicolaescu
Subject: Problem report #106: base/src/emacs/src/doprnt.c (doprnt1); OVERRUN_STATIC
Date: Tue, 2 Dec 2008 14:15:02 -0800 (PST)

CID: 106
Checker: OVERRUN_STATIC (help)
File: base/src/emacs/src/doprnt.c
Function: doprnt1
Description: NOTE: These bugs are often difficult to see at first glance. 
Coverity Prevent recommends a close inspection of the events leading to this 
overrun.

52      /* Generate output from a format-spec FORMAT,
53         terminated at position FORMAT_END.
54         Output goes in BUFFER, which has room for BUFSIZE chars.
55         If the output does not fit, truncate it to fit.
56         Returns the number of bytes stored into BUFFER.
57         ARGS points to the vector of arguments, and NARGS says how many.
58         A double counts as two arguments.
59         String arguments are passed as C strings.
60         Integers are passed as C integers.  */
61      
62      int
63      doprnt (buffer, bufsize, format, format_end, nargs, args)
64           char *buffer;
65           register int bufsize;
66           char *format;
67           char *format_end;
68           int nargs;
69           char **args;
70      {
71        return doprnt1 (0, buffer, bufsize, format, format_end, nargs, args);
72      }
73      
74      /* Like doprnt except that strings in ARGS are passed
75         as Lisp_Object.  */
76      
77      int
78      doprnt_lisp (buffer, bufsize, format, format_end, nargs, args)
79           char *buffer;
80           register int bufsize;
81           char *format;
82           char *format_end;
83           int nargs;
84           char **args;
85      {
86        return doprnt1 (1, buffer, bufsize, format, format_end, nargs, args);
87      }
88      
89      static int
90      doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
91           int lispstrings;
92           char *buffer;
93           register int bufsize;
94           char *format;
95           char *format_end;
96           int nargs;
97           char **args;
98      {
99        int cnt = 0;                  /* Number of arg to gobble next */
100       register char *fmt = format;  /* Pointer into format string */
101       register char *bufptr = buffer; /* Pointer into output buffer.. */
102     
103       /* Use this for sprintf unless we need something really big.  */
104       char tembuf[DBL_MAX_10_EXP + 100];
105     
106       /* Size of sprintf_buffer.  */
107       unsigned size_allocated = sizeof (tembuf);
108     
109       /* Buffer to use for sprintf.  Either tembuf or same as BIG_BUFFER.  
*/
110       char *sprintf_buffer = tembuf;
111     
112       /* Buffer we have got with malloc.  */
113       char *big_buffer = 0;
114     
115       register int tem;
116       unsigned char *string;
117       char fixed_buffer[20];        /* Default buffer for small formatting. 
*/
118       char *fmtcpy;
119       int minlen;
120       unsigned char charbuf[5];     /* Used for %c.  */
121     
122       if (format_end == 0)
123         format_end = format + strlen (format);
124     
125       if ((format_end - format + 1) < sizeof (fixed_buffer))
126         fmtcpy = fixed_buffer;
127       else
128         fmtcpy = (char *) alloca (format_end - format + 1);
129     
130       bufsize--;
131     
132       /* Loop until end of format string or buffer full. */

At conditional (6): "fmt != format_end" taking true path
At conditional (7): "bufsize > 0" taking true path

133       while (fmt != format_end && bufsize > 0)
134         {

At conditional (8): "*fmt == 37" taking true path

135           if (*fmt == '%')  /* Check for a '%' character */
136             {
137               unsigned size_bound = 0;
138               int width;            /* Columns occupied by STRING.  */
139     
140               fmt++;
141               /* Copy this one %-spec into fmtcpy.  */
142               string = (unsigned char *) fmtcpy;
143               *string++ = '%';

At conditional (9): "1" taking true path

144               while (1)
145                 {
146                   *string++ = *fmt;

At conditional (10): "48 <= *fmt" taking false path

147                   if ('0' <= *fmt && *fmt <= '9')
148                     {
149                       /* Get an idea of how much space we might need.
150                          This might be a field width or a precision; e.g.
151                          %1.1000f and %1000.1f both might need 1000+ bytes.
152                          Parse the width or precision, checking for 
overflow.  */
153                       unsigned n = *fmt - '0';
154                       while ('0' <= fmt[1] && fmt[1] <= '9')
155                         {
156                           if (n * 10 / 10 != n
157                               || (n = n * 10 + (fmt[1] - '0')) < n)
158                             error ("Format width or precision too large");
159                           *string++ = *++fmt;
160                         }
161     
162                       if (size_bound < n)
163                         size_bound = n;
164                     }

At conditional (11): "*fmt == 45" taking false path
At conditional (12): "*fmt == 32" taking false path
At conditional (13): "*fmt == 46" taking false path
At conditional (14): "*fmt == 43" taking false path

165                   else if (*fmt == '-' || *fmt == ' ' || *fmt == '.' || 
*fmt == '+')
166                     ;
167                   else
168                     break;
169                   fmt++;
170                 }
171               *string = 0;
172     
173               /* Make the size bound large enough to handle floating point 
formats
174                  with large numbers.  */

At conditional (15): "((size_bound + 308) + 50) < size_bound" taking false path

175               if (size_bound + DBL_MAX_10_EXP + 50 < size_bound)
176                 error ("Format width or precision too large");
177               size_bound += DBL_MAX_10_EXP + 50;
178     
179               /* Make sure we have that much.  */

At conditional (16): "size_bound > size_allocated" taking false path

180               if (size_bound > size_allocated)
181                 {
182                   if (big_buffer)
183                     big_buffer = (char *) xrealloc (big_buffer, size_bound);
184                   else
185                     big_buffer = (char *) xmalloc (size_bound);
186                   sprintf_buffer = big_buffer;
187                   size_allocated = size_bound;
188                 }
189               minlen = 0;
190               switch (*fmt++)
191                 {
192                 default:
193                   error ("Invalid format operation %%%c", fmt[-1]);
194     
195     /*          case 'b': */
196                 case 'd':
197                 case 'o':
198                 case 'x':
199                   if (cnt == nargs)
200                     error ("Not enough arguments for format string");
201                   if (sizeof (int) == sizeof (EMACS_INT))
202                     ;
203                   else if (sizeof (long) == sizeof (EMACS_INT))
204                     /* Insert an `l' the right place.  */
205                     string[1] = string[0],
206                     string[0] = string[-1],
207                     string[-1] = 'l',
208                     string++;
209                   else
210                     abort ();
211                   sprintf (sprintf_buffer, fmtcpy, args[cnt++]);
212                   /* Now copy into final output, truncating as nec.  */
213                   string = (unsigned char *) sprintf_buffer;
214                   goto doit;
215     
216                 case 'f':
217                 case 'e':
218                 case 'g':
219                   {
220                     union { double d; char *half[2]; } u;
221                     if (cnt + 1 == nargs)
222                       error ("Not enough arguments for format string");
223                     u.half[0] = args[cnt++];
224                     u.half[1] = args[cnt++];
225                     sprintf (sprintf_buffer, fmtcpy, u.d);
226                     /* Now copy into final output, truncating as nec.  */
227                     string = (unsigned char *) sprintf_buffer;
228                     goto doit;
229                   }
230     
231                 case 'S':
232                   string[-1] = 's';
233                 case 's':
234                   if (cnt == nargs)
235                     error ("Not enough arguments for format string");
236                   if (fmtcpy[1] != 's')
237                     minlen = atoi (&fmtcpy[1]);
238                   if (lispstrings)
239                     {
240                       string = ((struct Lisp_String *) args[cnt])->data;
241                       tem = STRING_BYTES ((struct Lisp_String *) args[cnt]);
242                       cnt++;
243                     }
244                   else
245                     {
246                       string = (unsigned char *) args[cnt++];
247                       tem = strlen (string);
248                     }
249                   width = strwidth (string, tem);
250                   goto doit1;
251     
252                   /* Copy string into final output, truncating if no room.  
*/
253                 doit:
254                   /* Coming here means STRING contains ASCII only.  */
255                   width = tem = strlen (string);
256                 doit1:
257                   /* We have already calculated:
258                      TEM -- length of STRING,
259                      WIDTH -- columns occupied by STRING when displayed, and
260                      MINLEN -- minimum columns of the output.  */
261                   if (minlen > 0)
262                     {

At conditional (1): "bufsize > 0" taking false path

263                       while (minlen > width && bufsize > 0)
264                         {
265                           *bufptr++ = ' ';
266                           bufsize--;
267                           minlen--;
268                         }
269                       minlen = 0;
270                     }

At conditional (2): "tem > bufsize" taking true path

271                   if (tem > bufsize)
272                     {
273                       /* Truncate the string at character boundary.  */
274                       tem = bufsize;

At conditional (3): "*(string + (tem - 1)) & 192 == 128" taking true path
At conditional (4): "*(string + (tem - 1)) & 192 == 128" taking false path

275                       while (!CHAR_HEAD_P (string[tem - 1])) tem--;
276                       bcopy (string, bufptr, tem);
277                       /* We must calculate WIDTH again.  */
278                       width = strwidth (bufptr, tem);
279                     }
280                   else
281                     bcopy (string, bufptr, tem);
282                   bufptr += tem;
283                   bufsize -= tem;

At conditional (5): "minlen < 0" taking false path

284                   if (minlen < 0)
285                     {
286                       while (minlen < - width && bufsize > 0)
287                         {
288                           *bufptr++ = ' ';
289                           bufsize--;
290                           minlen++;
291                         }
292                       minlen = 0;
293                     }
294                   continue;
295     

At conditional (17): "*fmt++ == 99" taking true path

296                 case 'c':

At conditional (18): "cnt == nargs" taking false path

297                   if (cnt == nargs)
298                     error ("Not enough arguments for format string");

Event assignment: Assigning "char_string" to "tem"
Event eq_context: Callee context: equality "char_string"
Also see events: [ptr_assign][eq_context][overrun-local][overrun-local]
At conditional (19): "*(args + (cnt * 8)) <= 127" taking false path
At conditional (20): "*(args + (cnt * 8)) <= 2047" taking false path
At conditional (21): "*(args + (cnt * 8)) <= 65535" taking false path

299                   tem = CHAR_STRING ((int) (EMACS_INT) args[cnt], charbuf);

Event ptr_assign: Pointer "string" assigned address of static buffer pointer 
"&charbuf" of size 5 and offset 0
Also see events: [assignment][eq_context][overrun-local][overrun-local]

300                   string = charbuf;
301                   cnt++;

Event overrun-local: Overrun of static array of size 5 at position 5 by 
indexing pointer alias "string" with index variable "tem"
Event overrun-local: NOTE: These bugs are often difficult to see at first 
glance. Coverity Prevent recommends a close inspection of the events leading to 
this overrun.
Also see events: [ptr_assign][assignment][eq_context][overrun-local]

302                   string[tem] = 0;
303                   width = strwidth (string, tem);
304                   if (fmtcpy[1] != 'c')
305                     minlen = atoi (&fmtcpy[1]);
306                   goto doit1;
307     
308                 case '%':
309                   fmt--;    /* Drop thru and this % will be treated as 
normal */
310                 }
311             }
312     
313           {
314             /* Just some character; Copy it if the whole multi-byte form
315                fit in the buffer.  */
316             char *save_bufptr = bufptr;
317     
318             do { *bufptr++ = *fmt++; }
319             while (--bufsize > 0 && !CHAR_HEAD_P (*fmt));
320             if (!CHAR_HEAD_P (*fmt))
321               {
322                 bufptr = save_bufptr;
323                 break;
324               }
325           }
326         };
327     
328       /* If we had to malloc something, free it.  */
329       xfree (big_buffer);
330     
331       *bufptr = 0;          /* Make sure our string end with a '\0' */
332       return bufptr - buffer;
333     }
334     
335     /* arch-tag: aa0ab528-7c5f-4c73-894c-aa2526a1efb3
336        (do not change this comment) */























































reply via email to

[Prev in Thread] Current Thread [Next in Thread]