summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorAndrew Kaster <akaster@serenityos.org>2022-02-08 22:33:35 -0700
committerBrian Gianforcaro <b.gianfo@gmail.com>2022-02-09 06:22:33 +0000
commit353e72ac9bc436f8d4635ed61211c34b623ab7ab (patch)
treeb0921d81beca84fa274771f0d6b9a0a7c423a887 /Userland
parent8ec4328fcb976f9088e0f1c19662310f3b776034 (diff)
downloadserenity-353e72ac9bc436f8d4635ed61211c34b623ab7ab.zip
LibC+Kernel: Remove global variable use from snprintf and fprintf
The global variable use in these functions is super thread-unsafe and means that any concurrent calls to sprintf or fprintf in a process could race with each other and end up writing unexpected results. We can just replace the function + global variable with a lambda that captures the relevant argument when calling printf_internal instead.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibC/stdio.cpp31
1 files changed, 11 insertions, 20 deletions
diff --git a/Userland/Libraries/LibC/stdio.cpp b/Userland/Libraries/LibC/stdio.cpp
index 4fbd70e8aa..bc9091cd27 100644
--- a/Userland/Libraries/LibC/stdio.cpp
+++ b/Userland/Libraries/LibC/stdio.cpp
@@ -870,17 +870,10 @@ ALWAYS_INLINE void stdout_putch(char*&, char ch)
putchar(ch);
}
-static FILE* __current_stream = nullptr;
-ALWAYS_INLINE static void stream_putch(char*&, char ch)
-{
- fputc(ch, __current_stream);
-}
-
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/vfprintf.html
int vfprintf(FILE* stream, const char* fmt, va_list ap)
{
- __current_stream = stream;
- return printf_internal(stream_putch, nullptr, fmt, ap);
+ return printf_internal([stream](auto, char ch) { fputc(ch, stream); }, nullptr, fmt, ap);
}
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
@@ -957,25 +950,23 @@ int sprintf(char* buffer, const char* fmt, ...)
return ret;
}
-static size_t __vsnprintf_space_remaining;
-ALWAYS_INLINE void sized_buffer_putch(char*& bufptr, char ch)
-{
- if (__vsnprintf_space_remaining) {
- *bufptr++ = ch;
- --__vsnprintf_space_remaining;
- }
-}
-
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/vsnprintf.html
int vsnprintf(char* buffer, size_t size, const char* fmt, va_list ap)
{
+ size_t space_remaining = 0;
if (size) {
- __vsnprintf_space_remaining = size - 1;
+ space_remaining = size - 1;
} else {
- __vsnprintf_space_remaining = 0;
+ space_remaining = 0;
}
+ auto sized_buffer_putch = [&](char*& bufptr, char ch) {
+ if (space_remaining) {
+ *bufptr++ = ch;
+ --space_remaining;
+ }
+ };
int ret = printf_internal(sized_buffer_putch, buffer, fmt, ap);
- if (__vsnprintf_space_remaining) {
+ if (space_remaining) {
buffer[ret] = '\0';
} else if (size > 0) {
buffer[size - 1] = '\0';