mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-05-03 06:46:38 -04:00
Merge pull request #2 from squassina/copilot/fix-security-issues
Fix critical security vulnerabilities in string handling and memory management
This commit is contained in:
commit
30d6acea0c
4 changed files with 75 additions and 17 deletions
1
_codeql_detected_source_root
Symbolic link
1
_codeql_detected_source_root
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
.
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
@ -537,11 +538,20 @@ int32_t parse_fold_state(const char *str) {
|
||||||
}
|
}
|
||||||
int64_t parse_color(const char *hex_str) {
|
int64_t parse_color(const char *hex_str) {
|
||||||
char *endptr;
|
char *endptr;
|
||||||
int64_t hex_num = strtol(hex_str, &endptr, 16);
|
errno = 0;
|
||||||
if (*endptr != '\0') {
|
uint64_t hex_num = strtoul(hex_str, &endptr, 16);
|
||||||
|
|
||||||
|
// Check for conversion errors
|
||||||
|
if (*endptr != '\0' || errno == ERANGE) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return hex_num;
|
|
||||||
|
// Validate range for color values (0x00000000 to 0xFFFFFFFF)
|
||||||
|
if (hex_num > 0xFFFFFFFF) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int64_t)hex_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 辅助函数:检查字符串是否以指定的前缀开头(忽略大小写)
|
// 辅助函数:检查字符串是否以指定的前缀开头(忽略大小写)
|
||||||
|
|
@ -581,19 +591,32 @@ static char *combine_args_until_empty(char *values[], int count) {
|
||||||
// plus the number of commas (first_empty-1 commas)
|
// plus the number of commas (first_empty-1 commas)
|
||||||
total_len += (first_empty - 1);
|
total_len += (first_empty - 1);
|
||||||
|
|
||||||
// allocate memory and concatenate
|
// allocate memory and concatenate safely
|
||||||
char *combined = malloc(total_len + 1);
|
char *combined = malloc(total_len + 1);
|
||||||
if (combined == NULL) {
|
if (combined == NULL) {
|
||||||
return strdup("");
|
return strdup("");
|
||||||
}
|
}
|
||||||
|
|
||||||
combined[0] = '\0';
|
char *ptr = combined;
|
||||||
|
size_t remaining = total_len + 1; // Include space for null terminator
|
||||||
|
|
||||||
for (int i = 0; i < first_empty; i++) {
|
for (int i = 0; i < first_empty; i++) {
|
||||||
if (i > 0) {
|
if (i > 0 && remaining > 1) {
|
||||||
strcat(combined, ",");
|
*ptr++ = ',';
|
||||||
|
remaining--;
|
||||||
|
}
|
||||||
|
if (remaining > 1) {
|
||||||
|
size_t val_len = strlen(values[i]);
|
||||||
|
// Always leave space for null terminator
|
||||||
|
size_t to_copy = (val_len < remaining - 1) ? val_len : remaining - 1;
|
||||||
|
if (to_copy > 0) {
|
||||||
|
memcpy(ptr, values[i], to_copy);
|
||||||
|
ptr += to_copy;
|
||||||
|
remaining -= to_copy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
strcat(combined, values[i]);
|
|
||||||
}
|
}
|
||||||
|
*ptr = '\0'; // Null terminate
|
||||||
|
|
||||||
return combined;
|
return combined;
|
||||||
}
|
}
|
||||||
|
|
@ -626,8 +649,10 @@ uint32_t parse_mod(const char *mod_str) {
|
||||||
if (strncmp(token, "code:", 5) == 0) {
|
if (strncmp(token, "code:", 5) == 0) {
|
||||||
// 处理 code: 形式
|
// 处理 code: 形式
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
errno = 0;
|
||||||
long keycode = strtol(token + 5, &endptr, 10);
|
long keycode = strtol(token + 5, &endptr, 10);
|
||||||
if (endptr != token + 5 && (*endptr == '\0' || *endptr == ' ')) {
|
// Check for conversion errors: overflow or no conversion
|
||||||
|
if (endptr != token + 5 && (*endptr == '\0' || *endptr == ' ') && errno != ERANGE) {
|
||||||
switch (keycode) {
|
switch (keycode) {
|
||||||
case 133:
|
case 133:
|
||||||
case 134:
|
case 134:
|
||||||
|
|
@ -777,7 +802,16 @@ KeySymCode parse_key(const char *key_str, bool isbindsym) {
|
||||||
// 处理 code: 前缀的情况
|
// 处理 code: 前缀的情况
|
||||||
if (strncmp(key_str, "code:", 5) == 0) {
|
if (strncmp(key_str, "code:", 5) == 0) {
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
errno = 0;
|
||||||
xkb_keycode_t keycode = (xkb_keycode_t)strtol(key_str + 5, &endptr, 10);
|
xkb_keycode_t keycode = (xkb_keycode_t)strtol(key_str + 5, &endptr, 10);
|
||||||
|
|
||||||
|
// Validate conversion
|
||||||
|
if (errno == ERANGE || *endptr != '\0') {
|
||||||
|
kc.type = KEY_TYPE_SYM;
|
||||||
|
kc.keysym = XKB_KEY_NoSymbol;
|
||||||
|
return kc;
|
||||||
|
}
|
||||||
|
|
||||||
kc.type = KEY_TYPE_CODE;
|
kc.type = KEY_TYPE_CODE;
|
||||||
kc.keycode.keycode1 = keycode; // 只设置第一个
|
kc.keycode.keycode1 = keycode; // 只设置第一个
|
||||||
kc.keycode.keycode2 = 0;
|
kc.keycode.keycode2 = 0;
|
||||||
|
|
@ -2284,7 +2318,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
trim_whitespace(arg_value4);
|
trim_whitespace(arg_value4);
|
||||||
trim_whitespace(arg_value5);
|
trim_whitespace(arg_value5);
|
||||||
|
|
||||||
strcpy(binding->mode, config->keymode);
|
strncpy(binding->mode, config->keymode, sizeof(binding->mode) - 1);
|
||||||
|
binding->mode[sizeof(binding->mode) - 1] = '\0';
|
||||||
if (strcmp(binding->mode, "common") == 0) {
|
if (strcmp(binding->mode, "common") == 0) {
|
||||||
binding->iscommonmode = true;
|
binding->iscommonmode = true;
|
||||||
binding->isdefaultmode = false;
|
binding->isdefaultmode = false;
|
||||||
|
|
@ -3479,7 +3514,8 @@ bool parse_config(void) {
|
||||||
config.tag_rules = NULL;
|
config.tag_rules = NULL;
|
||||||
config.tag_rules_count = 0;
|
config.tag_rules_count = 0;
|
||||||
config.cursor_theme = NULL;
|
config.cursor_theme = NULL;
|
||||||
strcpy(config.keymode, "default");
|
strncpy(config.keymode, "default", sizeof(config.keymode) - 1);
|
||||||
|
config.keymode[sizeof(config.keymode) - 1] = '\0';
|
||||||
|
|
||||||
create_config_keymap();
|
create_config_keymap();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -836,14 +836,24 @@ int32_t spawn(const Arg *arg) {
|
||||||
|
|
||||||
// 2. 解析参数
|
// 2. 解析参数
|
||||||
char *argv[64];
|
char *argv[64];
|
||||||
|
char *allocated_strings[64]; // Track strdup'd strings for cleanup
|
||||||
int32_t argc = 0;
|
int32_t argc = 0;
|
||||||
|
int32_t alloc_count = 0;
|
||||||
|
|
||||||
char *token = strtok((char *)arg->v, " ");
|
char *token = strtok((char *)arg->v, " ");
|
||||||
while (token != NULL && argc < 63) {
|
while (token != NULL && argc < 63) {
|
||||||
wordexp_t p;
|
wordexp_t p;
|
||||||
if (wordexp(token, &p, 0) == 0) {
|
if (wordexp(token, &p, 0) == 0 && p.we_wordc > 0) {
|
||||||
argv[argc++] = p.we_wordv[0];
|
// Duplicate the string since we'll free the wordexp result
|
||||||
|
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 {
|
} else {
|
||||||
argv[argc++] = token;
|
argv[argc] = token;
|
||||||
|
argc++;
|
||||||
}
|
}
|
||||||
token = strtok(NULL, " ");
|
token = strtok(NULL, " ");
|
||||||
}
|
}
|
||||||
|
|
@ -852,7 +862,12 @@ int32_t spawn(const Arg *arg) {
|
||||||
// 3. 执行命令
|
// 3. 执行命令
|
||||||
execvp(argv[0], argv);
|
execvp(argv[0], argv);
|
||||||
|
|
||||||
// 4. execvp 失败时:打印错误并直接退出(避免 coredump)
|
// 4. execvp 失败时:清理并退出
|
||||||
|
// If execvp succeeds, this code never runs (process replaced)
|
||||||
|
// If it fails, clean up allocated strings before exiting
|
||||||
|
for (int32_t i = 0; i < alloc_count; i++) {
|
||||||
|
free(allocated_strings[i]);
|
||||||
|
}
|
||||||
wlr_log(WLR_ERROR, "mango: execvp '%s' failed: %s\n", argv[0],
|
wlr_log(WLR_ERROR, "mango: execvp '%s' failed: %s\n", argv[0],
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
_exit(EXIT_FAILURE); // 使用 _exit 避免缓冲区刷新等操作
|
_exit(EXIT_FAILURE); // 使用 _exit 避免缓冲区刷新等操作
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,9 @@ int32_t isdescprocess(pid_t p, pid_t c) {
|
||||||
return (int32_t)c;
|
return (int32_t)c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Buffer size for layout abbreviations (must match kb_layout buffer in dwl-ipc.h)
|
||||||
|
#define LAYOUT_ABBR_SIZE 32
|
||||||
|
|
||||||
void get_layout_abbr(char *abbr, const char *full_name) {
|
void get_layout_abbr(char *abbr, const char *full_name) {
|
||||||
// 清空输出缓冲区
|
// 清空输出缓冲区
|
||||||
abbr[0] = '\0';
|
abbr[0] = '\0';
|
||||||
|
|
@ -33,7 +36,8 @@ void get_layout_abbr(char *abbr, const char *full_name) {
|
||||||
// 1. 尝试在映射表中查找
|
// 1. 尝试在映射表中查找
|
||||||
for (int32_t i = 0; layout_mappings[i].full_name != NULL; i++) {
|
for (int32_t i = 0; layout_mappings[i].full_name != NULL; i++) {
|
||||||
if (strcmp(full_name, layout_mappings[i].full_name) == 0) {
|
if (strcmp(full_name, layout_mappings[i].full_name) == 0) {
|
||||||
strcpy(abbr, layout_mappings[i].abbr);
|
strncpy(abbr, layout_mappings[i].abbr, LAYOUT_ABBR_SIZE - 1);
|
||||||
|
abbr[LAYOUT_ABBR_SIZE - 1] = '\0';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +77,9 @@ void get_layout_abbr(char *abbr, const char *full_name) {
|
||||||
abbr[2] = '\0';
|
abbr[2] = '\0';
|
||||||
} else {
|
} else {
|
||||||
// 5. 最终回退:返回 "xx"
|
// 5. 最终回退:返回 "xx"
|
||||||
strcpy(abbr, "xx");
|
abbr[0] = 'x';
|
||||||
|
abbr[1] = 'x';
|
||||||
|
abbr[2] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue