diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index fdf65a0d4..380bb2a4f 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2077,37 +2077,36 @@ static const char* ImAtoi(const char* src, TYPE* output) return src; } +// Sanitize format +// - Zero terminate so extra characters after format (e.g. "%f123") don't confuse atof/atoi +// - stb_sprintf.h supports several new modifiers which format numbers in a way that also makes them incompatible atof/atoi. +static void SanitizeFormatString(const char* fmt, char* fmt_out, size_t fmt_out_size) +{ + const char* fmt_end = ImParseFormatFindEnd(fmt); + IM_ASSERT((size_t)(fmt_end - fmt + 1) < fmt_out_size); // Format is too long, let us know if this happens to you! + while (fmt < fmt_end) + { + char c = *(fmt++); + if (c != '\'' && c != '$' && c != '_') // Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '. + *(fmt_out++) = c; + } + *fmt_out = 0; // Zero-terminate +} + template TYPE ImGui::RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, TYPE v) { const char* fmt_start = ImParseFormatFindStart(format); if (fmt_start[0] != '%' || fmt_start[1] == '%') // Don't apply if the value is not visible in the format string return v; + + // Sanitize format + char fmt_sanitized[32]; + SanitizeFormatString(fmt_start, fmt_sanitized, IM_ARRAYSIZE(fmt_sanitized)); + fmt_start = fmt_sanitized; + + // Format value with our rounding, and read back char v_str[64]; - char fmt[32]; - const char* fmt_end = ImParseFormatFindEnd(fmt_start); - IM_ASSERT(fmt_end - fmt_start < IM_ARRAYSIZE(fmt) && "Number format is too long!"); -#ifdef IMGUI_USE_STB_SPRINTF - // stb_sprintf.h supports several new modifiers which format numbers in a way that makes them incompatible with - // ImAtof()/ImAtoi(). Copy format string omitting incompatible modifiers and anything past the end of format specifier. - int fmt_len = 0; - for (int i = 0, end = fmt_end - fmt_start; i < end; i++) - { - char c = fmt_start[i]; - if (c == '\'' || c == '$' || c == '_') // Custom flags provided by stb_sprintf.h - continue; - fmt[fmt_len++] = c; - } - fmt[fmt_len] = 0; - fmt_start = fmt; -#else - // Extra characters after format specifier may confuse ImAtof()/ImAtoi(), therefore copying is performed, excluding anything beyond. - if (*fmt_end != 0) - { - ImStrncpy(fmt, fmt_start, fmt_end - fmt_start + 1); - fmt_start = fmt; - } -#endif ImFormatString(v_str, IM_ARRAYSIZE(v_str), fmt_start, v); const char* p = v_str; while (*p == ' ')