Revision 53a416d3 lib/printf.c

View differences:

lib/printf.c
4 4
 *	(c) 1991, 1992 Lars Wirzenius & Linus Torvalds
5 5
 *
6 6
 *	Hacked up for BIRD by Martin Mares <mj@ucw.cz>
7
 *	Buffer size limitation implemented by Martin Mares.
7 8
 */
8 9

  
9 10
#include "nest/bird.h"
......
38 39
n = ((unsigned long) n) / (unsigned) base; \
39 40
__res; })
40 41

  
41
static char * number(char * str, long num, int base, int size, int precision
42
	,int type)
42
static char * number(char * str, long num, int base, int size, int precision,
43
	int type, int remains)
43 44
{
44 45
	char c,sign,tmp[66];
45 46
	const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
46 47
	int i;
47 48

  
49
	if (size >= 0 && (remains -= size) < 0)
50
		return NULL;
48 51
	if (type & LARGE)
49 52
		digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
50 53
	if (type & LEFT)
......
80 83
	if (i > precision)
81 84
		precision = i;
82 85
	size -= precision;
86
	if (size < 0 && -size > remains)
87
		return NULL;
83 88
	if (!(type&(ZEROPAD+LEFT)))
84 89
		while(size-->0)
85 90
			*str++ = ' ';
......
105 110
	return str;
106 111
}
107 112

  
108
int bvsprintf(char *buf, const char *fmt, va_list args)
113
int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
109 114
{
110 115
	int len;
111 116
	unsigned long num;
112 117
	int i, base;
113
	char * str;
118
	char *str, *start;
114 119
	const char *s;
115 120

  
116 121
	int flags;		/* flags to number() */
......
120 125
				   number of chars for from string */
121 126
	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
122 127

  
123
	for (str=buf ; *fmt ; ++fmt) {
128
	for (start=str=buf ; *fmt ; ++fmt, size-=(str-start), start=str) {
124 129
		if (*fmt != '%') {
130
			if (!size)
131
				return -1;
125 132
			*str++ = *fmt;
126 133
			continue;
127 134
		}
......
177 184
		/* default base */
178 185
		base = 10;
179 186

  
187
		if (field_width > size)
188
			return -1;
180 189
		switch (*fmt) {
181 190
		case 'c':
182 191
			if (!(flags & LEFT))
......
199 208
			len = strlen(s);
200 209
			if (precision >= 0 && len > precision)
201 210
				len = precision;
211
			if (len > size)
212
				return -1;
202 213

  
203 214
			if (!(flags & LEFT))
204 215
				while (len < field_width--)
......
216 227
			}
217 228
			str = number(str,
218 229
				(unsigned long) va_arg(args, void *), 16,
219
				field_width, precision, flags);
230
				field_width, precision, flags, size);
231
			if (!str)
232
				return -1;
220 233
			continue;
221 234

  
222 235

  
......
232 245

  
233 246
		/* IP address */
234 247
		case 'I':
248
			if (size < STD_ADDRESS_P_LENGTH)
249
				return -1;
235 250
			if (flags & SPECIAL)
236 251
				str = ip_ntox(va_arg(args, ip_addr), str);
237 252
			else {
......
261 276
			break;
262 277

  
263 278
		default:
279
			if (size < 2)
280
				return -1;
264 281
			if (*fmt != '%')
265 282
				*str++ = '%';
266 283
			if (*fmt)
......
280 297
			num = va_arg(args, int);
281 298
		else
282 299
			num = va_arg(args, unsigned int);
283
		str = number(str, num, base, field_width, precision, flags);
300
		str = number(str, num, base, field_width, precision, flags, size);
301
		if (!str)
302
			return -1;
284 303
	}
304
	if (!size)
305
		return -1;
285 306
	*str = '\0';
286 307
	return str-buf;
287 308
}
288 309

  
310
int bvsprintf(char *buf, const char *fmt, va_list args)
311
{
312
  return bvsnprintf(buf, 1000000000, fmt, args);
313
}
314

  
289 315
int bsprintf(char * buf, const char *fmt, ...)
290 316
{
291
	va_list args;
292
	int i;
317
  va_list args;
318
  int i;
293 319

  
294
	va_start(args, fmt);
295
	i=bvsprintf(buf,fmt,args);
296
	va_end(args);
297
	return i;
320
  va_start(args, fmt);
321
  i=bvsnprintf(buf, 1000000000, fmt, args);
322
  va_end(args);
323
  return i;
324
}
325

  
326
int bsnprintf(char * buf, int size, const char *fmt, ...)
327
{
328
  va_list args;
329
  int i;
330

  
331
  va_start(args, fmt);
332
  i=bvsnprintf(buf, size, fmt, args);
333
  va_end(args);
334
  return i;
298 335
}

Also available in: Unified diff