aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorOrlando Arbildo <oarbildo@google.com>2022-06-07 09:38:30 +0000
committerOrlando Arbildo <oarbildo@google.com>2022-06-07 20:39:20 +0000
commitb2652b21384444baf819d20ae7ec001ed335a4e5 (patch)
treec8b52c6943b2e306d94a1c21820bbab86ba9f400 /lib
parentae1884b1f147d3ea7dacd5b3acf81b054575b4e9 (diff)
downloadcommon-b2652b21384444baf819d20ae7ec001ed335a4e5.tar.gz
[lib][libc] Modifying printf to not print address-like values
Modified printf implementation to not print numerical values if the number is > +/-4096 for %x, %u, %d and %p when doing a release build. This change affects printf and fprintf function families. Bug: 218483110 Test: Added host unit tests for both test-debug and release like builds. Change-Id: I95f66393752878f9aa606f9af568cd36787dd660
Diffstat (limited to 'lib')
-rw-r--r--lib/kerneltests-inc.mk2
-rw-r--r--lib/libc/hosttest/rules.mk49
-rw-r--r--lib/libc/hosttest_release/rules.mk49
-rw-r--r--lib/libc/printf.c84
-rw-r--r--lib/libc/test_common/libc_printf_tests.cpp213
-rw-r--r--lib/libc/test_common/test_functions.c82
-rw-r--r--lib/libc/test_includes/printf_test.h37
-rw-r--r--lib/libc/test_includes/printf_test_defs.h32
8 files changed, 531 insertions, 17 deletions
diff --git a/lib/kerneltests-inc.mk b/lib/kerneltests-inc.mk
index e679e797..28a70b9f 100644
--- a/lib/kerneltests-inc.mk
+++ b/lib/kerneltests-inc.mk
@@ -22,4 +22,6 @@
MODULES += \
$(GET_LOCAL_DIR)/binary_search_tree/hosttest \
+ $(GET_LOCAL_DIR)/libc/hosttest \
+ $(GET_LOCAL_DIR)/libc/hosttest_release \
diff --git a/lib/libc/hosttest/rules.mk b/lib/libc/hosttest/rules.mk
new file mode 100644
index 00000000..74fc1a1e
--- /dev/null
+++ b/lib/libc/hosttest/rules.mk
@@ -0,0 +1,49 @@
+#
+# Copyright (c) 2022 LK Trusty Authors. All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+HOST_TEST := libc_printf_test
+
+GTEST_DIR := external/googletest/googletest
+
+HOST_FLAGS += -DUTEST_BUILD -DRELEASE_BUILD=0
+
+HOST_SRCS := \
+ $(LOCAL_DIR)/../test_common/libc_printf_tests.cpp \
+ $(GTEST_DIR)/src/gtest-all.cc \
+ $(GTEST_DIR)/src/gtest_main.cc \
+ $(LOCAL_DIR)/../include/printf.h \
+ $(LOCAL_DIR)/../printf.c \
+ $(LOCAL_DIR)/../test_common/test_functions.c \
+
+HOST_INCLUDE_DIRS := \
+ $(GTEST_DIR)/include \
+ $(GTEST_DIR) \
+ $(LOCAL_DIR)/../test_includes \
+
+HOST_LIBS := \
+ stdc++ \
+ pthread \
+
+include make/host_test.mk
diff --git a/lib/libc/hosttest_release/rules.mk b/lib/libc/hosttest_release/rules.mk
new file mode 100644
index 00000000..0594e408
--- /dev/null
+++ b/lib/libc/hosttest_release/rules.mk
@@ -0,0 +1,49 @@
+#
+# Copyright (c) 2022 LK Trusty Authors. All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+HOST_TEST := libc_printf_release_test
+
+GTEST_DIR := external/googletest/googletest
+
+HOST_FLAGS += -DUTEST_BUILD -DRELEASE_BUILD=1
+
+HOST_SRCS := \
+ $(LOCAL_DIR)/../test_common/libc_printf_tests.cpp \
+ $(GTEST_DIR)/src/gtest-all.cc \
+ $(GTEST_DIR)/src/gtest_main.cc \
+ $(LOCAL_DIR)/../include/printf.h \
+ $(LOCAL_DIR)/../printf.c \
+ $(LOCAL_DIR)/../test_common/test_functions.c \
+
+HOST_INCLUDE_DIRS := \
+ $(GTEST_DIR)/include \
+ $(GTEST_DIR) \
+ $(LOCAL_DIR)/../test_includes \
+
+HOST_LIBS := \
+ stdc++ \
+ pthread \
+
+include make/host_test.mk
diff --git a/lib/libc/printf.c b/lib/libc/printf.c
index d182ceba..82d48af7 100644
--- a/lib/libc/printf.c
+++ b/lib/libc/printf.c
@@ -28,12 +28,26 @@
#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
+
#if WITH_NO_FP
#define FLOAT_PRINTF 0
#else
#define FLOAT_PRINTF 1
#endif
+static int _printf_unfiltered_engine(_printf_engine_output_func out, void *state, const char *fmt, va_list ap);
+
int sprintf(char *str, const char *fmt, ...)
{
int err;
@@ -95,7 +109,7 @@ int vsnprintf(char *str, size_t len, const char *fmt, va_list ap)
args.len = len;
args.pos = 0;
- wlen = _printf_engine(&_vsnprintf_output, (void *)&args, fmt, ap);
+ wlen = _printf_unfiltered_engine(&_vsnprintf_output, (void *)&args, fmt, ap);
if (args.pos >= len)
str[len-1] = '\0';
else
@@ -103,20 +117,21 @@ int vsnprintf(char *str, size_t len, const char *fmt, va_list ap)
return wlen;
}
-#define LONGFLAG 0x00000001
-#define LONGLONGFLAG 0x00000002
-#define HALFFLAG 0x00000004
-#define HALFHALFFLAG 0x00000008
-#define SIZETFLAG 0x00000010
-#define INTMAXFLAG 0x00000020
-#define PTRDIFFFLAG 0x00000040
-#define ALTFLAG 0x00000080
-#define CAPSFLAG 0x00000100
-#define SHOWSIGNFLAG 0x00000200
-#define SIGNEDFLAG 0x00000400
-#define LEFTFORMATFLAG 0x00000800
-#define LEADZEROFLAG 0x00001000
-#define BLANKPOSFLAG 0x00002000
+#define LONGFLAG 0x00000001
+#define LONGLONGFLAG 0x00000002
+#define HALFFLAG 0x00000004
+#define HALFHALFFLAG 0x00000008
+#define SIZETFLAG 0x00000010
+#define INTMAXFLAG 0x00000020
+#define PTRDIFFFLAG 0x00000040
+#define ALTFLAG 0x00000080
+#define CAPSFLAG 0x00000100
+#define SHOWSIGNFLAG 0x00000200
+#define SIGNEDFLAG 0x00000400
+#define LEFTFORMATFLAG 0x00000800
+#define LEADZEROFLAG 0x00001000
+#define BLANKPOSFLAG 0x00002000
+#define FILTERED_ON_RELEASE 0x00004000
__NO_INLINE static char *longlong_to_string(char *buf, unsigned long long n, size_t len, uint flag, char *signchar)
{
@@ -130,6 +145,16 @@ __NO_INLINE static char *longlong_to_string(char *buf, unsigned long long n, siz
}
buf[--pos] = 0;
+#if RELEASE_BUILD
+ if (flag & FILTERED_ON_RELEASE) {
+ if (n > 4096) {
+ buf[--pos] = '*';
+ buf[--pos] = '*';
+ buf[--pos] = '*';
+ return &buf[pos];
+ }
+ }
+#endif
/* only do the math if the number is >= 10 */
while (n >= 10) {
@@ -162,6 +187,17 @@ __NO_INLINE static char *longlong_to_hexstring(char *buf, unsigned long long u,
const char *table = (flag & CAPSFLAG) ? hextable_caps : hextable;
buf[--pos] = 0;
+#if RELEASE_BUILD
+ if (flag & FILTERED_ON_RELEASE) {
+ if ((u > 4096) &&
+ (u < (unsigned long long)(-4096))) {
+ buf[--pos] = '*';
+ buf[--pos] = '*';
+ buf[--pos] = '*';
+ return &buf[pos];
+ }
+ }
+#endif
do {
unsigned int digit = u % 16;
u /= 16;
@@ -402,7 +438,7 @@ __NO_INLINE static char *double_to_hexstring(char *buf, size_t len, double d, ui
#endif // FLOAT_PRINTF
-int _printf_engine(_printf_engine_output_func out, void *state, const char *fmt, va_list ap)
+static int _printf_engine_internal(_printf_engine_output_func out, void *state, const char *fmt, va_list ap, bool filtered)
{
int err = 0;
char c;
@@ -422,7 +458,11 @@ int _printf_engine(_printf_engine_output_func out, void *state, const char *fmt,
for (;;) {
/* reset the format state */
- flags = 0;
+ if (filtered) {
+ flags = FILTERED_ON_RELEASE;
+ } else {
+ flags = 0;
+ }
format_num = 0;
signchar = '\0';
@@ -634,3 +674,13 @@ _output_string:
exit:
return (err < 0) ? err : (int)chars_written;
}
+
+int _printf_engine(_printf_engine_output_func out, void *state, const char *fmt, va_list ap)
+{
+ return _printf_engine_internal(out, state, fmt, ap, true);
+}
+
+static int _printf_unfiltered_engine(_printf_engine_output_func out, void *state, const char *fmt, va_list ap)
+{
+ return _printf_engine_internal(out, state, fmt, ap, false);
+}
diff --git a/lib/libc/test_common/libc_printf_tests.cpp b/lib/libc/test_common/libc_printf_tests.cpp
new file mode 100644
index 00000000..fc6fb1d7
--- /dev/null
+++ b/lib/libc/test_common/libc_printf_tests.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2022 LK Trusty Authors. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <lk/compiler.h>
+#include <stdlib.h>
+
+#include "gtest/gtest.h"
+#include "printf_test_defs.h"
+
+class PrintfTest : public testing::TestWithParam<bool> {
+};
+
+#define BUFFER_SIZE 100
+TEST(PrintfTest, SmallIntegerPrintTest) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "%d", 100);
+ EXPECT_STREQ(buffer, "100");
+}
+
+TEST(PrintfTest, NullPointerPrintTest) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "pointer: %p", (void*)0);
+ EXPECT_STREQ(buffer, "pointer: 0x0");
+}
+
+TEST(PrintfTest, SmallPointerPrintTest) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "pointer: %p", (void*)0x1000);
+ EXPECT_STREQ(buffer, "pointer: 0x1000");
+}
+
+TEST(PrintfTest, SmallPseudoNegativePointerPrintTest) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "pointer: %p", (void*)-4096);
+ EXPECT_STREQ(buffer, "pointer: 0xfffffffffffff000");
+}
+
+
+TEST(PrintfTest, PointerAndUnsignedOneLineOneBigOneSmall) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "pointer1: %p number: %u", 0x5000, 100);
+ EXPECT_STREQ_COND(buffer, "pointer1: 0x*** number: 100", "pointer1: 0x5000 number: 100", RELEASE_BUILD);
+}
+
+TEST(PrintfTest, PointerAndUnsignedOneLineOneBigOneSmallInverse) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "pointer1: %p number: %u", 0x500, 10000);
+ EXPECT_STREQ_COND(buffer, "pointer1: 0x500 number: ***", "pointer1: 0x500 number: 10000", RELEASE_BUILD);
+}
+
+TEST(PrintfTest, OnePointersTwoIntsOneLineOneSmallTwoBig) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "pointer1: %p number: %u hex: %x", 0x5, 10000, 0X70);
+ EXPECT_STREQ_COND(buffer, "pointer1: 0x5 number: *** hex: 70", "pointer1: 0x5 number: 10000 hex: 70", RELEASE_BUILD);
+}
+
+TEST(PrintfTest, OnePointersTwoIntsOneLineOneSmallTwoBigInverse) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "pointer1: %p number: %u hex: %x", 0x5000, 10, 0X7000);
+ EXPECT_STREQ_COND(buffer, "pointer1: 0x*** number: 10 hex: ***", "pointer1: 0x5000 number: 10 hex: 7000", RELEASE_BUILD);
+}
+
+TEST(PrintfTest, BiggerPseudoNegativePointerPrintTest) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "pointer: %p", (void*)-4097);
+ EXPECT_STREQ_COND(buffer, "pointer: 0x***", "pointer: 0xffffffffffffefff", RELEASE_BUILD);
+}
+
+TEST(PrintfTest, PointerAndUnsignedOneLine) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "pointer1: %p number: %u", 0x5000, 10000);
+ EXPECT_STREQ_COND(buffer, "pointer1: 0x*** number: ***", "pointer1: 0x5000 number: 10000", RELEASE_BUILD);
+}
+
+TEST(PrintfTest, SmallestPseudoNegativePointerPrintTest) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "pointer: %p", (void*)-1);
+ EXPECT_STREQ(buffer, "pointer: 0xffffffffffffffff");
+}
+
+TEST(PrintfTest, PointerPrintTest) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "pointer: %p", (void*)0x5000);
+ EXPECT_STREQ_COND(buffer, "pointer: 0x***", "pointer: 0x5000", RELEASE_BUILD);
+}
+
+TEST(PrintfTest, PointerSprintfTest) {
+ char buffer[BUFFER_SIZE];
+
+ sprintf(buffer, "pointer: %p", (void*)0x5000);
+ EXPECT_STREQ(buffer, "pointer: 0x5000");
+}
+
+TEST(PrintfTest, PointerSnprintfTest) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf(buffer, BUFFER_SIZE,"pointer: %p", (void*)0x5000);
+ EXPECT_STREQ(buffer, "pointer: 0x5000");
+}
+
+TEST(PrintfTest, LargerIntTest) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "integer: %d", 4097);
+ EXPECT_STREQ_COND(buffer, "integer: ***", "integer: 4097", RELEASE_BUILD);
+}
+
+TEST(PrintfTest, LargerNegIntTest) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "integer: %d", -4097);
+ EXPECT_STREQ_COND(buffer, "integer: ***", "integer: -4097", RELEASE_BUILD);
+}
+
+TEST(PrintfTest, SmallIntTest) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "integer: %d", 4096);
+ EXPECT_STREQ(buffer, "integer: 4096");
+}
+
+TEST(PrintfTest, SmallNegIntTest) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "integer: %d", -4096);
+ EXPECT_STREQ(buffer, "integer: -4096");
+}
+
+TEST(PrintfTest, LargerUintTest) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "unsigned integer: %u", 4097);
+ EXPECT_STREQ_COND(buffer, "unsigned integer: ***", "unsigned integer: 4097", RELEASE_BUILD);
+}
+
+TEST(PrintfTest, LargerHexTest) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "unsigned integer: 0x%x", 0x1001);
+ EXPECT_STREQ_COND(buffer, "unsigned integer: 0x***", "unsigned integer: 0x1001", RELEASE_BUILD);
+}
+
+TEST(PrintfTest, PrintfBufferLargeEnough) {
+ char buffer[BUFFER_SIZE];
+ memset(buffer, 0, BUFFER_SIZE);
+ buffer[5] = '@';
+
+ snprintf_filtered(buffer, 5, "%x", 0x3000);
+ EXPECT_STREQ_COND(buffer, "***",
+ "3000", RELEASE_BUILD);
+ EXPECT_EQ(buffer[5], '@');
+}
+
+TEST(PrintfTest, PrintfBufferLargeEnoughForRelease) {
+ char buffer[BUFFER_SIZE];
+ memset(buffer, 0, BUFFER_SIZE);
+ buffer[4] = '@';
+
+ snprintf_filtered(buffer, 4, "%x", 0x3000);
+ EXPECT_STREQ_COND(buffer, "***",
+ "300", RELEASE_BUILD);
+ EXPECT_EQ(buffer[4], '@');
+}
+
+TEST(PrintfTest, PrintfBufferTooSmallForRelease) {
+ char buffer[BUFFER_SIZE];
+ memset(buffer, 0, BUFFER_SIZE);
+ buffer[3] = '@';
+
+ snprintf_filtered(buffer, 3, "%x", 0x3000);
+ EXPECT_STREQ_COND(buffer, "**",
+ "30", RELEASE_BUILD);
+ EXPECT_EQ(buffer[3], '@');
+}
+
+TEST(PrintfTest, SmallHexTest) {
+ char buffer[BUFFER_SIZE];
+
+ snprintf_filtered(buffer, BUFFER_SIZE, "unsigned integer: 0x%x", 0x1000);
+ EXPECT_STREQ(buffer, "unsigned integer: 0x1000");
+}
diff --git a/lib/libc/test_common/test_functions.c b/lib/libc/test_common/test_functions.c
new file mode 100644
index 00000000..97d64143
--- /dev/null
+++ b/lib/libc/test_common/test_functions.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2022 LK Trusty Authors. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdarg.h>
+#include "printf_test.h"
+
+struct _output_args {
+ char *outstr;
+ size_t len;
+ size_t pos;
+};
+
+static int _vsnprintf_output(const char *str, size_t len, void *state)
+{
+ struct _output_args *args = state;
+
+ size_t count = 0;
+ while (count < len) {
+ if (args->pos < args->len) {
+ args->outstr[args->pos++] = *str;
+ }
+
+ str++;
+ count++;
+ }
+
+ return count;
+}
+
+/*
+* vsnprintf_filtered and snprintf_filtered were added to test that klog, printf and fprintf
+* filtering is working. Normal sprintf variants are currently not being filtered.
+*/
+
+int vsnprintf_filtered(char *str, size_t len, const char *fmt, va_list ap)
+{
+ struct _output_args args;
+ int wlen;
+
+ args.outstr = str;
+ args.len = len;
+ args.pos = 0;
+
+ wlen = _printf_engine(&_vsnprintf_output, (void *)&args, fmt, ap);
+ if (args.pos >= len)
+ str[len-1] = '\0';
+ else
+ str[wlen] = '\0';
+ return wlen;
+}
+
+int snprintf_filtered(char *str, size_t len, const char *fmt, ...)
+{
+ int err;
+
+ va_list ap;
+ va_start(ap, fmt);
+ err = vsnprintf_filtered(str, len, fmt, ap);
+ va_end(ap);
+
+ return err;
+}
diff --git a/lib/libc/test_includes/printf_test.h b/lib/libc/test_includes/printf_test.h
new file mode 100644
index 00000000..96366d47
--- /dev/null
+++ b/lib/libc/test_includes/printf_test.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022 LK Trusty Authors. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __PRINTF_TEST_H
+#define __PRINTF_TEST_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+typedef unsigned int uint;
+typedef int (*_printf_engine_output_func)(const char *str, size_t len, void *state);
+
+int _printf_engine(_printf_engine_output_func out, void *state, const char *fmt, va_list ap);
+#define __NO_INLINE
+#define __FALLTHROUGH
+
+#endif \ No newline at end of file
diff --git a/lib/libc/test_includes/printf_test_defs.h b/lib/libc/test_includes/printf_test_defs.h
new file mode 100644
index 00000000..9554ba57
--- /dev/null
+++ b/lib/libc/test_includes/printf_test_defs.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2022 LK Trusty Authors. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __PRINTF_TEST_DEFS_H
+#define __PRINTF_TEST_DEFS_H
+
+extern "C" int snprintf_filtered(char *str, size_t len, const char *fmt, ...);
+
+#define EXPECT_STREQ_COND(lhs, rhs_true, rhs_false, condition) EXPECT_STREQ((lhs), (condition)?(rhs_true):(rhs_false))
+
+#endif
+