aboutsummaryrefslogtreecommitdiffstats
path: root/lib/vsprintf.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-03-09 16:15:04 -0400
committerIngo Molnar <mingo@elte.hu>2009-03-10 08:15:06 -0400
commit39e874f8afbdb3745e2406ce4ecbde9ac4cbaa78 (patch)
tree7803af729748413da864811ebcc7a44cd98bbe52 /lib/vsprintf.c
parentfef20d9c1380f04ba9492d6463148db07b413708 (diff)
vsprintf: fix bug in negative value printing
Sitsofe Wheeler found and bisected that while unifying the vsprintf format decoding in: fef20d9: vsprintf: unify the format decoding layer for its 3 users The sign flag has been dropped out in favour of precise types (ie: LONG/ULONG). But the format helper number() still needs this flag to keep track of the signedness unless it will consider all numbers as unsigned. Also add an explicit cast to int (for %d) while parsing with va_arg() to ensure the highest bit is well extended on the 64 bits number that hosts the value in case of negative values. Reported-Bisected-Tested-by: Sitsofe Wheeler <sitsofe@yahoo.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> LKML-Reference: <20090309201503.GA5010@nowhere> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r--lib/vsprintf.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 25f01578c856..dc1674377009 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -768,7 +768,6 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
768static int format_decode(const char *fmt, struct printf_spec *spec) 768static int format_decode(const char *fmt, struct printf_spec *spec)
769{ 769{
770 const char *start = fmt; 770 const char *start = fmt;
771 bool sign = false;
772 771
773 /* we finished early by reading the field width */ 772 /* we finished early by reading the field width */
774 if (spec->type == FORMAT_TYPE_WITDH) { 773 if (spec->type == FORMAT_TYPE_WITDH) {
@@ -900,7 +899,7 @@ qualifier:
900 899
901 case 'd': 900 case 'd':
902 case 'i': 901 case 'i':
903 sign = true; 902 spec->flags |= SIGN;
904 case 'u': 903 case 'u':
905 break; 904 break;
906 905
@@ -912,7 +911,7 @@ qualifier:
912 if (spec->qualifier == 'L') 911 if (spec->qualifier == 'L')
913 spec->type = FORMAT_TYPE_LONG_LONG; 912 spec->type = FORMAT_TYPE_LONG_LONG;
914 else if (spec->qualifier == 'l') { 913 else if (spec->qualifier == 'l') {
915 if (sign) 914 if (spec->flags & SIGN)
916 spec->type = FORMAT_TYPE_LONG; 915 spec->type = FORMAT_TYPE_LONG;
917 else 916 else
918 spec->type = FORMAT_TYPE_ULONG; 917 spec->type = FORMAT_TYPE_ULONG;
@@ -921,12 +920,12 @@ qualifier:
921 } else if (spec->qualifier == 't') { 920 } else if (spec->qualifier == 't') {
922 spec->type = FORMAT_TYPE_PTRDIFF; 921 spec->type = FORMAT_TYPE_PTRDIFF;
923 } else if (spec->qualifier == 'h') { 922 } else if (spec->qualifier == 'h') {
924 if (sign) 923 if (spec->flags & SIGN)
925 spec->type = FORMAT_TYPE_SHORT; 924 spec->type = FORMAT_TYPE_SHORT;
926 else 925 else
927 spec->type = FORMAT_TYPE_USHORT; 926 spec->type = FORMAT_TYPE_USHORT;
928 } else { 927 } else {
929 if (sign) 928 if (spec->flags & SIGN)
930 spec->type = FORMAT_TYPE_INT; 929 spec->type = FORMAT_TYPE_INT;
931 else 930 else
932 spec->type = FORMAT_TYPE_UINT; 931 spec->type = FORMAT_TYPE_UINT;
@@ -1101,8 +1100,8 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
1101 case FORMAT_TYPE_SHORT: 1100 case FORMAT_TYPE_SHORT:
1102 num = (short) va_arg(args, int); 1101 num = (short) va_arg(args, int);
1103 break; 1102 break;
1104 case FORMAT_TYPE_UINT: 1103 case FORMAT_TYPE_INT:
1105 num = va_arg(args, unsigned int); 1104 num = (int) va_arg(args, int);
1106 break; 1105 break;
1107 default: 1106 default:
1108 num = va_arg(args, unsigned int); 1107 num = va_arg(args, unsigned int);