diff options
author | Elliott Hughes <enh@google.com> | 2016-08-10 11:07:54 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2016-08-10 11:50:12 -0700 |
commit | fb3873d4db3012ac2d1ba87d688138798787c6e0 (patch) | |
tree | 1e392110ebe5ca3b0f3f466e493c1085b403b864 /libc/stdio/stdio.cpp | |
parent | f5042cab109f7136191fd316be1471532d2ddf71 (diff) |
Fortify vsnprintf in more cases.
Bug: http://b/30445072
Change-Id: I1893890f0e3b56533eef053eda1bd96a0b9a5119
Diffstat (limited to 'libc/stdio/stdio.cpp')
-rw-r--r-- | libc/stdio/stdio.cpp | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp index c6736118e..b709b40c8 100644 --- a/libc/stdio/stdio.cpp +++ b/libc/stdio/stdio.cpp @@ -46,6 +46,7 @@ #include "local.h" #include "glue.h" +#include "private/bionic_fortify.h" #include "private/ErrnoRestorer.h" #include "private/thread_private.h" @@ -779,7 +780,7 @@ int snprintf(char* s, size_t n, const char* fmt, ...) { } int sprintf(char* s, const char* fmt, ...) { - PRINTF_IMPL(vsnprintf(s, INT_MAX, fmt, ap)); + PRINTF_IMPL(vsprintf(s, fmt, ap)); } int sscanf(const char* s, const char* fmt, ...) { @@ -802,8 +803,34 @@ int vscanf(const char* fmt, va_list ap) { return vfscanf(stdin, fmt, ap); } +int vsnprintf(char* s, size_t n, const char* fmt, va_list ap) { + // stdio internals use int rather than size_t. + static_assert(INT_MAX <= SSIZE_MAX, "SSIZE_MAX too large to fit in int"); + + __check_count("vsnprintf", "size", n); + + // Stdio internals do not deal correctly with zero length buffer. + char dummy; + if (n == 0) { + s = &dummy; + n = 1; + } + + FILE f; + __sfileext fext; + _FILEEXT_SETUP(&f, &fext); + f._file = -1; + f._flags = __SWR | __SSTR; + f._bf._base = f._p = reinterpret_cast<unsigned char*>(s); + f._bf._size = f._w = n - 1; + + int result = __vfprintf(&f, fmt, ap); + *f._p = '\0'; + return result; +} + int vsprintf(char* s, const char* fmt, va_list ap) { - return vsnprintf(s, INT_MAX, fmt, ap); + return vsnprintf(s, SSIZE_MAX, fmt, ap); } int vwprintf(const wchar_t* fmt, va_list ap) { |