POSIX strerror_r returns an int while the glibc "extension" returns a char* and this causes segfaults when running on systems with libc's like musl which only implement the portable version or deliberately don't provide a flag to identify compiling using their headers. Glibc provides the POSIX variant of the function, but only if _GNU_SOURCE is not set i.e. all gnu extensions are disabled. Meson sets _GNU_SOURCE globally at build time. So detect during build if we have the char* version and #ifdef the logic. Signed-off-by: Ioan-Adrian Ratiu <adi at adirat.com> --- meson.build | 13 +++++++++++++ src/journal/journal-send.c | 9 +++++++++ src/libsystemd/sd-bus/bus-error.c | 9 +++++++++ 3 files changed, 31 insertions(+) diff --git a/meson.build b/meson.build index b53dfaa94..fe807237f 100644 --- a/meson.build +++ b/meson.build @@ -383,6 +383,19 @@ if cc.compiles(''' add_project_arguments('-Werror=shadow', language : 'c') endif +if cc.compiles(' + #include <string.h> + int func (void) { + char error_string[256]; + char *ptr = strerror_r(-2, error_string, 256); + char c = *strerror_r(-2, error_string, 256); + return c != 0 && ptr != (void*) 0L; + } +', name : 'strerror_r() returns char *', args : '-D_GNU_SOURCE') + conf.set('STRERROR_R_CHAR_P', 1, + description: 'Defined if strerror_r returns char *') +endif + if cc.get_id() == 'clang' foreach arg : ['-Wno-typedef-redefinition', '-Wno-gnu-variable-sized-type-not-at-end', diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c index b6adf64c2..9b33c6c3b 100644 --- a/src/journal/journal-send.c +++ b/src/journal/journal-send.c @@ -355,7 +355,16 @@ static int fill_iovec_perror_and_send(const char *message, int skip, struct iove char* j; errno = 0; + +#ifdef STRERROR_R_CHAR_P j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k); +#else + j = buffer + 8 + k; + int ret = strerror_r(_saved_errno_, j, n - 8 - k); + if (ret) + errno = ret; +#endif + if (errno == 0) { char error[STRLEN("ERRNO=") + DECIMAL_STR_MAX(int) + 1]; diff --git a/src/libsystemd/sd-bus/bus-error.c b/src/libsystemd/sd-bus/bus-error.c index 66a09a35f..10390f0d8 100644 --- a/src/libsystemd/sd-bus/bus-error.c +++ b/src/libsystemd/sd-bus/bus-error.c @@ -378,7 +378,16 @@ static void bus_error_strerror(sd_bus_error *e, int error) { return; errno = 0; + +#ifdef STRERROR_R_CHAR_P x = strerror_r(error, m, k); +#else + int ret = strerror_r(error, m, k); + if (ret) + errno = ret; + x = m; +#endif + if (errno == ERANGE || strlen(x) >= k - 1) { free(m); k *= 2; -- 2.16.3