From 0efb3c61a9575eede8984f362dfa6cd0b7562f4a Mon Sep 17 00:00:00 2001 From: Phil Jones Date: Tue, 6 Dec 2022 11:51:41 +0000 Subject: Add config file unit tests and fix some bugs. --- src/color.c | 31 +++++++++++++++++++++++++++---- src/config.c | 30 ++++++++++++++++-------------- src/config.h | 3 ++- src/main.c | 8 ++++++-- 4 files changed, 51 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/color.c b/src/color.c index 3fd9516..4b6b356 100644 --- a/src/color.c +++ b/src/color.c @@ -1,3 +1,4 @@ +#include #include #include #include "color.h" @@ -10,15 +11,22 @@ struct color hex_to_color(const char *hex) } uint32_t val = 0; + int64_t tmp; size_t len = strlen(hex); + errno = 0; if (len == 3) { char str[] = { hex[0], hex[0], hex[1], hex[1], hex[2], hex[2], '\0'}; - val = strtol(str, NULL, 16); + char *endptr; + tmp = strtol(str, &endptr, 16); + if (errno || *endptr != '\0' || tmp < 0) { + return (struct color) { -1, -1, -1, -1 }; + } + val = tmp; val <<= 8; val |= 0xFFu; } else if (len == 4) { @@ -28,13 +36,28 @@ struct color hex_to_color(const char *hex) hex[2], hex[2], hex[3], hex[3], '\0'}; - val = strtol(str, NULL, 16); + char *endptr; + tmp = strtol(str, &endptr, 16); + if (errno || *endptr != '\0' || tmp < 0) { + return (struct color) { -1, -1, -1, -1 }; + } + val = tmp; } else if (len == 6) { - val = strtol(hex, NULL, 16); + char *endptr; + tmp = strtol(hex, &endptr, 16); + if (errno || *endptr != '\0' || tmp < 0) { + return (struct color) { -1, -1, -1, -1 }; + } + val = tmp; val <<= 8; val |= 0xFFu; } else if (len == 8) { - val = strtol(hex, NULL, 16); + char *endptr; + tmp = strtol(hex, &endptr, 16); + if (errno || *endptr != '\0' || tmp < 0) { + return (struct color) { -1, -1, -1, -1 }; + } + val = tmp; } else { return (struct color) { -1, -1, -1, -1 }; } diff --git a/src/config.c b/src/config.c index 0cfd566..99a4494 100644 --- a/src/config.c +++ b/src/config.c @@ -710,11 +710,9 @@ bool parse_option(struct tofi *tofi, const char *filename, size_t lineno, const return !err; } -void config_apply(struct tofi *tofi, const char *option, const char *value) +bool config_apply(struct tofi *tofi, const char *option, const char *value) { - if (!parse_option(tofi, "", 0, option, value)) { - exit(EXIT_FAILURE); - }; + return parse_option(tofi, "", 0, option, value); } uint32_t fixup_percentage(uint32_t value, uint32_t base, bool is_percent, uint32_t scale, bool use_scale) @@ -905,6 +903,9 @@ uint32_t parse_char(const char *filename, size_t lineno, const char *str, bool * ch = utf8_to_utf32_validate(tmp); if (ch == (uint32_t)-2 || ch == (uint32_t)-1 || *utf8_next_char(tmp) != '\0') { PARSE_ERROR(filename, lineno, "Failed to parse \"%s\" as a character.\n", str); + if (err) { + *err = true; + } } free(tmp); @@ -961,13 +962,13 @@ uint32_t parse_uint32(const char *filename, size_t lineno, const char *str, bool { errno = 0; char *endptr; - int32_t ret = strtoul(str, &endptr, 0); - if (endptr == str) { + int64_t ret = strtoul(str, &endptr, 0); + if (endptr == str || *endptr != '\0') { PARSE_ERROR(filename, lineno, "Failed to parse \"%s\" as unsigned int.\n", str); if (err) { *err = true; } - } else if (errno || ret < 0) { + } else if (errno || ret < 0 || ret > UINT32_MAX) { PARSE_ERROR(filename, lineno, "Unsigned int value \"%s\" out of range.\n", str); if (err) { *err = true; @@ -980,13 +981,13 @@ int32_t parse_int32(const char *filename, size_t lineno, const char *str, bool * { errno = 0; char *endptr; - int32_t ret = strtol(str, &endptr, 0); - if (endptr == str) { + int64_t ret = strtol(str, &endptr, 0); + if (endptr == str || *endptr != '\0') { PARSE_ERROR(filename, lineno, "Failed to parse \"%s\" as int.\n", str); if (err) { *err = true; } - } else if (errno) { + } else if (errno || ret < INT32_MIN || ret > INT32_MAX) { PARSE_ERROR(filename, lineno, "Int value \"%s\" out of range.\n", str); if (err) { *err = true; @@ -999,14 +1000,14 @@ struct uint32_percent parse_uint32_percent(const char *filename, size_t lineno, { errno = 0; char *endptr; - int32_t val = strtoul(str, &endptr, 0); + int64_t val = strtoul(str, &endptr, 0); bool percent = false; - if (endptr == str) { + if (endptr == str || (*endptr != '\0' && *endptr != '%')) { PARSE_ERROR(filename, lineno, "Failed to parse \"%s\" as unsigned int.\n", str); if (err) { *err = true; } - } else if (errno || val < 0) { + } else if (errno || val < 0 || val > UINT32_MAX) { PARSE_ERROR(filename, lineno, "Unsigned int value \"%s\" out of range.\n", str); if (err) { *err = true; @@ -1022,7 +1023,8 @@ struct uint32_percent parse_uint32_percent(const char *filename, size_t lineno, struct directional parse_directional(const char *filename, size_t lineno, const char *str, bool *err) { - int32_t values[4]; + /* One extra value to act as a sentinel for too many values in str. */ + int32_t values[5]; char *saveptr = NULL; char *tmp = xstrdup(str); char *val = strtok_r(tmp, ",", &saveptr); diff --git a/src/config.h b/src/config.h index 8dbd241..a9f0c56 100644 --- a/src/config.h +++ b/src/config.h @@ -1,10 +1,11 @@ #ifndef TOFI_CONFIG_H #define TOFI_CONFIG_H +#include #include "tofi.h" void config_load(struct tofi *tofi, const char *filename); -void config_apply(struct tofi *tofi, const char *option, const char *value); +bool config_apply(struct tofi *tofi, const char *option, const char *value); void config_fixup_values(struct tofi *tofi); #endif /* TOFI_CONFIG_H */ diff --git a/src/main.c b/src/main.c index cde56b4..0c5c6cb 100644 --- a/src/main.c +++ b/src/main.c @@ -935,14 +935,18 @@ static void parse_args(struct tofi *tofi, int argc, char *argv[]) opt = getopt_long(argc, argv, short_options, long_options, &option_index); while (opt != -1) { if (opt == 0) { - config_apply(tofi, long_options[option_index].name, optarg); + if (!config_apply(tofi, long_options[option_index].name, optarg)) { + exit(EXIT_FAILURE); + } } else if (opt == 'k') { /* * Backwards compatibility for --late-keyboard-init not * taking an argument. */ if (optarg) { - config_apply(tofi, long_options[option_index].name, optarg); + if (!config_apply(tofi, long_options[option_index].name, optarg)) { + exit(EXIT_FAILURE); + } } else { tofi->late_keyboard_init = true; } -- cgit v1.2.3