error.h: Never call (para_)strerror() on osl errors.
authorAndre Noll <maan@tuebingen.mpg.de>
Wed, 12 Aug 2015 17:24:50 +0000 (19:24 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Sun, 27 Sep 2015 13:25:40 +0000 (13:25 +0000)
In the (inlined) function para_strerror() of error.h we compile in
the call to osl_strerror() if and only if osl.h has been included
(in which case the preprocessor macro _OSL_H is defined). This is
wrong because an osl error code might well be passed to a function
defined in a compilation unit which does not include osl.h. If this
function calls para_strerror(), we will segfault or worse.

We need to check at link time whether osl_strerror is a defined
symbol rather than checking a preprocessor macro at compile time.
Fortunately, a little linker fu helps us out here. This patch
introduces a weak reference to osl_strerror to tell whether
osl_strerror is defined.

error.h

diff --git a/error.h b/error.h
index 379d37326782f308ce6b7e576c25383ea1b7b8c7..49a57a5a15bcd6c070328161310be83cd0a7379a 100644 (file)
--- a/error.h
+++ b/error.h
@@ -578,6 +578,8 @@ extern const char **para_errlist[];
 /** Set the osl error bit for the given number. */
 #define OSL_ERRNO_TO_PARA_ERROR(num) ((num) | (1 << OSL_ERROR_BIT))
 
+
+static const char *weak_osl_strerror(int) __attribute__ ((weakref("osl_strerror")));
 /**
  * Paraslash's version of strerror(3).
  *
@@ -588,10 +590,10 @@ extern const char **para_errlist[];
 _static_inline_ const char *para_strerror(int num)
 {
        assert(num > 0);
-#ifdef _OSL_H
-       if (IS_OSL_ERROR(num))
-               return osl_strerror(num & ~(1U << OSL_ERROR_BIT));
-#endif
+       if (IS_OSL_ERROR(num)) {
+               assert(weak_osl_strerror);
+               return weak_osl_strerror(num & ~(1U << OSL_ERROR_BIT));
+       }
        if (IS_SYSTEM_ERROR(num))
                return strerror(num & ~(1U << SYSTEM_ERROR_BIT));
        return para_errlist[ERRNUM_TO_SS(num)][ERRNUM_TO_INDEX(num)];