From 476f84cf5928ab4c6d94c6a6f2fc251c5640de92 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Thu, 23 Jul 2015 13:58:02 +0200 Subject: [PATCH] Use portable version of strerror_r There are 2 variants of strerror_r, GNU extension and a POSIX variant. Use the more portable POSIX variant. Also fix a potensial stack-use-after-return bug, instead of relying on undefined behavoir in GNU libc implementation. The strerror_r manpage says: > This may be either a pointer to a string that the function stores in > buf, or a pointer to some (immutable) static string (in which case buf > is unused). So it does not guarantee that it returns a pointer to some (immutable) static string. It might return a pointer to "buf", in which case we get a stack-use-after-return bug. We fix this by declaring a thread local static buffer which we always return. --- src/c++wrap.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/c++wrap.cc b/src/c++wrap.cc index c21b4735..213f9c4f 100644 --- a/src/c++wrap.cc +++ b/src/c++wrap.cc @@ -26,8 +26,14 @@ #include "c++wrap.hh" #include + +/* force use of POSIX strerror_r instead of non-portable GNU specific */ +#ifdef _GNU_SOURCE +#undef _GNU_SOURCE +#endif #include + #if !defined(HAVE_PIPE2) || !defined(HAVE_O_CLOEXEC) #include @@ -62,8 +68,10 @@ namespace { std::string strerror_r(int errnum) { - char buf[100]; - return strerror_r(errnum, buf, sizeof buf); + static thread_local char buf[100]; + if (strerror_r(errnum, buf, sizeof buf) != 0) + snprintf(buf, sizeof buf, "Unknown error %i", errnum); + return buf; } std::pair pipe2(int flags)