diff options
author | Orlando Arbildo <oarbildo@google.com> | 2022-08-09 22:24:27 +0000 |
---|---|---|
committer | Orlando Arbildo <oarbildo@google.com> | 2022-09-08 19:58:36 +0000 |
commit | 7ac8b7983f78a8d511f527f5f78e3a5f9593b719 (patch) | |
tree | 20c3666846dbb74cf34eed4fd8e3517a47be2a4a /lib | |
parent | c5edec8b78f992781e456a21d5e610ea6dce4e85 (diff) | |
download | common-7ac8b7983f78a8d511f527f5f78e3a5f9593b719.tar.gz |
[lib][libc] Improving log filtering capabilities
Adding modifiers to override filtering. We are using the same modifier
used by printk in the linux kernel to override filtering of pointers
(%px), and extending it to also %dx, %ux and %xx.
We are also removing the override of RELEASE_BUILD on code because
this is now taken care on test build makefiles.
Bug: 234061145
Test: Added host unit tests for both test-debug and release like builds.
Change-Id: I120cd7ef6664ec02ec02c2324cfa9bac3445e6a6
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/printf.c | 49 | ||||
-rw-r--r-- | lib/libc/test_common/libc_printf_tests.cpp | 129 |
2 files changed, 170 insertions, 8 deletions
diff --git a/lib/libc/printf.c b/lib/libc/printf.c index 0ac64798..9723196e 100644 --- a/lib/libc/printf.c +++ b/lib/libc/printf.c @@ -28,14 +28,6 @@ #include <stdio.h> #include <string.h> -/* -* We are overriding the RELEASE_BUILD behavior on this file to always disable filtering on test builds. -*/ -#if TEST_BUILD -#undef RELEASE_BUILD -#define RELEASE_BUILD 0 -#endif - #ifdef UTEST_BUILD #include "test_includes/printf_test.h" #endif @@ -467,6 +459,44 @@ __NO_INLINE static char *double_to_hexstring(char *buf, size_t len, double d, ui #endif // FLOAT_PRINTF +/* Currently only doing a 1 char lookahead for the modifiers*/ +static void parse_extra_modifiers(const char **format_string, int *flags, bool use_filter_modifiers) +{ + char currChar; + + /* Because this function is called only when we are parsing + * and actual format specifier, this value will either point + * to the printable string or at most to the NULL terminator. + */ + currChar = **format_string; + if (currChar == 0) { + return; + } + /* This is a not filtered call, we should not "eat" the extra x.*/ + if (!use_filter_modifiers) { + return; + } + switch(currChar) { + case 'x': + /* Found an x modifier; we really want to print this value.*/ + *flags &= ~FILTERED_ON_RELEASE; + /* We are consuming this character, advance format string. + * Advancing is safe because the current character is a + * printable one, so worst case we will advance to the end + * of the string and the original algorithm was prepared to + * handling advancing to end of string before starting to + * parse. + */ + (*format_string)++; + break; + default: + /* We didn't understood the next character, + * normal parsing code will take care of it + */ + break; + } +} + static int _printf_engine_internal(_printf_engine_output_func out, void *state, const char *fmt, va_list ap, bool filtered) { int err = 0; @@ -582,6 +612,7 @@ next_format: (flags & PTRDIFFFLAG) ? va_arg(ap, ptrdiff_t) : va_arg(ap, int)); flags |= SIGNEDFLAG; + parse_extra_modifiers(&fmt, &flags, filtered); s = longlong_to_string(num_buffer, n, sizeof(num_buffer), flags, &signchar); goto _output_string; case 'u': @@ -593,6 +624,7 @@ next_format: (flags & INTMAXFLAG) ? va_arg(ap, uintmax_t) : (flags & PTRDIFFFLAG) ? (uintptr_t)va_arg(ap, ptrdiff_t) : va_arg(ap, unsigned int)); + parse_extra_modifiers(&fmt, &flags, filtered); s = longlong_to_string(num_buffer, n, sizeof(num_buffer), flags, &signchar); goto _output_string; case 'p': @@ -611,6 +643,7 @@ hex: (flags & INTMAXFLAG) ? va_arg(ap, uintmax_t) : (flags & PTRDIFFFLAG) ? (uintptr_t)va_arg(ap, ptrdiff_t) : va_arg(ap, unsigned int); + parse_extra_modifiers(&fmt, &flags, filtered); s = longlong_to_hexstring(num_buffer, n, sizeof(num_buffer), flags); if (flags & ALTFLAG) { OUTPUT_CHAR('0'); diff --git a/lib/libc/test_common/libc_printf_tests.cpp b/lib/libc/test_common/libc_printf_tests.cpp index fc6fb1d7..9debbe01 100644 --- a/lib/libc/test_common/libc_printf_tests.cpp +++ b/lib/libc/test_common/libc_printf_tests.cpp @@ -211,3 +211,132 @@ TEST(PrintfTest, SmallHexTest) { snprintf_filtered(buffer, BUFFER_SIZE, "unsigned integer: 0x%x", 0x1000); EXPECT_STREQ(buffer, "unsigned integer: 0x1000"); } + +TEST(PrintfTest, PointerUnsignedOneLineFilterOne) { + char buffer[BUFFER_SIZE]; + + snprintf_filtered(buffer, BUFFER_SIZE, "pointer1: %px number: %u", 0x5000, 10000); + EXPECT_STREQ_COND(buffer, "pointer1: 0x5000 number: ***", "pointer1: 0x5000 number: 10000", RELEASE_BUILD); +} + +TEST(PrintfTest, PointerUnsignedOneLineFilterOneInverse) { + char buffer[BUFFER_SIZE]; + + snprintf_filtered(buffer, BUFFER_SIZE, "pointer1: %p number: %ux", 0x5000, 10000); + EXPECT_STREQ_COND(buffer, "pointer1: 0x*** number: 10000", "pointer1: 0x5000 number: 10000", RELEASE_BUILD); +} + +TEST(PrintfTest, PointerUnsignedHexOneLineFilterOne) { + char buffer[BUFFER_SIZE]; + + snprintf_filtered(buffer, BUFFER_SIZE, "pointer1: %px number: %u hex: %xx", 0x5000, 10000, 0X7000); + EXPECT_STREQ_COND(buffer, "pointer1: 0x5000 number: *** hex: 7000", "pointer1: 0x5000 number: 10000 hex: 7000", RELEASE_BUILD); +} + +TEST(PrintfTest, PointerUnsignedHexOneLineFilterOneInverse) { + char buffer[BUFFER_SIZE]; + + snprintf_filtered(buffer, BUFFER_SIZE, "pointer1: %p number: %ux hex: %x", 0x5000, 10000, 0X7000); + EXPECT_STREQ_COND(buffer, "pointer1: 0x*** number: 10000 hex: ***", "pointer1: 0x5000 number: 10000 hex: 7000", RELEASE_BUILD); +} + +TEST(PrintfTest, ReleaseUnfilteredPointerPrintTest) { + char buffer[BUFFER_SIZE]; + + snprintf_filtered(buffer, BUFFER_SIZE, "pointer: %px", (void*)0x5000); + EXPECT_STREQ(buffer, "pointer: 0x5000"); +} + +TEST(PrintfTest, ReleaseUnfilteredLargNegIntTest) { + char buffer[BUFFER_SIZE]; + + snprintf_filtered(buffer, BUFFER_SIZE, "integer: %dx", -4097); + EXPECT_STREQ(buffer, "integer: -4097"); +} + +TEST(PrintfTest, ReleaseUnfilteredLargerHexTest) { + char buffer[BUFFER_SIZE]; + + snprintf_filtered(buffer, BUFFER_SIZE, "unsigned integer: 0x%xx", 0x1001); + EXPECT_STREQ(buffer, "unsigned integer: 0x1001"); +} + +TEST(PrintfTest, ReleaseUnfilteredLargerUintTest) { + char buffer[BUFFER_SIZE]; + + snprintf_filtered(buffer, BUFFER_SIZE, "unsigned integer: %ux", 4097); + EXPECT_STREQ(buffer, "unsigned integer: 4097"); +} + +TEST(PrintfTest, ReleaseUnfilteredLargerUintXAtEndTest) { + char buffer[BUFFER_SIZE]; + + snprintf_filtered(buffer, BUFFER_SIZE, "unsigned integer: %uxx", 34127); + EXPECT_STREQ(buffer, "unsigned integer: 34127x"); +} + +TEST(PrintfTest, ReleaseUnfilteredPrintfBufferLargeEnoughTest) { + char buffer[BUFFER_SIZE]; + memset(buffer, 0, BUFFER_SIZE); + buffer[5] = '@'; + + snprintf_filtered(buffer, 5, "%xx", 0x3000); + EXPECT_STREQ(buffer, "3000"); + EXPECT_EQ(buffer[5], '@'); +} + +TEST(PrintfTest, ReleaseUnfilteredPrintfBufferLargeEnoughForReleaseTest) { + char buffer[BUFFER_SIZE]; + memset(buffer, 0, BUFFER_SIZE); + buffer[4] = '@'; + + snprintf_filtered(buffer, 4, "%xx", 0x3000); + EXPECT_STREQ(buffer,"300"); + EXPECT_EQ(buffer[4], '@'); +} + +TEST(PrintfTest, ReleaseUnfilteredPrintfBufferTooSmallForReleaseTest) { + char buffer[BUFFER_SIZE]; + memset(buffer, 0, BUFFER_SIZE); + buffer[3] = '@'; + + snprintf_filtered(buffer, 3, "%xx", 0x3000); + EXPECT_STREQ(buffer, "30"); + EXPECT_EQ(buffer[3], '@'); +} + +TEST(PrintfTest, ReleaseUnfilteredPrintfStringXPrintsTest) { + char buffer[BUFFER_SIZE]; + + snprintf_filtered(buffer, BUFFER_SIZE, "%sx", "hello"); + EXPECT_STREQ(buffer, "hellox"); +} + +TEST(PrintfTest, ThreeModifierTogetherOneNotFilteredTest) { + char buffer[BUFFER_SIZE]; + + snprintf_filtered(buffer, BUFFER_SIZE, "%d%xx%u", 98765, 0x43210, 123456); + EXPECT_STREQ_COND(buffer, "***43210***", "9876543210123456", RELEASE_BUILD); +} + +TEST(PrintfTest, ThreeModifierTogetherOneNotFilteredInverseTest) { + char buffer[BUFFER_SIZE]; + + snprintf_filtered(buffer, BUFFER_SIZE, "%dx%x%ux", 98765, 0x43210, 123456); + EXPECT_STREQ_COND(buffer, "98765***123456", "9876543210123456", RELEASE_BUILD); +} + +TEST(PrintfTest, ReleaseUnfilteredThreeModifiersTest) { + char buffer[BUFFER_SIZE]; + + snprintf_filtered(buffer, BUFFER_SIZE, "pointer: %px unsigned: %ux signed: %dx", (void*)0x5000, 7000, 80000); + EXPECT_STREQ(buffer, "pointer: 0x5000 unsigned: 7000 signed: 80000"); +} + +TEST(PrintfTest, SnprintfModifierNotUsedTest) { + char buffer[BUFFER_SIZE]; + + snprintf(buffer, BUFFER_SIZE, "hex: %xx pointer: %px unsigned: %ux signed: %dx", 2, (void*) 3, 4, 5); + + EXPECT_STREQ(buffer, "hex: 2x pointer: 0x3x unsigned: 4x signed: 5x"); +} |