Bug 1517433 - do not assert on over-long float printf; r=froydnj

mozilla::PrintfTarget::cvt_f release asserts that the desired printf
fit into a statically-sized buffer.  However, this may not be the case
if the user requested a larger width or precision.  Handle this
unusual case by allocating a temporary buffer.

MozReview-Commit-ID: 2WicecHDzDR

Differential Revision: https://phabricator.services.mozilla.com/D15989

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Tom Tromey 2019-01-09 15:50:27 +00:00
Родитель e4a445730d
Коммит 18e18bcdb3
2 изменённых файлов: 26 добавлений и 2 удалений

Просмотреть файл

@ -11,6 +11,7 @@
*/
#include "mozilla/AllocPolicy.h"
#include "mozilla/Likely.h"
#include "mozilla/Printf.h"
#include "mozilla/Sprintf.h"
#include "mozilla/UniquePtrExtensions.h"
@ -258,9 +259,27 @@ bool mozilla::PrintfTarget::cvt_f(double d, const char* fmt0,
}
#endif
size_t len = SprintfLiteral(fout, fin, d);
MOZ_RELEASE_ASSERT(len <= sizeof(fout));
// Note that SprintfLiteral will always write a \0 at the end, so a
// "<=" check here would be incorrect -- the buffer size passed to
// snprintf includes the trailing \0, but the returned length does
// not.
if (MOZ_LIKELY(len < sizeof(fout))) {
return emit(fout, len);
}
return emit(fout, len);
// Maybe the user used "%500.500f" or something like that.
size_t buf_size = len + 1;
UniqueFreePtr<char> buf((char*)malloc(buf_size));
if (!buf) {
return false;
}
len = snprintf(buf.get(), buf_size, fin, d);
// If this assert fails, then SprintfLiteral has a bug -- and in
// this case we would like to learn of it, which is why there is a
// release assert.
MOZ_RELEASE_ASSERT(len < buf_size);
return emit(buf.get(), len);
}
/*

Просмотреть файл

@ -122,6 +122,11 @@ static void TestPrintfFormats() {
// failure caused by printing a very long floating point value.
print_one("ignore", "%lf", DBL_MAX);
// Regression test for bug#1517433. The bug was an assertion
// failure caused by printing a floating point value with a large
// precision and/or width.
print_one("ignore", "%500.500lf", DBL_MAX);
MOZ_RELEASE_ASSERT(print_one("2727", "%" PRIu32, (uint32_t)2727));
MOZ_RELEASE_ASSERT(print_one("aa7", "%" PRIx32, (uint32_t)2727));
MOZ_RELEASE_ASSERT(print_one("2727", "%" PRIu64, (uint64_t)2727));