debuggers.hg

view xen/common/vsprintf.c @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents 40233384ffe3
children
line source
1 /*
2 * linux/lib/vsprintf.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
8 /*
9 * Wirzenius wrote this portably, Torvalds fucked it up :-)
10 */
12 /*
13 * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
14 * - changed to provide snprintf and vsnprintf functions
15 * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
16 * - scnprintf and vscnprintf
17 */
19 #include <xen/stdarg.h>
20 #include <xen/ctype.h>
21 #include <xen/lib.h>
22 #include <asm/div64.h>
23 #include <asm/page.h>
25 /**
26 * simple_strtoul - convert a string to an unsigned long
27 * @cp: The start of the string
28 * @endp: A pointer to the end of the parsed string will be placed here
29 * @base: The number base to use
30 */
31 unsigned long simple_strtoul(
32 const char *cp, const char **endp, unsigned int base)
33 {
34 unsigned long result = 0,value;
36 if (!base) {
37 base = 10;
38 if (*cp == '0') {
39 base = 8;
40 cp++;
41 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
42 cp++;
43 base = 16;
44 }
45 }
46 } else if (base == 16) {
47 if (cp[0] == '0' && toupper(cp[1]) == 'X')
48 cp += 2;
49 }
50 while (isxdigit(*cp) &&
51 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
52 result = result*base + value;
53 cp++;
54 }
55 if (endp)
56 *endp = cp;
57 return result;
58 }
60 EXPORT_SYMBOL(simple_strtoul);
62 /**
63 * simple_strtol - convert a string to a signed long
64 * @cp: The start of the string
65 * @endp: A pointer to the end of the parsed string will be placed here
66 * @base: The number base to use
67 */
68 long simple_strtol(const char *cp, const char **endp, unsigned int base)
69 {
70 if(*cp=='-')
71 return -simple_strtoul(cp+1,endp,base);
72 return simple_strtoul(cp,endp,base);
73 }
75 EXPORT_SYMBOL(simple_strtol);
77 /**
78 * simple_strtoull - convert a string to an unsigned long long
79 * @cp: The start of the string
80 * @endp: A pointer to the end of the parsed string will be placed here
81 * @base: The number base to use
82 */
83 unsigned long long simple_strtoull(
84 const char *cp, const char **endp, unsigned int base)
85 {
86 unsigned long long result = 0,value;
88 if (!base) {
89 base = 10;
90 if (*cp == '0') {
91 base = 8;
92 cp++;
93 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
94 cp++;
95 base = 16;
96 }
97 }
98 } else if (base == 16) {
99 if (cp[0] == '0' && toupper(cp[1]) == 'X')
100 cp += 2;
101 }
102 while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
103 ? toupper(*cp) : *cp)-'A'+10) < base) {
104 result = result*base + value;
105 cp++;
106 }
107 if (endp)
108 *endp = cp;
109 return result;
110 }
112 EXPORT_SYMBOL(simple_strtoull);
114 /**
115 * simple_strtoll - convert a string to a signed long long
116 * @cp: The start of the string
117 * @endp: A pointer to the end of the parsed string will be placed here
118 * @base: The number base to use
119 */
120 long long simple_strtoll(const char *cp,const char **endp,unsigned int base)
121 {
122 if(*cp=='-')
123 return -simple_strtoull(cp+1,endp,base);
124 return simple_strtoull(cp,endp,base);
125 }
127 static int skip_atoi(const char **s)
128 {
129 int i=0;
131 while (isdigit(**s))
132 i = i*10 + *((*s)++) - '0';
133 return i;
134 }
136 #define ZEROPAD 1 /* pad with zero */
137 #define SIGN 2 /* unsigned/signed long */
138 #define PLUS 4 /* show plus */
139 #define SPACE 8 /* space if plus */
140 #define LEFT 16 /* left justified */
141 #define SPECIAL 32 /* 0x */
142 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
144 static char *number(
145 char *buf, char *end, unsigned long long num,
146 int base, int size, int precision, int type)
147 {
148 char c,sign,tmp[66];
149 const char *digits;
150 static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
151 static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
152 int i;
154 digits = (type & LARGE) ? large_digits : small_digits;
155 if (type & LEFT)
156 type &= ~ZEROPAD;
157 if (base < 2 || base > 36)
158 return NULL;
159 c = (type & ZEROPAD) ? '0' : ' ';
160 sign = 0;
161 if (type & SIGN) {
162 if ((signed long long) num < 0) {
163 sign = '-';
164 num = - (signed long long) num;
165 size--;
166 } else if (type & PLUS) {
167 sign = '+';
168 size--;
169 } else if (type & SPACE) {
170 sign = ' ';
171 size--;
172 }
173 }
174 if (type & SPECIAL) {
175 if (base == 16)
176 size -= 2;
177 else if (base == 8)
178 size--;
179 }
180 i = 0;
181 if (num == 0)
182 tmp[i++]='0';
183 else while (num != 0)
184 tmp[i++] = digits[do_div(num,base)];
185 if (i > precision)
186 precision = i;
187 size -= precision;
188 if (!(type&(ZEROPAD+LEFT))) {
189 while(size-->0) {
190 if (buf <= end)
191 *buf = ' ';
192 ++buf;
193 }
194 }
195 if (sign) {
196 if (buf <= end)
197 *buf = sign;
198 ++buf;
199 }
200 if (type & SPECIAL) {
201 if (base==8) {
202 if (buf <= end)
203 *buf = '0';
204 ++buf;
205 } else if (base==16) {
206 if (buf <= end)
207 *buf = '0';
208 ++buf;
209 if (buf <= end)
210 *buf = digits[33];
211 ++buf;
212 }
213 }
214 if (!(type & LEFT)) {
215 while (size-- > 0) {
216 if (buf <= end)
217 *buf = c;
218 ++buf;
219 }
220 }
221 while (i < precision--) {
222 if (buf <= end)
223 *buf = '0';
224 ++buf;
225 }
226 while (i-- > 0) {
227 if (buf <= end)
228 *buf = tmp[i];
229 ++buf;
230 }
231 while (size-- > 0) {
232 if (buf <= end)
233 *buf = ' ';
234 ++buf;
235 }
236 return buf;
237 }
239 /**
240 * vsnprintf - Format a string and place it in a buffer
241 * @buf: The buffer to place the result into
242 * @size: The size of the buffer, including the trailing null space
243 * @fmt: The format string to use
244 * @args: Arguments for the format string
245 *
246 * The return value is the number of characters which would
247 * be generated for the given input, excluding the trailing
248 * '\0', as per ISO C99. If you want to have the exact
249 * number of characters written into @buf as return value
250 * (not including the trailing '\0'), use vscnprintf. If the
251 * return is greater than or equal to @size, the resulting
252 * string is truncated.
253 *
254 * Call this function if you are already dealing with a va_list.
255 * You probably want snprintf instead.
256 */
257 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
258 {
259 int len;
260 unsigned long long num;
261 int i, base;
262 char *str, *end, c;
263 const char *s;
265 int flags; /* flags to number() */
267 int field_width; /* width of output field */
268 int precision; /* min. # of digits for integers; max
269 number of chars for from string */
270 int qualifier; /* 'h', 'l', or 'L' for integer fields */
271 /* 'z' support added 23/7/1999 S.H. */
272 /* 'z' changed to 'Z' --davidm 1/25/99 */
274 /* Reject out-of-range values early */
275 BUG_ON(((int)size < 0) || ((unsigned int)size != size));
277 str = buf;
278 end = buf + size - 1;
280 if (end < buf - 1) {
281 end = ((void *) -1);
282 size = end - buf + 1;
283 }
285 for (; *fmt ; ++fmt) {
286 if (*fmt != '%') {
287 if (str <= end)
288 *str = *fmt;
289 ++str;
290 continue;
291 }
293 /* process flags */
294 flags = 0;
295 repeat:
296 ++fmt; /* this also skips first '%' */
297 switch (*fmt) {
298 case '-': flags |= LEFT; goto repeat;
299 case '+': flags |= PLUS; goto repeat;
300 case ' ': flags |= SPACE; goto repeat;
301 case '#': flags |= SPECIAL; goto repeat;
302 case '0': flags |= ZEROPAD; goto repeat;
303 }
305 /* get field width */
306 field_width = -1;
307 if (isdigit(*fmt))
308 field_width = skip_atoi(&fmt);
309 else if (*fmt == '*') {
310 ++fmt;
311 /* it's the next argument */
312 field_width = va_arg(args, int);
313 if (field_width < 0) {
314 field_width = -field_width;
315 flags |= LEFT;
316 }
317 }
319 /* get the precision */
320 precision = -1;
321 if (*fmt == '.') {
322 ++fmt;
323 if (isdigit(*fmt))
324 precision = skip_atoi(&fmt);
325 else if (*fmt == '*') {
326 ++fmt;
327 /* it's the next argument */
328 precision = va_arg(args, int);
329 }
330 if (precision < 0)
331 precision = 0;
332 }
334 /* get the conversion qualifier */
335 qualifier = -1;
336 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
337 *fmt =='Z' || *fmt == 'z') {
338 qualifier = *fmt;
339 ++fmt;
340 if (qualifier == 'l' && *fmt == 'l') {
341 qualifier = 'L';
342 ++fmt;
343 }
344 }
346 /* default base */
347 base = 10;
349 switch (*fmt) {
350 case 'c':
351 if (!(flags & LEFT)) {
352 while (--field_width > 0) {
353 if (str <= end)
354 *str = ' ';
355 ++str;
356 }
357 }
358 c = (unsigned char) va_arg(args, int);
359 if (str <= end)
360 *str = c;
361 ++str;
362 while (--field_width > 0) {
363 if (str <= end)
364 *str = ' ';
365 ++str;
366 }
367 continue;
369 case 's':
370 s = va_arg(args, char *);
371 if ((unsigned long)s < PAGE_SIZE)
372 s = "<NULL>";
374 len = strnlen(s, precision);
376 if (!(flags & LEFT)) {
377 while (len < field_width--) {
378 if (str <= end)
379 *str = ' ';
380 ++str;
381 }
382 }
383 for (i = 0; i < len; ++i) {
384 if (str <= end)
385 *str = *s;
386 ++str; ++s;
387 }
388 while (len < field_width--) {
389 if (str <= end)
390 *str = ' ';
391 ++str;
392 }
393 continue;
395 case 'p':
396 if (field_width == -1) {
397 field_width = 2*sizeof(void *);
398 flags |= ZEROPAD;
399 }
400 str = number(str, end,
401 (unsigned long) va_arg(args, void *),
402 16, field_width, precision, flags);
403 continue;
406 case 'n':
407 if (qualifier == 'l') {
408 long * ip = va_arg(args, long *);
409 *ip = (str - buf);
410 } else if (qualifier == 'Z' || qualifier == 'z') {
411 size_t * ip = va_arg(args, size_t *);
412 *ip = (str - buf);
413 } else {
414 int * ip = va_arg(args, int *);
415 *ip = (str - buf);
416 }
417 continue;
419 case '%':
420 if (str <= end)
421 *str = '%';
422 ++str;
423 continue;
425 /* integer number formats - set up the flags and "break" */
426 case 'o':
427 base = 8;
428 break;
430 case 'X':
431 flags |= LARGE;
432 case 'x':
433 base = 16;
434 break;
436 case 'd':
437 case 'i':
438 flags |= SIGN;
439 case 'u':
440 break;
442 default:
443 if (str <= end)
444 *str = '%';
445 ++str;
446 if (*fmt) {
447 if (str <= end)
448 *str = *fmt;
449 ++str;
450 } else {
451 --fmt;
452 }
453 continue;
454 }
455 if (qualifier == 'L')
456 num = va_arg(args, long long);
457 else if (qualifier == 'l') {
458 num = va_arg(args, unsigned long);
459 if (flags & SIGN)
460 num = (signed long) num;
461 } else if (qualifier == 'Z' || qualifier == 'z') {
462 num = va_arg(args, size_t);
463 } else if (qualifier == 'h') {
464 num = (unsigned short) va_arg(args, int);
465 if (flags & SIGN)
466 num = (signed short) num;
467 } else {
468 num = va_arg(args, unsigned int);
469 if (flags & SIGN)
470 num = (signed int) num;
471 }
473 str = number(str, end, num, base,
474 field_width, precision, flags);
475 }
476 if (str <= end)
477 *str = '\0';
478 else if (size > 0)
479 /* don't write out a null byte if the buf size is zero */
480 *end = '\0';
481 /* the trailing null byte doesn't count towards the total
482 * ++str;
483 */
484 return str-buf;
485 }
487 EXPORT_SYMBOL(vsnprintf);
489 /**
490 * vscnprintf - Format a string and place it in a buffer
491 * @buf: The buffer to place the result into
492 * @size: The size of the buffer, including the trailing null space
493 * @fmt: The format string to use
494 * @args: Arguments for the format string
495 *
496 * The return value is the number of characters which have been written into
497 * the @buf not including the trailing '\0'. If @size is <= 0 the function
498 * returns 0.
499 *
500 * Call this function if you are already dealing with a va_list.
501 * You probably want scnprintf instead.
502 */
503 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
504 {
505 int i;
507 i = vsnprintf(buf,size,fmt,args);
508 if (i >= size)
509 i = size - 1;
510 return (i > 0) ? i : 0;
511 }
513 EXPORT_SYMBOL(vscnprintf);
515 /**
516 * vsscanf - Unformat a buffer into a list of arguments
517 * @buf: input buffer
518 * @fmt: format of buffer
519 * @args: arguments
520 */
521 int vsscanf(const char * buf, const char * fmt, va_list args)
522 {
523 const char *str = buf;
524 const char *next;
525 char digit;
526 int num = 0;
527 int qualifier;
528 int base;
529 int field_width;
530 int is_sign = 0;
532 while (*fmt && *str) {
533 /* skip any white space in format */
534 /* white space in format matchs any amount of
535 * white space, including none, in the input.
536 */
537 if (isspace(*fmt)) {
538 while (isspace(*fmt))
539 ++fmt;
540 while (isspace(*str))
541 ++str;
542 }
544 /* anything that is not a conversion must match exactly */
545 if (*fmt != '%' && *fmt) {
546 if (*fmt++ != *str++)
547 break;
548 continue;
549 }
551 if (!*fmt)
552 break;
553 ++fmt;
555 /* skip this conversion.
556 * advance both strings to next white space
557 */
558 if (*fmt == '*') {
559 while (!isspace(*fmt) && *fmt)
560 fmt++;
561 while (!isspace(*str) && *str)
562 str++;
563 continue;
564 }
566 /* get field width */
567 field_width = -1;
568 if (isdigit(*fmt))
569 field_width = skip_atoi(&fmt);
571 /* get conversion qualifier */
572 qualifier = -1;
573 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z'
574 || *fmt == 'z') {
575 qualifier = *fmt++;
576 if (unlikely(qualifier == *fmt)) {
577 if (qualifier == 'h') {
578 qualifier = 'H';
579 fmt++;
580 } else if (qualifier == 'l') {
581 qualifier = 'L';
582 fmt++;
583 }
584 }
585 }
586 base = 10;
587 is_sign = 0;
589 if (!*fmt || !*str)
590 break;
592 switch(*fmt++) {
593 case 'c': {
594 char *s = (char *) va_arg(args,char*);
595 if (field_width == -1)
596 field_width = 1;
597 do {
598 *s++ = *str++;
599 } while (--field_width > 0 && *str);
600 num++;
601 }
602 continue;
603 case 's': {
604 char *s = (char *) va_arg(args, char *);
605 if(field_width == -1)
606 field_width = INT_MAX;
607 /* first, skip leading white space in buffer */
608 while (isspace(*str))
609 str++;
611 /* now copy until next white space */
612 while (*str && !isspace(*str) && field_width--)
613 *s++ = *str++;
614 *s = '\0';
615 num++;
616 }
617 continue;
618 case 'n': {
619 /* return number of characters read so far */
620 int *i = (int *)va_arg(args,int*);
621 *i = str - buf;
622 }
623 continue;
624 case 'o':
625 base = 8;
626 break;
627 case 'x':
628 case 'X':
629 base = 16;
630 break;
631 case 'i':
632 base = 0;
633 case 'd':
634 is_sign = 1;
635 case 'u':
636 break;
637 case '%':
638 /* looking for '%' in str */
639 if (*str++ != '%')
640 return num;
641 continue;
642 default:
643 /* invalid format; stop here */
644 return num;
645 }
647 /* have some sort of integer conversion.
648 * first, skip white space in buffer.
649 */
650 while (isspace(*str))
651 str++;
653 digit = *str;
654 if (is_sign && digit == '-')
655 digit = *(str + 1);
657 if (!digit || (base == 16 && !isxdigit(digit))
658 || (base == 10 && !isdigit(digit))
659 || (base == 8 && (!isdigit(digit) || digit > '7'))
660 || (base == 0 && !isdigit(digit)))
661 break;
663 switch(qualifier) {
664 case 'H': /* that's 'hh' in format */
665 if (is_sign) {
666 signed char *s = (signed char *) va_arg(args,signed char *);
667 *s = (signed char) simple_strtol(str,&next,base);
668 } else {
669 unsigned char *s = (unsigned char *)
670 va_arg(args, unsigned char *);
671 *s = (unsigned char) simple_strtoul(str, &next, base);
672 }
673 break;
674 case 'h':
675 if (is_sign) {
676 short *s = (short *) va_arg(args,short *);
677 *s = (short) simple_strtol(str,&next,base);
678 } else {
679 unsigned short *s = (unsigned short *)
680 va_arg(args, unsigned short *);
681 *s = (unsigned short) simple_strtoul(str, &next, base);
682 }
683 break;
684 case 'l':
685 if (is_sign) {
686 long *l = (long *) va_arg(args,long *);
687 *l = simple_strtol(str,&next,base);
688 } else {
689 unsigned long *l = (unsigned long*)
690 va_arg(args,unsigned long*);
691 *l = simple_strtoul(str,&next,base);
692 }
693 break;
694 case 'L':
695 if (is_sign) {
696 long long *l = (long long*) va_arg(args,long long *);
697 *l = simple_strtoll(str,&next,base);
698 } else {
699 unsigned long long *l = (unsigned long long*)
700 va_arg(args,unsigned long long*);
701 *l = simple_strtoull(str,&next,base);
702 }
703 break;
704 case 'Z':
705 case 'z': {
706 size_t *s = (size_t*) va_arg(args,size_t*);
707 *s = (size_t) simple_strtoul(str,&next,base);
708 }
709 break;
710 default:
711 if (is_sign) {
712 int *i = (int *) va_arg(args, int*);
713 *i = (int) simple_strtol(str,&next,base);
714 } else {
715 unsigned int *i = (unsigned int*)
716 va_arg(args, unsigned int*);
717 *i = (unsigned int) simple_strtoul(str,&next,base);
718 }
719 break;
720 }
721 num++;
723 if (!next)
724 break;
725 str = next;
726 }
727 return num;
728 }
730 EXPORT_SYMBOL(vsscanf);
732 /**
733 * snprintf - Format a string and place it in a buffer
734 * @buf: The buffer to place the result into
735 * @size: The size of the buffer, including the trailing null space
736 * @fmt: The format string to use
737 * @...: Arguments for the format string
738 *
739 * The return value is the number of characters which would be
740 * generated for the given input, excluding the trailing null,
741 * as per ISO C99. If the return is greater than or equal to
742 * @size, the resulting string is truncated.
743 */
744 int snprintf(char * buf, size_t size, const char *fmt, ...)
745 {
746 va_list args;
747 int i;
749 va_start(args, fmt);
750 i=vsnprintf(buf,size,fmt,args);
751 va_end(args);
752 return i;
753 }
755 EXPORT_SYMBOL(snprintf);
757 /**
758 * scnprintf - Format a string and place it in a buffer
759 * @buf: The buffer to place the result into
760 * @size: The size of the buffer, including the trailing null space
761 * @fmt: The format string to use
762 * @...: Arguments for the format string
763 *
764 * The return value is the number of characters written into @buf not including
765 * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is
766 * greater than or equal to @size, the resulting string is truncated.
767 */
769 int scnprintf(char * buf, size_t size, const char *fmt, ...)
770 {
771 va_list args;
772 int i;
774 va_start(args, fmt);
775 i = vsnprintf(buf, size, fmt, args);
776 va_end(args);
777 if (i >= size)
778 i = size - 1;
779 return (i > 0) ? i : 0;
780 }
781 EXPORT_SYMBOL(scnprintf);
783 /**
784 * sscanf - Unformat a buffer into a list of arguments
785 * @buf: input buffer
786 * @fmt: formatting of buffer
787 * @...: resulting arguments
788 */
789 int sscanf(const char * buf, const char * fmt, ...)
790 {
791 va_list args;
792 int i;
794 va_start(args,fmt);
795 i = vsscanf(buf,fmt,args);
796 va_end(args);
797 return i;
798 }
800 EXPORT_SYMBOL(sscanf);
802 /*
803 * Local variables:
804 * mode: C
805 * c-set-style: "BSD"
806 * c-basic-offset: 4
807 * tab-width: 4
808 * indent-tabs-mode: nil
809 * End:
810 */