summaryrefslogtreecommitdiffstats
path: root/pkgs/tools/X11/xkbvalidate
diff options
context:
space:
mode:
authoraszlig <aszlig@nix.build>2019-08-15 00:06:51 +0200
committeraszlig <aszlig@nix.build>2019-08-15 00:59:58 +0200
commit1964b0c1b1e2e8092a15da64bd37838bed261e26 (patch)
tree6db891aa788c2f35f182613207bd74aa2f5d1a94 /pkgs/tools/X11/xkbvalidate
parent77e8a12755632d62ef25541e3622f478edaa28c6 (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.nix4
-rw-r--r--pkgs/tools/X11/xkbvalidate/xkbvalidate.c21
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)