diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 114e19e8..a5f2391b 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -591,27 +591,29 @@ static char *combine_args_until_empty(char *values[], int count) { // plus the number of commas (first_empty-1 commas) total_len += (first_empty - 1); - // allocate memory and concatenate + // allocate memory and concatenate safely char *combined = malloc(total_len + 1); if (combined == NULL) { return strdup(""); } - combined[0] = '\0'; - size_t current_len = 0; + char *ptr = combined; + size_t remaining = total_len + 1; // Include space for null terminator + for (int i = 0; i < first_empty; i++) { - if (i > 0 && current_len < total_len) { - strncat(combined, ",", total_len - current_len); - current_len++; + if (i > 0 && remaining > 1) { + *ptr++ = ','; + remaining--; } - if (current_len < total_len) { - size_t remaining = total_len - current_len; + if (remaining > 1) { size_t val_len = strlen(values[i]); - size_t will_add = (val_len < remaining) ? val_len : remaining; - strncat(combined, values[i], remaining); - current_len += will_add; + size_t to_copy = (val_len < remaining - 1) ? val_len : remaining - 1; + memcpy(ptr, values[i], to_copy); + ptr += to_copy; + remaining -= to_copy; } } + *ptr = '\0'; // Null terminate return combined; } diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index 4407f981..7a24417b 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -836,7 +836,9 @@ int32_t spawn(const Arg *arg) { // 2. 解析参数 char *argv[64]; + char *allocated_strings[64]; // Track strdup'd strings for cleanup int32_t argc = 0; + int32_t alloc_count = 0; char *token = strtok((char *)arg->v, " "); while (token != NULL && argc < 63) { @@ -846,6 +848,7 @@ int32_t spawn(const Arg *arg) { argv[argc] = strdup(p.we_wordv[0]); wordfree(&p); // Free immediately after copying if (argv[argc] != NULL) { + allocated_strings[alloc_count++] = argv[argc]; argc++; } } else { @@ -859,9 +862,12 @@ int32_t spawn(const Arg *arg) { // 3. 执行命令 execvp(argv[0], argv); - // 4. execvp 失败时打印错误并退出 - // Note: We don't need to free here since we're about to _exit - // The OS will clean up when the process exits + // 4. execvp 失败时:清理并退出 + // If execvp succeeds, this code never runs (process replaced) + // If it fails, clean up allocated strings before exiting + for (int i = 0; i < alloc_count; i++) { + free(allocated_strings[i]); + } wlr_log(WLR_ERROR, "mango: execvp '%s' failed: %s\n", argv[0], strerror(errno)); _exit(EXIT_FAILURE); // 使用 _exit 避免缓冲区刷新等操作