aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Benjamin Barenblat <bbaren@google.com>2020-05-13 13:48:32 -0400
committerGravatar Benjamin Barenblat <bbaren@google.com>2020-05-13 13:48:32 -0400
commitafbf22d62076868d6db30411ad1924d99fbdb05d (patch)
tree09c226042542225302b95cd4fa9f4b72785539cf
parentf099f30489f958c4466b83ecb0427f28b9c11e9d (diff)
Don’t pass `char` to `va_start`cleanup
Passing `va_start` an argument of a type that undergoes promotion (`char`, `float`, etc.) triggers undefined behavior. Make `_cat_with` take an `int c` instead, and assert that `c` can be stored in a `char` before using it as one.
-rw-r--r--brightnessctl.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/brightnessctl.c b/brightnessctl.c
index 31a066d..922a3c4 100644
--- a/brightnessctl.c
+++ b/brightnessctl.c
@@ -1,3 +1,4 @@
+#include <assert.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/stat.h>
@@ -31,7 +32,7 @@ enum operation;
static void fail(char *, ...);
static void usage(void);
#define cat_with(...) _cat_with(__VA_ARGS__, NULL)
-static char *_cat_with(char, ...);
+static char *_cat_with(int, ...);
static char *dir_child(char *, char*);
static char *device_path(struct device *);
static char *class_path(char *);
@@ -601,12 +602,16 @@ bool ensure_dev_dir(struct device *dev) {
return ret;
}
-char *_cat_with(char c, ...) {
+char *_cat_with(int c, ...) {
+ // We'd like c to be a char, but passing a char to va_start triggers
+ // undefined behavior. Take it as an int instead, and assert that it can
+ // fit in a char before using it as one.
+ assert(c >= CHAR_MIN && c <= CHAR_MAX);
size_t size = 32;
size_t length = 0;
char *buf = calloc(1, size + 1);
char *curr;
- char split[2] = {c, '\0'};
+ char split[2] = {(char) c, '\0'};
va_list va;
va_start(va, c);
curr = va_arg(va, char *);