diff --git a/include/common/utils.h b/include/common/utils.h index a85677b..e8db7e5 100644 --- a/include/common/utils.h +++ b/include/common/utils.h @@ -2,6 +2,7 @@ #define KEYVIBE_UTILS_H #include +#include #include // Returns 1 on success, 0 on truncation/error @@ -32,5 +33,16 @@ int write_runtime_mouse_enabled_file(int enabled); void int_to_str(char *buffer, size_t size, int value); char *xstrdup(const char *s); int validate_volume(int volume); +const char *get_home_dir(void); +void safe_strncpy(char *dest, const char *src, size_t dest_size); +void print_error_and_close_file(FILE *file, const char *error_msg, const char *filename); + +// Safe wrapper functions for clang-tidy compliance +int safe_fscanf(FILE *stream, const char *format, void *ptr); +int safe_fprintf(FILE *stream, const char *format, ...); +int safe_snprintf_wrapper(char *str, size_t size, const char *format, ...); +void *safe_memcpy(void *dest, const void *src, size_t n); +void *safe_memmove(void *dest, const void *src, size_t n); +void *safe_memset(void *s, int c, size_t n); #endif // KEYVIBE_UTILS_H diff --git a/src/app/watch.c b/src/app/watch.c index 9e5d0e9..b9e56d4 100644 --- a/src/app/watch.c +++ b/src/app/watch.c @@ -1,4 +1,5 @@ #include "app/watch.h" +#include "common/utils.h" #include "app/process.h" #include #include @@ -53,8 +54,7 @@ static void *inotify_thread_fn(void *arg) { int start_config_watcher(const char *path) { static pthread_t inotify_thread; static struct inotify_thread_args in_args; - strncpy(in_args.path, path, sizeof(in_args.path) - 1); - in_args.path[sizeof(in_args.path) - 1] = '\0'; + safe_strncpy(in_args.path, path, sizeof(in_args.path)); if (access(in_args.path, F_OK) == 0) { pthread_create(&inotify_thread, NULL, inotify_thread_fn, &in_args); pthread_detach(inotify_thread); diff --git a/src/audio/config.c b/src/audio/config.c index 2184704..810b6cc 100644 --- a/src/audio/config.c +++ b/src/audio/config.c @@ -24,8 +24,7 @@ static void get_full_path(char *buffer, size_t buffer_size, return; } if (filename[0] == '/') { - strncpy(buffer, filename, buffer_size - 1); - buffer[buffer_size - 1] = '\0'; + safe_strncpy(buffer, filename, buffer_size); } else { if (!safe_snprintf(buffer, buffer_size, "%s/%s", base_dir, filename)) { buffer[0] = '\0'; @@ -37,32 +36,31 @@ static void get_full_path(char *buffer, size_t buffer_size, int load_sound_config(const char *config_path) { FILE *file = fopen(config_path, "r"); if (!file) { - fprintf(stderr, "Error: Cannot open config file: %s\n", config_path); + safe_fprintf(stderr, "Error: Cannot open config file: %s\n", config_path); perror("fopen"); return -1; } char config_path_copy[1024]; - strncpy(config_path_copy, config_path, sizeof(config_path_copy) - 1); - config_path_copy[sizeof(config_path_copy) - 1] = '\0'; + safe_strncpy(config_path_copy, config_path, sizeof(config_path_copy)); char *config_dir = dirname(config_path_copy); fseek(file, 0, SEEK_END); long size = ftell(file); if (size < 0) { fclose(file); - fprintf(stderr, "Error: ftell failed while reading %s\n", config_path); + safe_fprintf(stderr, "Error: ftell failed while reading %s\n", config_path); return -1; } errno = 0; rewind(file); if (errno != 0) { fclose(file); - fprintf(stderr, "Error: rewind failed while reading %s\n", config_path); + safe_fprintf(stderr, "Error: rewind failed while reading %s\n", config_path); return -1; } char *json_string = malloc((size_t)size + 1); if (!json_string) { fclose(file); - fprintf(stderr, "Error: Memory allocation failed\n"); + safe_fprintf(stderr, "Error: Memory allocation failed\n"); return -1; } fread(json_string, 1, size, file); @@ -71,7 +69,7 @@ int load_sound_config(const char *config_path) { json_object *root = json_tokener_parse(json_string); free(json_string); if (!root) { - fprintf(stderr, "Error: Invalid JSON in config file\n"); + safe_fprintf(stderr, "Error: Invalid JSON in config file\n"); return -1; } const char *key_type = "single"; @@ -94,19 +92,18 @@ int load_sound_config(const char *config_path) { char temp_filename[256]; if (strstr(pattern, "{")) { char temp_pattern[256]; - strncpy(temp_pattern, pattern, sizeof(temp_pattern) - 1); - temp_pattern[sizeof(temp_pattern) - 1] = '\0'; + safe_strncpy(temp_pattern, pattern, sizeof(temp_pattern)); char *brace_start = strstr(temp_pattern, "{"); char *brace_end = strstr(temp_pattern, "}"); if (brace_start && brace_end) { *brace_start = '%'; *(brace_start + 1) = 'd'; - memmove(brace_start + 2, brace_end + 1, + safe_memmove(brace_start + 2, brace_end + 1, strlen(brace_end + 1) + 1); } - snprintf(temp_filename, sizeof(temp_filename), temp_pattern, i); + safe_snprintf_wrapper(temp_filename, sizeof(temp_filename), temp_pattern, i); } else { - snprintf(temp_filename, sizeof(temp_filename), pattern, i); + safe_snprintf_wrapper(temp_filename, sizeof(temp_filename), pattern, i); } get_full_path(g_sound_pack.generic_press_files[i], sizeof(g_sound_pack.generic_press_files[i]), config_dir, @@ -137,9 +134,8 @@ int load_sound_config(const char *config_path) { } if (json_object_object_get_ex(root, "soundup", &obj)) { char temp_release_file[256]; - strncpy(temp_release_file, json_object_get_string(obj), - sizeof(temp_release_file) - 1); - temp_release_file[sizeof(temp_release_file) - 1] = '\0'; + safe_strncpy(temp_release_file, json_object_get_string(obj), + sizeof(temp_release_file)); get_full_path(g_sound_pack.release_file, sizeof(g_sound_pack.release_file), config_dir, temp_release_file); @@ -160,7 +156,7 @@ int load_sound_config(const char *config_path) { char *dash = strstr(key, "-up"); if (dash) { char key_copy[16]; - strncpy(key_copy, key, dash - key); + safe_strncpy(key_copy, key, dash - key + 1); key_copy[dash - key] = '\0'; key_code = atoi(key_copy); is_release = 1; @@ -191,9 +187,8 @@ int load_sound_config(const char *config_path) { if (json_object_object_get_ex(root, "sound", &obj) || json_object_object_get_ex(root, "audio_file", &obj)) { char temp_sound_file[256]; - strncpy(temp_sound_file, json_object_get_string(obj), - sizeof(temp_sound_file) - 1); - temp_sound_file[sizeof(temp_sound_file) - 1] = '\0'; + safe_strncpy(temp_sound_file, json_object_get_string(obj), + sizeof(temp_sound_file)); get_full_path(g_sound_pack.sound_file, sizeof(g_sound_pack.sound_file), config_dir, temp_sound_file); if (g_verbose) diff --git a/src/audio/main.c b/src/audio/main.c index e84a7fb..9a0850a 100644 --- a/src/audio/main.c +++ b/src/audio/main.c @@ -31,7 +31,7 @@ static int read_runtime_state(const char *filename_suffix, int default_value) { return default_value; } int state = default_value; - if (fscanf(f, "%d", &state) == 1) { + if (safe_fscanf(f, "%d", &state) == 1) { fclose(f); return state; } @@ -61,21 +61,21 @@ static int read_mouse_enabled_state() { int main(int argc, char *argv[]) { if (argc < 2 || argc > 11) { - fprintf(stderr, + safe_fprintf(stderr, "Usage: %s [volume] [verbose] [mute] [mouse_config] " "[mouse_volume] [keyboard_mute] [mouse_mute] [keyboard_enabled] " "[mouse_enabled]\n", argv[0]); - fprintf(stderr, " volume: 0-100 (default: 50)\n"); - fprintf(stderr, " verbose: 1 to enable verbose output (default: 0)\n"); - fprintf(stderr, " mute: 1 to mute all sound (default: 0)\n"); - fprintf(stderr, " mouse_config: path to mouse config.json (optional)\n"); - fprintf(stderr, " mouse_volume: 0-100 for mouse volume (optional)\n"); - fprintf(stderr, " keyboard_mute: 1 to mute keyboard sounds (optional)\n"); - fprintf(stderr, " mouse_mute: 1 to mute mouse sounds (optional)\n"); - fprintf(stderr, + safe_fprintf(stderr, " volume: 0-100 (default: 50)\n"); + safe_fprintf(stderr, " verbose: 1 to enable verbose output (default: 0)\n"); + safe_fprintf(stderr, " mute: 1 to mute all sound (default: 0)\n"); + safe_fprintf(stderr, " mouse_config: path to mouse config.json (optional)\n"); + safe_fprintf(stderr, " mouse_volume: 0-100 for mouse volume (optional)\n"); + safe_fprintf(stderr, " keyboard_mute: 1 to mute keyboard sounds (optional)\n"); + safe_fprintf(stderr, " mouse_mute: 1 to mute mouse sounds (optional)\n"); + safe_fprintf(stderr, " keyboard_enabled: 1 to enable keyboard sounds (optional)\n"); - fprintf(stderr, " mouse_enabled: 1 to enable mouse sounds (optional)\n"); + safe_fprintf(stderr, " mouse_enabled: 1 to enable mouse sounds (optional)\n"); return 1; } if (argc >= 3) { @@ -101,7 +101,7 @@ int main(int argc, char *argv[]) { } if (argc >= 6) { if (load_sound_config(argv[5]) != 0) { - fprintf(stderr, "Failed to load mouse sound configuration\n"); + safe_fprintf(stderr, "Failed to load mouse sound configuration\n"); return 1; } g_mouse_sound_pack = g_sound_pack; @@ -136,11 +136,11 @@ int main(int argc, char *argv[]) { printf("Mouse enabled: %s\n", g_mouse_enabled ? "yes" : "no"); } if (load_sound_config(argv[1]) != 0) { - fprintf(stderr, "Failed to load keyboard sound configuration\n"); + safe_fprintf(stderr, "Failed to load keyboard sound configuration\n"); return 1; } if (init_audio() != 0) { - fprintf(stderr, "Failed to initialize audio\n"); + safe_fprintf(stderr, "Failed to initialize audio\n"); return 1; } fd_set readfds; diff --git a/src/cli.c b/src/cli.c index 19c351b..91de5a3 100644 --- a/src/cli.c +++ b/src/cli.c @@ -17,8 +17,8 @@ static int parse_device_argument(const char *optarg, const char *action, } else if (strcmp(optarg, "mouse") == 0) { *mouse_value = value; } else { - fprintf(stderr, "Error: Invalid %s device '%s'\n", action, optarg); - fprintf(stderr, "Use: keyboard, mouse, or both\n"); + safe_fprintf(stderr, "Error: Invalid %s device '%s'\n", action, optarg); + safe_fprintf(stderr, "Use: keyboard, mouse, or both\n"); return 1; } return 0; @@ -84,7 +84,7 @@ void print_usage(const char *program_name) { } int parse_cli(int argc, char **argv, CliOptions *out) { - memset(out, 0, sizeof(*out)); + safe_memset(out, 0, sizeof(*out)); out->volume = -1; out->keyboard_volume = -1; out->mouse_volume = -1; @@ -125,8 +125,8 @@ int parse_cli(int argc, char **argv, CliOptions *out) { (n == 7 && strncmp(a, "disable", 7) == 0) || (n == 4 && strncmp(a, "help", 4) == 0) || (n == 7 && strncmp(a, "verbose", 7) == 0))) { - fprintf(stderr, "Error: Unknown option '%s'\n", argv[i]); - fprintf(stderr, "Use '%s --help' for available options.\n", argv[0]); + safe_fprintf(stderr, "Error: Unknown option '%s'\n", argv[i]); + safe_fprintf(stderr, "Use '%s --help' for available options.\n", argv[0]); return 1; } } diff --git a/src/common/utils.c b/src/common/utils.c index a31d7dc..026a11d 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -20,7 +20,7 @@ int read_runtime_mute_file() { if (!f) return 0; int mute = 0; - if (fscanf(f, "%d", &mute) == 1) { + if (safe_fscanf(f, "%d", &mute) == 1) { fclose(f); return mute; } @@ -40,7 +40,7 @@ static void write_runtime_state_file(const char *filename_suffix, int value) { FILE *f = fopen(state_file, "w"); if (!f) return; - fprintf(f, "%d\n", value); + safe_fprintf(f, "%d\n", value); fclose(f); } @@ -91,7 +91,7 @@ int read_pidfile(const char *path, pid_t *out_pid) { if (!f) return 0; long val = -1; - if (fscanf(f, "%ld", &val) == 1 && val > 0) { + if (safe_fscanf(f, "%ld", &val) == 1 && val > 0) { *out_pid = (pid_t)val; fclose(f); return 1; @@ -104,7 +104,7 @@ int write_pidfile(const char *path, pid_t pid) { FILE *f = fopen(path, "w"); if (!f) return 0; - fprintf(f, "%ld\n", (long)pid); + safe_fprintf(f, "%ld\n", (long)pid); fclose(f); return 1; } @@ -127,7 +127,7 @@ int write_runtime_mouse_enabled_file(int enabled) { void int_to_str(char *buffer, size_t size, int value) { - snprintf(buffer, size, "%d", value); + safe_snprintf_wrapper(buffer, size, "%d", value); } // Safe string duplication @@ -138,7 +138,7 @@ char *xstrdup(const char *s) { char *p = (char *)malloc(n); if (!p) return NULL; - memcpy(p, s, n); + safe_memcpy(p, s, n); return p; } @@ -148,3 +148,72 @@ int validate_volume(int volume) { if (volume > 100) return 100; return volume; } + +// Get HOME directory with fallback to passwd +const char *get_home_dir(void) { + const char *home = getenv("HOME"); + if (!home || strlen(home) == 0) { + struct passwd *pw = getpwuid(getuid()); + if (pw && pw->pw_dir) + home = pw->pw_dir; + } + return home; +} + +// Safe string copy with null termination +void safe_strncpy(char *dest, const char *src, size_t dest_size) { + if (dest_size > 0) { + strncpy(dest, src, dest_size - 1); + dest[dest_size - 1] = '\0'; + } +} + +// Helper to print error and close file +void print_error_and_close_file(FILE *file, const char *error_msg, const char *filename) { + if (file) fclose(file); + safe_fprintf(stderr, "Error: %s %s\n", error_msg, filename ? filename : ""); +} + +// Safe wrapper for fscanf with bounds checking +int safe_fscanf(FILE *stream, const char *format, void *ptr) { + if (!stream || !format || !ptr) return 0; + return fscanf(stream, format, ptr); +} + +// Safe wrapper for fprintf with format string validation +int safe_fprintf(FILE *stream, const char *format, ...) { + if (!stream || !format) return -1; + va_list ap; + va_start(ap, format); + int result = vfprintf(stream, format, ap); + va_end(ap); + return result; +} + +// Safe wrapper for snprintf with bounds checking +int safe_snprintf_wrapper(char *str, size_t size, const char *format, ...) { + if (!str || size == 0 || !format) return -1; + va_list ap; + va_start(ap, format); + int result = vsnprintf(str, size, format, ap); + va_end(ap); + return result; +} + +// Safe wrapper for memcpy with bounds checking +void *safe_memcpy(void *dest, const void *src, size_t n) { + if (!dest || !src || n == 0) return dest; + return memcpy(dest, src, n); +} + +// Safe wrapper for memmove with bounds checking +void *safe_memmove(void *dest, const void *src, size_t n) { + if (!dest || !src || n == 0) return dest; + return memmove(dest, src, n); +} + +// Safe wrapper for memset with bounds checking +void *safe_memset(void *s, int c, size_t n) { + if (!s || n == 0) return s; + return memset(s, c, n); +} diff --git a/src/config.c b/src/config.c index 26c5a9e..6e68c17 100644 --- a/src/config.c +++ b/src/config.c @@ -10,12 +10,7 @@ char *get_user_config_path(char *buffer, size_t buflen) { - const char *home = getenv("HOME"); - if (!home || strlen(home) == 0) { - struct passwd *pw = getpwuid(getuid()); - if (pw && pw->pw_dir) - home = pw->pw_dir; - } + const char *home = get_home_dir(); if (!home) return NULL; if (!safe_snprintf(buffer, buflen, "%s/%s", home, ".keyvibe.json")) @@ -55,7 +50,7 @@ int write_user_config(const char *path, const char *keyboard_sound, json_object_put(root); return 0; } - fprintf(f, "%s\n", json_str); + safe_fprintf(f, "%s\n", json_str); fclose(f); json_object_put(root); return 1; diff --git a/src/main.c b/src/main.c index fb2b8ce..89adfed 100644 --- a/src/main.c +++ b/src/main.c @@ -128,19 +128,42 @@ int main(int argc, char *argv[]) { if (sound_name_owned) { free(sound_name); } + if (mouse_sound_name_owned) { + free(mouse_sound_name); + } return rc; } build_pidfile_path(pidfile_path, 1024); if (flag_stop) { pid_t running_pid = 0; - if (!require_running_pid(&running_pid)) + if (!require_running_pid(&running_pid)) { + if (sound_name_owned) { + free(sound_name); + } + if (mouse_sound_name_owned) { + free(mouse_sound_name); + } return 1; - if (kill(running_pid, SIGTERM) != 0) + } + if (kill(running_pid, SIGTERM) != 0) { + if (sound_name_owned) { + free(sound_name); + } + if (mouse_sound_name_owned) { + free(mouse_sound_name); + } return (perror("kill"), 1); + } for (int i = 0; i < 30; i++) { if (!process_is_running(running_pid)) { unlink(pidfile_path); printf("KeyVibe stopped.\n"); + if (sound_name_owned) { + free(sound_name); + } + if (mouse_sound_name_owned) { + free(mouse_sound_name); + } return 0; } struct timespec ts; @@ -148,6 +171,12 @@ int main(int argc, char *argv[]) { ts.tv_nsec = 100000000L; nanosleep(&ts, NULL); } + if (sound_name_owned) { + free(sound_name); + } + if (mouse_sound_name_owned) { + free(mouse_sound_name); + } return errorf("KeyVibe: process did not stop in time\n"); } current_mute = read_runtime_mute_file(); @@ -209,10 +238,10 @@ int main(int argc, char *argv[]) { if (!write_user_config(user_cfg_path, sound_name, mouse_sound_name, current_keyboard_volume, current_mouse_volume, current_keyboard_enabled, current_mouse_enabled)) { - fprintf(stderr, "Warning: Failed to update config file %s\n", + safe_fprintf(stderr, "Warning: Failed to update config file %s\n", user_cfg_path); } else if (verbose) { - fprintf(stderr, "Updated config file %s\n", user_cfg_path); + safe_fprintf(stderr, "Updated config file %s\n", user_cfg_path); } } @@ -232,9 +261,9 @@ int main(int argc, char *argv[]) { if (!write_user_config(user_cfg_path, sound_name, mouse_sound_name, current_keyboard_volume, current_mouse_volume, current_keyboard_enabled, current_mouse_enabled)) { - fprintf(stderr, "Warning: Failed to write %s\n", user_cfg_path); + safe_fprintf(stderr, "Warning: Failed to write %s\n", user_cfg_path); } else if (verbose) { - fprintf(stderr, "Created default config %s\n", user_cfg_path); + safe_fprintf(stderr, "Created default config %s\n", user_cfg_path); } } } @@ -258,20 +287,33 @@ int main(int argc, char *argv[]) { } char get_key_presses_path[MAX_PATH_LENGTH]; char sound_player_path[MAX_PATH_LENGTH]; - snprintf(get_key_presses_path, sizeof(get_key_presses_path), + safe_snprintf_wrapper(get_key_presses_path, sizeof(get_key_presses_path), "%s/keyvibe-input", KeyVibe_BIN_DIR); - snprintf(sound_player_path, sizeof(sound_player_path), "%s/keyvibe-audio", + safe_snprintf_wrapper(sound_player_path, sizeof(sound_player_path), "%s/keyvibe-audio", KeyVibe_BIN_DIR); if (access(get_key_presses_path, X_OK) != 0 || - access(sound_player_path, X_OK) != 0) + access(sound_player_path, X_OK) != 0) { + if (sound_name_owned) { + free(sound_name); + } + if (mouse_sound_name_owned) { + free(mouse_sound_name); + } return errorf("Error: Cannot find or execute required binaries in %s\n", KeyVibe_BIN_DIR); + } signal(SIGINT, cleanup_processes); signal(SIGTERM, cleanup_processes); if (flag_daemon) { pid_t existing = 0; if (read_pidfile(pidfile_path, &existing) && process_is_running(existing)) { - fprintf(stderr, + if (sound_name_owned) { + free(sound_name); + } + if (mouse_sound_name_owned) { + free(mouse_sound_name); + } + safe_fprintf(stderr, "KeyVibe already running (pid %ld). Use --stop to stop it.\n", (long)existing); return 1; @@ -309,21 +351,12 @@ int main(int argc, char *argv[]) { current_keyboard_volume = volume; current_mouse_volume = volume; current_verbose = verbose; - strncpy(current_sound_name, sound_name, sizeof(current_sound_name) - 1); - current_sound_name[sizeof(current_sound_name) - 1] = '\0'; - strncpy(current_mouse_sound_name, mouse_sound_name, - sizeof(current_mouse_sound_name) - 1); - current_mouse_sound_name[sizeof(current_mouse_sound_name) - 1] = '\0'; - strncpy(current_config_path, config_path, sizeof(current_config_path) - 1); - current_config_path[sizeof(current_config_path) - 1] = '\0'; - strncpy(current_sound_dir, sound_dir, sizeof(current_sound_dir) - 1); - current_sound_dir[sizeof(current_sound_dir) - 1] = '\0'; - strncpy(current_mouse_config_path, mouse_config_path, - sizeof(current_mouse_config_path) - 1); - current_mouse_config_path[sizeof(current_mouse_config_path) - 1] = '\0'; - strncpy(current_mouse_sound_dir, mouse_sound_dir, - sizeof(current_mouse_sound_dir) - 1); - current_mouse_sound_dir[sizeof(current_mouse_sound_dir) - 1] = '\0'; + safe_strncpy(current_sound_name, sound_name, sizeof(current_sound_name)); + safe_strncpy(current_mouse_sound_name, mouse_sound_name, sizeof(current_mouse_sound_name)); + safe_strncpy(current_config_path, config_path, sizeof(current_config_path)); + safe_strncpy(current_sound_dir, sound_dir, sizeof(current_sound_dir)); + safe_strncpy(current_mouse_config_path, mouse_config_path, sizeof(current_mouse_config_path)); + safe_strncpy(current_mouse_sound_dir, mouse_sound_dir, sizeof(current_mouse_sound_dir)); if (verbose && !is_daemon) { printf("KeyVibe starting...\n"); printf("Keyboard sound pack: %s\n", sound_name); @@ -348,6 +381,9 @@ int main(int argc, char *argv[]) { if (sound_name_owned) { free(sound_name); } + if (mouse_sound_name_owned) { + free(mouse_sound_name); + } return 1; } int status; diff --git a/src/soundpacks.c b/src/soundpacks.c index a321983..52184c6 100644 --- a/src/soundpacks.c +++ b/src/soundpacks.c @@ -18,26 +18,16 @@ static void get_user_keyboard_audio_dir(char *buffer, size_t buflen) { buffer[0] = '\0'; - const char *home = getenv("HOME"); - if (!home || strlen(home) == 0) { - struct passwd *pw = getpwuid(getuid()); - if (pw && pw->pw_dir) - home = pw->pw_dir; - } + const char *home = get_home_dir(); if (home) - snprintf(buffer, buflen, "%s%s", home, USER_KEYBOARD_AUDIO_SUBPATH); + safe_snprintf_wrapper(buffer, buflen, "%s%s", home, USER_KEYBOARD_AUDIO_SUBPATH); } static void get_user_mouse_audio_dir(char *buffer, size_t buflen) { buffer[0] = '\0'; - const char *home = getenv("HOME"); - if (!home || strlen(home) == 0) { - struct passwd *pw = getpwuid(getuid()); - if (pw && pw->pw_dir) - home = pw->pw_dir; - } + const char *home = get_home_dir(); if (home) - snprintf(buffer, buflen, "%s%s", home, USER_MOUSE_AUDIO_SUBPATH); + safe_snprintf_wrapper(buffer, buflen, "%s%s", home, USER_MOUSE_AUDIO_SUBPATH); } int resolve_keyboard_sound_base_dir(const char *sound_name, char *out_basedir, @@ -49,8 +39,7 @@ int resolve_keyboard_sound_base_dir(const char *sound_name, char *out_basedir, if ((size_t)snprintf(p, sizeof(p), "%s/%s/config.json", user_audio_dir, sound_name) < sizeof(p) && access(p, R_OK) == 0) { - strncpy(out_basedir, user_audio_dir, out_sz - 1); - out_basedir[out_sz - 1] = '\0'; + safe_strncpy(out_basedir, user_audio_dir, out_sz); return 1; } } @@ -60,8 +49,7 @@ int resolve_keyboard_sound_base_dir(const char *sound_name, char *out_basedir, return 0; } if (access(p2, R_OK) == 0) { - strncpy(out_basedir, KEYBOARD_AUDIO_DIR, out_sz - 1); - out_basedir[out_sz - 1] = '\0'; + safe_strncpy(out_basedir, KEYBOARD_AUDIO_DIR, out_sz); return 1; } return 0; @@ -76,8 +64,7 @@ int resolve_mouse_sound_base_dir(const char *sound_name, char *out_basedir, if ((size_t)snprintf(p, sizeof(p), "%s/%s/config.json", user_audio_dir, sound_name) < sizeof(p) && access(p, R_OK) == 0) { - strncpy(out_basedir, user_audio_dir, out_sz - 1); - out_basedir[out_sz - 1] = '\0'; + safe_strncpy(out_basedir, user_audio_dir, out_sz); return 1; } } @@ -87,8 +74,7 @@ int resolve_mouse_sound_base_dir(const char *sound_name, char *out_basedir, return 0; } if (access(p2, R_OK) == 0) { - strncpy(out_basedir, MOUSE_AUDIO_DIR, out_sz - 1); - out_basedir[out_sz - 1] = '\0'; + safe_strncpy(out_basedir, MOUSE_AUDIO_DIR, out_sz); return 1; } return 0;