diff --git a/sys/ddb/db_expr.c b/sys/ddb/db_expr.c --- a/sys/ddb/db_expr.c +++ b/sys/ddb/db_expr.c @@ -43,6 +43,20 @@ static boolean_t db_term (db_expr_t *valuep); static boolean_t db_unary (db_expr_t *valuep); +/* + * Maximum parenthesis nesting depth accepted by the expression parser. + * Each '(' costs 272 bytes of kernel stack in the DDB context (measured + * on X86_64_GENERIC: db_term 32 + db_expression 16 + db_shift_expr 64 + + * db_add_expr 64 + db_mult_expr 64 + db_unary 32), and DDB runs on the + * interrupted context's 16 KB kernel stack, so unbounded nesting (the + * 120-char ddb line allows 120 levels = ~32 KB) overflows into the stack + * guard page (double fault / panic). 16 levels caps the parser's + * recursion at ~4.4 KB. db_expr_depth is reset by db_flush_lex() + * so that db_error() longjmps out of the parser cannot leave it stale. + */ +#define DB_MAX_EXPR_DEPTH 16 +int db_expr_depth; + static boolean_t db_term(db_expr_t *valuep) { @@ -225,5 +239,12 @@ int db_expression(db_expr_t *valuep) { - return (db_shift_expr(valuep)); + int rv; + + if (db_expr_depth >= DB_MAX_EXPR_DEPTH) + db_error("Expression too deep\n"); + db_expr_depth++; + rv = db_shift_expr(valuep); + db_expr_depth--; + return (rv); } diff --git a/sys/ddb/db_lex.c b/sys/ddb/db_lex.c --- a/sys/ddb/db_lex.c +++ b/sys/ddb/db_lex.c @@ -42,6 +42,8 @@ static char db_line[120]; static char * db_lp, *db_endlp; +extern int db_expr_depth; /* db_expr.c; reset on abort paths */ + static int db_lex (void); static void db_flush_line (void); static int db_read_char (void); @@ -153,6 +155,7 @@ db_flush_line(); db_look_char = 0; db_look_token = 0; + db_expr_depth = 0; } static int