From f5b4e3ce58e075526bb55804620af4b2f6befa01 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 22 Aug 2023 13:50:39 -0700 Subject: [PATCH] Add %b/%B to async-safe logging. Missed this when we added the new C23 binary output to the printf() family. Also fix %X to use "0X" instead of "0x" and add missing tests. Test: used by new LD_SHOW_AUXV functionality Change-Id: I6623b92acec7daf534536697de0f87352a2653ad --- libc/async_safe/async_safe_log.cpp | 13 ++++++++----- tests/async_safe_test.cpp | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/libc/async_safe/async_safe_log.cpp b/libc/async_safe/async_safe_log.cpp index 420560f7b..2bff616cd 100644 --- a/libc/async_safe/async_safe_log.cpp +++ b/libc/async_safe/async_safe_log.cpp @@ -207,10 +207,12 @@ static void format_integer(char* buf, size_t buf_size, uint64_t value, char conv // Decode the conversion specifier. int is_signed = (conversion == 'd' || conversion == 'i' || conversion == 'o'); int base = 10; - if (conversion == 'x' || conversion == 'X') { + if (tolower(conversion) == 'x') { base = 16; } else if (conversion == 'o') { base = 8; + } else if (tolower(conversion) == 'b') { + base = 2; } bool caps = (conversion == 'X'); @@ -360,7 +362,8 @@ static void out_vformat(Out& o, const char* format, va_list args) { format_integer(buffer + 2, sizeof(buffer) - 2, value, 'x'); } else if (c == 'm') { strerror_r(errno, buffer, sizeof(buffer)); - } else if (c == 'd' || c == 'i' || c == 'o' || c == 'u' || c == 'x' || c == 'X') { + } else if (tolower(c) == 'b' || c == 'd' || c == 'i' || c == 'o' || c == 'u' || + tolower(c) == 'x') { /* integers - first read value from stack */ uint64_t value; int is_signed = (c == 'd' || c == 'i' || c == 'o'); @@ -391,10 +394,10 @@ static void out_vformat(Out& o, const char* format, va_list args) { value = static_cast((static_cast(value << shift)) >> shift); } - if (alternate && value != 0 && (c == 'x' || c == 'o')) { - if (c == 'x') { + if (alternate && value != 0 && (tolower(c) == 'x' || c == 'o' || tolower(c) == 'b')) { + if (tolower(c) == 'x' || tolower(c) == 'b') { buffer[0] = '0'; - buffer[1] = 'x'; + buffer[1] = c; format_integer(buffer + 2, sizeof(buffer) - 2, value, c); } else { buffer[0] = '0'; diff --git a/tests/async_safe_test.cpp b/tests/async_safe_test.cpp index dc4db07dc..cc1b59834 100644 --- a/tests/async_safe_test.cpp +++ b/tests/async_safe_test.cpp @@ -45,6 +45,15 @@ TEST(async_safe_log, smoke) { async_safe_format_buffer(buf, sizeof(buf), "aa%scc", "bb"); EXPECT_STREQ("aabbcc", buf); + async_safe_format_buffer(buf, sizeof(buf), "a%bb", 1234); + EXPECT_STREQ("a10011010010b", buf); + + async_safe_format_buffer(buf, sizeof(buf), "a%#bb", 1234); + EXPECT_STREQ("a0b10011010010b", buf); + + async_safe_format_buffer(buf, sizeof(buf), "a%#Bb", 1234); + EXPECT_STREQ("a0B10011010010b", buf); + async_safe_format_buffer(buf, sizeof(buf), "a%cc", 'b'); EXPECT_STREQ("abc", buf); @@ -76,9 +85,15 @@ TEST(async_safe_log, smoke) { async_safe_format_buffer(buf, sizeof(buf), "a%xz", 0x12ab); EXPECT_STREQ("a12abz", buf); + async_safe_format_buffer(buf, sizeof(buf), "a%#xz", 0x12ab); + EXPECT_STREQ("a0x12abz", buf); + async_safe_format_buffer(buf, sizeof(buf), "a%Xz", 0x12ab); EXPECT_STREQ("a12ABz", buf); + async_safe_format_buffer(buf, sizeof(buf), "a%#Xz", 0x12ab); + EXPECT_STREQ("a0X12ABz", buf); + async_safe_format_buffer(buf, sizeof(buf), "a%08xz", 0x123456); EXPECT_STREQ("a00123456z", buf);