util/u_printf: properly handle %%

Cc: mesa-stable
Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29776>
(cherry picked from commit d51a14aab8)
This commit is contained in:
Karol Herbst 2024-06-18 23:46:53 +02:00 committed by Eric Engestrom
parent 6e61244d0f
commit ce2f8fa7b2
3 changed files with 43 additions and 7 deletions

View file

@ -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

View file

@ -217,5 +217,5 @@ TEST_F(u_printf_test, util_printf_mixed_multiple)
add_arg<float>(3.0);
add_arg<float, 4>(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 ");
}

View file

@ -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);
}
}