Fortify vsnprintf in more cases.
Bug: http://b/30445072
Change-Id: I1893890f0e3b56533eef053eda1bd96a0b9a5119
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp
index c673611..b709b40 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 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 @@
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) {