Fix remaining memory and buffer issues

- Use memcpy with pointer arithmetic for safe string concatenation
- Track and free allocated strings in spawn error path
- Properly account for null terminator in all buffer operations
- Eliminate potential buffer overflows from strncat edge cases

Co-authored-by: squassina <8495707+squassina@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-02-18 09:03:32 +00:00
parent 5d145cc80f
commit 969c68b66d
2 changed files with 22 additions and 14 deletions

View file

@ -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;
}

View file

@ -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 避免缓冲区刷新等操作