aboutsummaryrefslogtreecommitdiffstats
path: root/patches/linux-2.6.16.33/vsnprintf.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/linux-2.6.16.33/vsnprintf.patch')
-rw-r--r--patches/linux-2.6.16.33/vsnprintf.patch211
1 files changed, 211 insertions, 0 deletions
diff --git a/patches/linux-2.6.16.33/vsnprintf.patch b/patches/linux-2.6.16.33/vsnprintf.patch
new file mode 100644
index 0000000000..69a93fa5c5
--- /dev/null
+++ b/patches/linux-2.6.16.33/vsnprintf.patch
@@ -0,0 +1,211 @@
+commit f796937a062c7aeb44cd0e75e1586c8543634a7d
+Author: Jeremy Fitzhardinge <jeremy@xensource.com>
+Date: Sun Jun 25 05:49:17 2006 -0700
+
+ [PATCH] Fix bounds check in vsnprintf, to allow for a 0 size and NULL buffer
+
+ This change allows callers to use a 0-byte buffer and a NULL buffer pointer
+ with vsnprintf, so it can be used to determine how large the resulting
+ formatted string will be.
+
+ Previously the code effectively treated a size of 0 as a size of 4G (on
+ 32-bit systems), with other checks preventing it from actually trying to
+ emit the string - but the terminal \0 would still be written, which would
+ crash if the buffer is NULL.
+
+ This change changes the boundary check so that 'end' points to the putative
+ location of the terminal '\0', which is only written if size > 0.
+
+ vsnprintf still allows the buffer size to be set very large, to allow
+ unbounded buffer sizes (to implement sprintf, etc).
+
+ [akpm@osdl.org: fix long-vs-longlong confusion]
+ Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>
+ Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+ Signed-off-by: Andrew Morton <akpm@osdl.org>
+ Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+
+diff --git a/lib/vsprintf.c b/lib/vsprintf.c
+index b07db5c..f595947 100644
+--- a/lib/vsprintf.c
++++ b/lib/vsprintf.c
+@@ -187,49 +187,49 @@ static char * number(char * buf, char *
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT))) {
+ while(size-->0) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = ' ';
+ ++buf;
+ }
+ }
+ if (sign) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = sign;
+ ++buf;
+ }
+ if (type & SPECIAL) {
+ if (base==8) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = '0';
+ ++buf;
+ } else if (base==16) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = '0';
+ ++buf;
+- if (buf <= end)
++ if (buf < end)
+ *buf = digits[33];
+ ++buf;
+ }
+ }
+ if (!(type & LEFT)) {
+ while (size-- > 0) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = c;
+ ++buf;
+ }
+ }
+ while (i < precision--) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = '0';
+ ++buf;
+ }
+ while (i-- > 0) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = tmp[i];
+ ++buf;
+ }
+ while (size-- > 0) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = ' ';
+ ++buf;
+ }
+@@ -272,7 +272,8 @@ int vsnprintf(char *buf, size_t size, co
+ /* 'z' changed to 'Z' --davidm 1/25/99 */
+ /* 't' added for ptrdiff_t */
+
+- /* Reject out-of-range values early */
++ /* Reject out-of-range values early. Large positive sizes are
++ used for unknown buffer sizes. */
+ if (unlikely((int) size < 0)) {
+ /* There can be only one.. */
+ static int warn = 1;
+@@ -282,16 +283,17 @@ int vsnprintf(char *buf, size_t size, co
+ }
+
+ str = buf;
+- end = buf + size - 1;
++ end = buf + size;
+
+- if (end < buf - 1) {
+- end = ((void *) -1);
+- size = end - buf + 1;
++ /* Make sure end is always >= buf */
++ if (end < buf) {
++ end = ((void *)-1);
++ size = end - buf;
+ }
+
+ for (; *fmt ; ++fmt) {
+ if (*fmt != '%') {
+- if (str <= end)
++ if (str < end)
+ *str = *fmt;
+ ++str;
+ continue;
+@@ -357,17 +359,17 @@ int vsnprintf(char *buf, size_t size, co
+ case 'c':
+ if (!(flags & LEFT)) {
+ while (--field_width > 0) {
+- if (str <= end)
++ if (str < end)
+ *str = ' ';
+ ++str;
+ }
+ }
+ c = (unsigned char) va_arg(args, int);
+- if (str <= end)
++ if (str < end)
+ *str = c;
+ ++str;
+ while (--field_width > 0) {
+- if (str <= end)
++ if (str < end)
+ *str = ' ';
+ ++str;
+ }
+@@ -382,18 +384,18 @@ int vsnprintf(char *buf, size_t size, co
+
+ if (!(flags & LEFT)) {
+ while (len < field_width--) {
+- if (str <= end)
++ if (str < end)
+ *str = ' ';
+ ++str;
+ }
+ }
+ for (i = 0; i < len; ++i) {
+- if (str <= end)
++ if (str < end)
+ *str = *s;
+ ++str; ++s;
+ }
+ while (len < field_width--) {
+- if (str <= end)
++ if (str < end)
+ *str = ' ';
+ ++str;
+ }
+@@ -426,7 +428,7 @@ int vsnprintf(char *buf, size_t size, co
+ continue;
+
+ case '%':
+- if (str <= end)
++ if (str < end)
+ *str = '%';
+ ++str;
+ continue;
+@@ -449,11 +451,11 @@ int vsnprintf(char *buf, size_t size, co
+ break;
+
+ default:
+- if (str <= end)
++ if (str < end)
+ *str = '%';
+ ++str;
+ if (*fmt) {
+- if (str <= end)
++ if (str < end)
+ *str = *fmt;
+ ++str;
+ } else {
+@@ -483,14 +485,13 @@ int vsnprintf(char *buf, size_t size, co
+ str = number(str, end, num, base,
+ field_width, precision, flags);
+ }
+- if (str <= end)
+- *str = '\0';
+- else if (size > 0)
+- /* don't write out a null byte if the buf size is zero */
+- *end = '\0';
+- /* the trailing null byte doesn't count towards the total
+- * ++str;
+- */
++ if (size > 0) {
++ if (str < end)
++ *str = '\0';
++ else
++ *end = '\0';
++ }
++ /* the trailing null byte doesn't count towards the total */
+ return str-buf;
+ }
+