diff options
author | aszlig <aszlig@nix.build> | 2019-08-15 00:06:51 +0200 |
---|---|---|
committer | aszlig <aszlig@nix.build> | 2019-08-15 00:59:58 +0200 |
commit | 1964b0c1b1e2e8092a15da64bd37838bed261e26 (patch) | |
tree | 6db891aa788c2f35f182613207bd74aa2f5d1a94 /pkgs/tools/X11/xkbvalidate | |
parent | 77e8a12755632d62ef25541e3622f478edaa28c6 (diff) |
xkbvalidate: Don't rely on GNU extensions
The only reason why I was using _GNU_SOURCE was because of vasprintf(),
so getting rid of that extension should make the source way more
portable.
When using vsnprintf() with a null pointer for the output buffer and a
size of 0, I wasn't quite sure whether this would be undefined
behaviour, so I looked it up in the C11 standard.
In section 7.21.6.5, it explicitly mentions this case, so we're lucky:
If n is zero, nothing is written, and s may be a null pointer.
Additionally, section 7.21.6.12 writes the following about vsnprintf():
The vsnprintf function does not invoke the va_end macro.
So to be sure to avoid undefined behaviour I subsequently added the
corresponding va_end() calls.
With this, the platforms attribute is now "unix", because the program
should now even run on OS X, even though it usually wouldn't be needed.
Signed-off-by: aszlig <aszlig@nix.build>
Diffstat (limited to 'pkgs/tools/X11/xkbvalidate')
-rw-r--r-- | pkgs/tools/X11/xkbvalidate/default.nix | 4 | ||||
-rw-r--r-- | pkgs/tools/X11/xkbvalidate/xkbvalidate.c | 21 |
2 files changed, 20 insertions, 5 deletions
diff --git a/pkgs/tools/X11/xkbvalidate/default.nix b/pkgs/tools/X11/xkbvalidate/default.nix index c4aec30e7241..2855d03120fd 100644 --- a/pkgs/tools/X11/xkbvalidate/default.nix +++ b/pkgs/tools/X11/xkbvalidate/default.nix @@ -5,11 +5,11 @@ runCommandCC "xkbvalidate" { meta = { description = "NixOS tool to validate X keyboard configuration"; license = lib.licenses.mit; - platforms = lib.platforms.linux; + platforms = lib.platforms.unix; maintainers = [ lib.maintainers.aszlig ]; }; } '' mkdir -p "$out/bin" - $CC -std=gnu11 -Wall -pedantic -lxkbcommon ${./xkbvalidate.c} \ + $CC -std=c11 -Wall -pedantic -lxkbcommon ${./xkbvalidate.c} \ -o "$out/bin/validate" '' diff --git a/pkgs/tools/X11/xkbvalidate/xkbvalidate.c b/pkgs/tools/X11/xkbvalidate/xkbvalidate.c index d9c9042467c0..d25eef154b3c 100644 --- a/pkgs/tools/X11/xkbvalidate/xkbvalidate.c +++ b/pkgs/tools/X11/xkbvalidate/xkbvalidate.c @@ -1,4 +1,3 @@ -#define _GNU_SOURCE #include <stdarg.h> #include <stdbool.h> #include <stdio.h> @@ -14,6 +13,9 @@ static bool log_alloc_success = true; static void add_log(struct xkb_context *ctx, enum xkb_log_level level, const char *fmt, va_list args) { + size_t buflen; + va_list tmpargs; + log_buffer_size++; if (log_buffer == NULL) @@ -28,11 +30,24 @@ static void add_log(struct xkb_context *ctx, enum xkb_log_level level, return; } - if (vasprintf(&log_buffer[log_buffer_size - 1], fmt, args) == -1) { + /* Unfortunately, vasprintf() is a GNU extension and thus not very + * portable, so let's first get the required buffer size using a dummy + * vsnprintf and afterwards allocate the returned amount of bytes. + * + * We also need to make a copy of the args, because the value of the args + * will be indeterminate after the return. + */ + va_copy(tmpargs, args); + buflen = vsnprintf(NULL, 0, fmt, tmpargs); + va_end(tmpargs); + + log_buffer[log_buffer_size - 1] = malloc(++buflen); + + if (vsnprintf(log_buffer[log_buffer_size - 1], buflen, fmt, args) == -1) { perror("log line alloc"); log_alloc_success = false; - return; } + va_end(args); } static void print_logs(void) |