mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 15:01:29 +00:00
Don't allow OS::SNPrint or OS::VSNPrint to return negative values.
If we encounter conditions that would have caused vsnprintf to return a negative value, then something pretty wild is going on. We choose to terminate the vm when this occurs. This fixes security bug 1745. Review URL: https://chromiumcodereview.appspot.com//10696165 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@9558 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
1ae72fbd8b
commit
9cbae35238
|
@ -5,6 +5,9 @@
|
|||
# When a spawned isolate throws an uncaught exception, we terminate the vm.
|
||||
cc/RunLoop_ExceptionChild: Fail
|
||||
|
||||
# This test is expected to crash on all platforms.
|
||||
cc/SNPrint_BadArgs: Crash
|
||||
|
||||
[ $arch == x64 ]
|
||||
cc/IsolateInterrupt: Skip
|
||||
|
||||
|
|
|
@ -62,16 +62,21 @@ class OS {
|
|||
static void PrintErr(const char* format, ...);
|
||||
static void VFPrint(FILE* stream, const char* format, va_list args);
|
||||
// Print formatted output info a buffer.
|
||||
//
|
||||
// Does not write more than size characters (including the trailing '\0').
|
||||
// Returns the number of characters (excluding the trailing '\0') that would
|
||||
// been written if the buffer had been big enough.
|
||||
// If the return value is greater or equal than the given size then the output
|
||||
// has been truncated.
|
||||
// The buffer will always be terminated by a '\0', unless the buffer is of
|
||||
// size 0.
|
||||
// The buffer might be NULL if the size is 0.
|
||||
// This specification conforms to C99 standard which is implemented by
|
||||
// glibc 2.1+.
|
||||
//
|
||||
// Returns the number of characters (excluding the trailing '\0')
|
||||
// that would been written if the buffer had been big enough. If
|
||||
// the return value is greater or equal than the given size then the
|
||||
// output has been truncated. The return value is never negative.
|
||||
//
|
||||
// The buffer will always be terminated by a '\0', unless the buffer
|
||||
// is of size 0. The buffer might be NULL if the size is 0.
|
||||
//
|
||||
// This specification conforms to C99 standard which is implemented
|
||||
// by glibc 2.1+ with one exception: the C99 standard allows a
|
||||
// negative return value. We will terminate the vm rather than let
|
||||
// that occur.
|
||||
static int SNPrint(char* str, size_t size, const char* format, ...);
|
||||
static int VSNPrint(char* str, size_t size,
|
||||
const char* format,
|
||||
|
|
|
@ -153,7 +153,11 @@ int OS::SNPrint(char* str, size_t size, const char* format, ...) {
|
|||
|
||||
|
||||
int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) {
|
||||
return vsnprintf(str, size, format, args);
|
||||
int retval = vsnprintf(str, size, format, args);
|
||||
if (retval < 0) {
|
||||
FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -128,7 +128,11 @@ int OS::SNPrint(char* str, size_t size, const char* format, ...) {
|
|||
|
||||
|
||||
int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) {
|
||||
return vsnprintf(str, size, format, args);
|
||||
int retval = vsnprintf(str, size, format, args);
|
||||
if (retval < 0) {
|
||||
FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,6 +38,14 @@ UNIT_TEST_CASE(SNPrint) {
|
|||
}
|
||||
|
||||
|
||||
// This test is expected to crash when it runs.
|
||||
UNIT_TEST_CASE(SNPrint_BadArgs) {
|
||||
int width = kMaxInt32;
|
||||
int num = 7;
|
||||
OS::SNPrint(NULL, 0, "%*d%*d", width, num, width, num);
|
||||
}
|
||||
|
||||
|
||||
UNIT_TEST_CASE(OsFuncs) {
|
||||
EXPECT(Utils::IsPowerOfTwo(OS::ActivationFrameAlignment()));
|
||||
EXPECT(Utils::IsPowerOfTwo(OS::PreferredCodeAlignment()));
|
||||
|
|
|
@ -155,7 +155,11 @@ int OS::SNPrint(char* str, size_t size, const char* format, ...) {
|
|||
|
||||
int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) {
|
||||
if (str == NULL || size == 0) {
|
||||
return _vscprintf(format, args);
|
||||
int retval = _vscprintf(format, args);
|
||||
if (retval < 0) {
|
||||
FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
|
@ -168,6 +172,9 @@ int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) {
|
|||
va_list args_retry;
|
||||
va_copy(args_retry, args);
|
||||
written = _vscprintf(format, args_retry);
|
||||
if (written < 0) {
|
||||
FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
|
||||
}
|
||||
va_end(args_retry);
|
||||
}
|
||||
// Make sure to zero-terminate the string if the output was
|
||||
|
|
Loading…
Reference in a new issue