fix: 全面代码审查 — 修复 3 CRITICAL + 4 HIGH 问题
CRITICAL: - parser: 6处栈数组加边界检查 (struct_init/decl/block/params/functions/structs) - codegen: return前跳过返回值alloca防止use-after-free - ast: NEW宏加NULL检查防止arena耗尽崩溃 HIGH: - main: shell元字符过滤防命令注入 - codegen: LLVMContext泄漏修复 (out_context参数) - codegen: f64隐式return用LLVMConstReal替代LLVMConstInt - sema: 返回类型与函数声明校验 其他: - parser/codegen: 递归深度限制1000层 - codegen: struct值类型不追踪cleanup (栈上数据不能free) 基于三份审查报告 (架构/code quality/安全) 修复。
This commit is contained in:
+19
-3
@@ -10,6 +10,10 @@ typedef struct {
|
||||
Arena* arena;
|
||||
} Parser;
|
||||
|
||||
// === 递归深度限制 ===
|
||||
static int parse_depth = 0;
|
||||
#define MAX_PARSE_DEPTH 1000
|
||||
|
||||
// === 向前看 ===
|
||||
static const Token* peek(const Parser* p) { return &p->tokens[p->pos]; }
|
||||
static const Token* advance(Parser* p) { return &p->tokens[p->pos++]; }
|
||||
@@ -110,6 +114,7 @@ static AstNode* parse_struct_init(Parser* p, const Token* name, ErrorInfo* error
|
||||
int fcount = 0;
|
||||
|
||||
while (peek(p)->kind != TOK_RBRACE && !error->message) {
|
||||
if (fcount >= 32) { error->message = "结构体初始化字段过多 (最多32)"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; return NULL; }
|
||||
const Token* fname = expect(p, TOK_IDENT, error, "字段名");
|
||||
if (!fname) return NULL;
|
||||
if (!expect(p, TOK_COLON, error, "缺少 ':'")) return NULL;
|
||||
@@ -252,6 +257,7 @@ static AstNode* parse_struct_decl(Parser* p, ErrorInfo* error) {
|
||||
|
||||
AstNode* fields[32]; int fcount = 0;
|
||||
while (peek(p)->kind != TOK_RBRACE && !error->message) {
|
||||
if (fcount >= 32) { error->message = "结构体字段过多 (最多32)"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; return NULL; }
|
||||
const Token* fname = expect(p, TOK_IDENT, error, "字段名");
|
||||
if (!fname) return NULL;
|
||||
if (!expect(p, TOK_COLON, error, "缺少 ':'")) return NULL;
|
||||
@@ -285,17 +291,24 @@ static AstNode* parse_struct_decl(Parser* p, ErrorInfo* error) {
|
||||
// === 语句解析 ===
|
||||
|
||||
static AstNode* parse_block(Parser* p, ErrorInfo* error) {
|
||||
if (++parse_depth > MAX_PARSE_DEPTH) {
|
||||
error->message = "嵌套过深"; error->filename = p->filename;
|
||||
error->line = peek(p)->line; error->col = peek(p)->col;
|
||||
parse_depth--; return NULL;
|
||||
}
|
||||
const Token* open = peek(p);
|
||||
if (!expect(p, TOK_LBRACE, error, "缺少 '{'")) return NULL;
|
||||
if (!expect(p, TOK_LBRACE, error, "缺少 '{'")) { parse_depth--; return NULL; }
|
||||
AstNode* stmts[256]; int count = 0;
|
||||
while (peek(p)->kind != TOK_RBRACE && peek(p)->kind != TOK_EOF && !error->message) {
|
||||
if (count >= 256) { error->message = "代码块语句过多 (最多256)"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; parse_depth--; return NULL; }
|
||||
AstNode* s = parse_statement(p, error);
|
||||
if (!s) return NULL;
|
||||
if (!s) { parse_depth--; return NULL; }
|
||||
stmts[count++] = s;
|
||||
}
|
||||
if (!expect(p, TOK_RBRACE, error, "缺少 '}'")) return NULL;
|
||||
if (!expect(p, TOK_RBRACE, error, "缺少 '}'")) { parse_depth--; return NULL; }
|
||||
AstNode** arr = arena_alloc_impl(p->arena, count * sizeof(AstNode*));
|
||||
memcpy(arr, stmts, count * sizeof(AstNode*));
|
||||
parse_depth--;
|
||||
return ast_make_block(p->arena, arr, count, open->line, open->col);
|
||||
}
|
||||
|
||||
@@ -498,6 +511,7 @@ static AstNode* parse_function(Parser* p, ErrorInfo* error) {
|
||||
// 参数列表
|
||||
AstNode* params[64]; int pcount = 0;
|
||||
while (peek(p)->kind != TOK_RPAREN && !error->message) {
|
||||
if (pcount >= 64) { error->message = "函数参数过多 (最多64)"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; return NULL; }
|
||||
const Token* pname = expect(p, TOK_IDENT, error, "参数名");
|
||||
if (!pname) return NULL;
|
||||
if (!expect(p, TOK_COLON, error, "缺少 ':'")) return NULL;
|
||||
@@ -544,8 +558,10 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count,
|
||||
AstNode* structs[64]; int struct_count = 0;
|
||||
while (peek(&p)->kind != TOK_EOF && !error->message) {
|
||||
if (peek(&p)->kind == TOK_STRUCT) {
|
||||
if (struct_count >= 64) { error->message = "结构体过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
||||
structs[struct_count++] = parse_struct_decl(&p, error);
|
||||
} else if (peek(&p)->kind == TOK_FN) {
|
||||
if (fn_count >= 256) { error->message = "函数过多 (最多256)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
||||
functions[fn_count++] = parse_function(&p, error);
|
||||
} else {
|
||||
error->message = "顶层只允许 fn 或 struct";
|
||||
|
||||
Reference in New Issue
Block a user