From ce2f8fa7b2f97bf260ff8e8ccbd52d619e22a8ab Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 18 Jun 2024 23:46:53 +0200 Subject: [PATCH] util/u_printf: properly handle %% Cc: mesa-stable Reviewed-by: Jesse Natalie Part-of: (cherry picked from commit d51a14aab8724d0b5b6e11fb92747f04042d63e1) --- .pick_status.json | 2 +- src/util/tests/u_printf_test.cpp | 2 +- src/util/u_printf.c | 46 ++++++++++++++++++++++++++++---- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index ed0b4da9d8e..4e001133a83 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -34,7 +34,7 @@ "description": "util/u_printf: properly handle %%", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null, "notes": null diff --git a/src/util/tests/u_printf_test.cpp b/src/util/tests/u_printf_test.cpp index fe689958fa2..91b29c1fe7c 100644 --- a/src/util/tests/u_printf_test.cpp +++ b/src/util/tests/u_printf_test.cpp @@ -217,5 +217,5 @@ TEST_F(u_printf_test, util_printf_mixed_multiple) add_arg(3.0); add_arg(floats); - EXPECT_EQ(parse(), "ABCED\n-5 6\n%%%%mesa 10 3.000000 1.0,2.0,3.0,4.0 "); + EXPECT_EQ(parse(), "ABCED\n-5 6\n%%mesa 10 3.000000 1.0,2.0,3.0,4.0 "); } diff --git a/src/util/u_printf.c b/src/util/u_printf.c index ef4837b9ff4..09c4b98071b 100644 --- a/src/util/u_printf.c +++ b/src/util/u_printf.c @@ -99,6 +99,42 @@ size_t u_printf_length(const char *fmt, va_list untouched_args) return size; } +/** + * Used to print plain format strings without arguments as some post-processing + * will be required: + * - %% needs to be printed as % + */ +static void +u_printf_plain_sized(FILE *out, const char* format, size_t len) +{ + bool found = false; + size_t last = 0; + + for (size_t i = 0; i < len; i++) { + if (!found && format[i] == '%') { + found = true; + } else if (found && format[i] == '%') { + /* print one character less so we only print a single % */ + fwrite(format + last, i - last - 1, 1, out); + + last = i; + found = false; + } else { + /* We should never end up here with an actual format token */ + assert(!found); + found = false; + } + } + + fwrite(format + last, len - last, 1, out); +} + +static void +u_printf_plain(FILE *out, const char* format) +{ + u_printf_plain_sized(out, format, strlen(format)); +} + static void u_printf_impl(FILE *out, const char *buffer, size_t buffer_size, const u_printf_info *info, @@ -122,7 +158,7 @@ u_printf_impl(FILE *out, const char *buffer, size_t buffer_size, buf_pos += sizeof(fmt_idx); if (!fmt->num_args) { - fprintf(out, "%s", format); + u_printf_plain(out, format); continue; } @@ -131,7 +167,7 @@ u_printf_impl(FILE *out, const char *buffer, size_t buffer_size, size_t spec_pos = util_printf_next_spec_pos(format, 0); if (spec_pos == -1) { - fprintf(out, "%s", format); + u_printf_plain(out, format); continue; } @@ -140,13 +176,13 @@ u_printf_impl(FILE *out, const char *buffer, size_t buffer_size, /* print the part before the format token */ if (token != format) - fwrite(format, token - format, 1, out); + u_printf_plain_sized(out, format, token - format); char *print_str = strndup(token, next_format - token); /* rebase spec_pos so we can use it with print_str */ spec_pos += format - token; - /* print the formated part */ + /* print the formatted part */ if (print_str[spec_pos] == 's') { uint64_t idx; memcpy(&idx, &buffer[buf_pos], 8); @@ -233,7 +269,7 @@ u_printf_impl(FILE *out, const char *buffer, size_t buffer_size, } /* print remaining */ - fprintf(out, "%s", format); + u_printf_plain(out, format); } }