summaryrefslogtreecommitdiff
path: root/stdio-common/vfprintf.c
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@redhat.com>2009-09-29 06:11:59 -0700
committerUlrich Drepper <drepper@redhat.com>2009-09-29 06:11:59 -0700
commit199eb0de8d673fb23aa127721054b4f1803d61f3 (patch)
tree0234b688e8ee6f68ceb310d58753a934eac2a74b /stdio-common/vfprintf.c
parent9d076f21cdf5f7bb2293498ed22330bb02c0a68d (diff)
downloadglibc-199eb0de8d673fb23aa127721054b4f1803d61f3.tar.gz
Check for integer overflows in formatting functions
Diffstat (limited to 'stdio-common/vfprintf.c')
-rw-r--r--stdio-common/vfprintf.c49
1 files changed, 31 insertions, 18 deletions
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index 38ba8ffdcd..6e0e85cd7c 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -1439,23 +1439,29 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
left = 1;
}
- if (width + 32 >= (int) (sizeof (work_buffer)
- / sizeof (work_buffer[0])))
+ if (__builtin_expect (width >= (size_t) -1 / sizeof (CHAR_T) - 32, 0))
+ {
+ __set_errno (ERANGE);
+ done = -1;
+ goto all_done;
+ }
+
+ if (width >= sizeof (work_buffer) / sizeof (work_buffer[0]) - 32)
{
/* We have to use a special buffer. The "32" is just a safe
bet for all the output which is not counted in the width. */
- if (__libc_use_alloca ((width + 32) * sizeof (CHAR_T)))
- workend = ((CHAR_T *) alloca ((width + 32) * sizeof (CHAR_T))
- + (width + 32));
+ size_t needed = ((size_t) width + 32) * sizeof (CHAR_T);
+ if (__libc_use_alloca (needed))
+ workend = (CHAR_T *) alloca (needed) + width + 32;
else
{
- workstart = (CHAR_T *) malloc ((width + 32) * sizeof (CHAR_T));
+ workstart = (CHAR_T *) malloc (needed);
if (workstart == NULL)
{
done = -1;
goto all_done;
}
- workend = workstart + (width + 32);
+ workend = workstart + width + 32;
}
}
}
@@ -1465,22 +1471,29 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
LABEL (width):
width = read_int (&f);
- if (width + 32 >= (int) (sizeof (work_buffer) / sizeof (work_buffer[0])))
+ if (__builtin_expect (width >= (size_t) -1 / sizeof (CHAR_T) - 32, 0))
+ {
+ __set_errno (ERANGE);
+ done = -1;
+ goto all_done;
+ }
+
+ if (width >= sizeof (work_buffer) / sizeof (work_buffer[0]) - 32)
{
/* We have to use a special buffer. The "32" is just a safe
bet for all the output which is not counted in the width. */
- if (__libc_use_alloca ((width + 32) * sizeof (CHAR_T)))
- workend = ((CHAR_T *) alloca ((width + 32) * sizeof (CHAR_T))
- + (width + 32));
+ size_t needed = ((size_t) width + 32) * sizeof (CHAR_T);
+ if (__libc_use_alloca (needed))
+ workend = (CHAR_T *) alloca (needed) + width + 32;
else
{
- workstart = (CHAR_T *) malloc ((width + 32) * sizeof (CHAR_T));
+ workstart = (CHAR_T *) malloc (needed);
if (workstart == NULL)
{
done = -1;
goto all_done;
}
- workend = workstart + (width + 32);
+ workend = workstart + width + 32;
}
}
if (*f == L_('$'))
@@ -1510,18 +1523,18 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
else
prec = 0;
if (prec > width
- && prec + 32 > (int)(sizeof (work_buffer) / sizeof (work_buffer[0])))
+ && prec > sizeof (work_buffer) / sizeof (work_buffer[0]) - 32)
{
- if (__builtin_expect (prec > ~((size_t) 0) / sizeof (CHAR_T) - 31,
- 0))
+ if (__builtin_expect (prec >= (size_t) -1 / sizeof (CHAR_T) - 32, 0))
{
+ __set_errno (ERANGE);
done = -1;
goto all_done;
}
size_t needed = ((size_t) prec + 32) * sizeof (CHAR_T);
if (__libc_use_alloca (needed))
- workend = (((CHAR_T *) alloca (needed)) + ((size_t) prec + 32));
+ workend = (CHAR_T *) alloca (needed) + prec + 32;
else
{
workstart = (CHAR_T *) malloc (needed);
@@ -1530,7 +1543,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
done = -1;
goto all_done;
}
- workend = workstart + ((size_t) prec + 32);
+ workend = workstart + prec + 32;
}
}
JUMP (*f, step2_jumps);