aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/str.cpp16
1 files changed, 12 insertions, 4 deletions
diff --git a/common/str.cpp b/common/str.cpp
index 4585905d62..c3c19adfe6 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -439,12 +439,20 @@ String String::printf(const char *fmt, ...) {
int len = vsnprintf(output._str, _builtinCapacity, fmt, va);
va_end(va);
- if (len == -1) {
- // MSVC doesn't return the size the full string would take up.
- // Try increasing the size of the string until it fits.
+ if (len == -1 || len == _builtinCapacity - 1) {
+ // MSVC and IRIX don't return the size the full string would take up.
+ // MSVC returns -1, IRIX returns the number of characters actually written,
+ // which is at the most the size of the buffer minus one, as the string is
+ // truncated to fit.
// We assume MSVC failed to output the correct, null-terminated string
// if the return value is either -1 or size.
+ // For IRIX, because we lack a better mechanism, we assume failure
+ // if the return value equals size - 1.
+ // The downside to this is that whenever we try to format a string where the
+ // size is 1 below the built-in capacity, the size is needlessly increased.
+
+ // Try increasing the size of the string until it fits.
int size = _builtinCapacity;
do {
size *= 2;
@@ -455,7 +463,7 @@ String String::printf(const char *fmt, ...) {
va_start(va, fmt);
len = vsnprintf(output._str, size, fmt, va);
va_end(va);
- } while (len == -1 || len >= size);
+ } while (len == -1 || len >= size - 1);
output._size = len;
} else if (len < (int)_builtinCapacity) {
// vsnprintf succeeded