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>
This commit is contained in:
parent
77e8a12755
commit
1964b0c1b1
@ -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"
|
||||
''
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user