--- a/sys/ddb/db_variables.c +++ b/sys/ddb/db_variables.c @@ -40,19 +40,58 @@ static int db_find_variable (struct db_variable **varp); static void db_write_variable (struct db_variable *, db_expr_t *); +static int db_radix_fcn (struct db_variable *, db_expr_t *, int); +static int db_maxoff_fcn (struct db_variable *, db_expr_t *, int); #ifdef notused static int db_set_variable (db_expr_t value); #endif static struct db_variable db_vars[] = { - { "radix", &db_radix, NULL }, - { "maxoff", &db_maxoff, NULL }, + { "radix", &db_radix, db_radix_fcn }, + { "maxoff", &db_maxoff, db_maxoff_fcn }, { "maxwidth", &db_max_width, NULL }, { "tabstops", &db_tab_stop_width, NULL }, }; static struct db_variable *db_evars = db_vars + NELEM(db_vars); +/* + * $radix and $maxoff are settable from the ddb console with no other + * validation. A radix outside {8,10,16} silently corrupts the expression + * language itself: db_lex() parses every subsequent number literal in that + * base and accepts digits invalid for it (db_lex.c:190-205), including the + * values of later `set' commands; recovery requires the forced 0x/0t + * prefixes. A negative maxoff casts to ULONG_MAX and inverts the symbol + * attribution threshold (db_sym.c:289), misattributing distant raw + * addresses to unrelated symbols. Complements DF-5724's fix, which adds + * validating setters for $tabstops and $maxwidth. + */ +static int +db_radix_fcn(struct db_variable *vp, db_expr_t *valuep, int op) +{ + if (op == DB_VAR_SET) { + if (*valuep != 8 && *valuep != 10 && *valuep != 16) + db_error("radix must be 8, 10 or 16\n"); + db_radix = *valuep; + } else { + *valuep = db_radix; + } + return (0); +} + +static int +db_maxoff_fcn(struct db_variable *vp, db_expr_t *valuep, int op) +{ + if (op == DB_VAR_SET) { + if (*valuep < 0) + db_error("maxoff must be >= 0\n"); + db_maxoff = *valuep; + } else { + *valuep = db_maxoff; + } + return (0); +} + static int db_find_variable(struct db_variable **varp) {