From 8d46c9bbe2c61fd6ef5f5c882cc7a1ad6c0620a7 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 30 Oct 2022 09:53:23 +0100 Subject: [PATCH] Kernel, libc: Fix a big bug in printf() Every time printf flushes the buffer to us in sprintf() or snprintf(), we call strncat to append the data. But we want to start from the beginning in the first flush. What if there was data already there? Well, we just append to the old data. Which is not good, and breaks snprintf()'s maximum size policy. This fix sets the first byte of str to NULL, to avoid this. --- kernel/src/std/stdio.cpp | 4 ++++ libs/libc/src/printf.cpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/kernel/src/std/stdio.cpp b/kernel/src/std/stdio.cpp index 08819639..18af8db5 100644 --- a/kernel/src/std/stdio.cpp +++ b/kernel/src/std/stdio.cpp @@ -228,6 +228,7 @@ int sprintf(char* __s, const char* fmt, ...) { va_list ap; va_start(ap, fmt); + if (__s) *__s = 0; int written = internal_printf( fmt, [&](const char* s) { @@ -242,6 +243,7 @@ int snprintf(char* __s, size_t max, const char* fmt, ...) { va_list ap; va_start(ap, fmt); + if (__s && max) *__s = 0; int written = internal_printf( fmt, [&](const char* s) { @@ -266,6 +268,7 @@ int vkprintf(const char* fmt, va_list ap) int vsprintf(char* __s, const char* fmt, va_list ap) { + *__s = 0; return internal_printf( fmt, [&](const char* s) { @@ -276,6 +279,7 @@ int vsprintf(char* __s, const char* fmt, va_list ap) int vsnprintf(char* __s, size_t max, const char* fmt, va_list ap) { + if (max) *__s = 0; return internal_printf( fmt, [&](const char* s) { diff --git a/libs/libc/src/printf.cpp b/libs/libc/src/printf.cpp index e4bb9847..e47568c1 100644 --- a/libs/libc/src/printf.cpp +++ b/libs/libc/src/printf.cpp @@ -261,6 +261,7 @@ extern "C" int vsprintf(char* str, const char* format, va_list ap) { + if (str) *str = 0; // so strncat starts from the beginning return internal_printf( format, [&](const char* s) { @@ -271,6 +272,7 @@ extern "C" int vsnprintf(char* str, size_t max, const char* format, va_list ap) { + if (max && str) *str = 0; // so strncat starts from the beginning return internal_printf( format, [&](const char* s) {