The ddb variable table accesses db_max_line, db_max_width and
db_tab_stop_width through db_expr_t pointers, but their definitions
use int. On 64-bit kernels, assigning these variables overwrites
adjacent storage. In particular, setting $lines cleared the tab width
and caused division by zero during tab expansion.
Define all three variables as db_expr_t. For non-positive tab widths,
avoid division in NEXT_TAB() and emit pending whitespace as spaces so
db_force_whitespace() keeps advancing. This also changes invalid-width
handling on 32-bit kernels.
Tested in the serial-console debugger on i386 and amd64 with tab widths
0, -1, 4 and 8; output completed and variable values were preserved.
---
ddb/db_output.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/ddb/db_output.c b/ddb/db_output.c
index
9a76f545604d374f0dfb833dee6b9bf8da195881..bff1de99b0a10fdccbbc15301941cdf6972bf2a2
100644
--- a/ddb/db_output.c
+++ b/ddb/db_output.c
@@ -69,11 +69,14 @@
int db_output_position = 0; /* output column */
int db_output_line = 0; /* output line number */
int db_last_non_space = 0; /* last non-space character */
-int db_tab_stop_width = 8; /* how wide are tab stops? */
+/* Accessed through db_expr_t pointers in db_variables.c. */
+db_expr_t db_tab_stop_width = 8; /* how wide are tab stops? */
#define NEXT_TAB(i) \
- ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
-int db_max_line = DB_MAX_LINE; /* output max lines */
-int db_max_width = DB_MAX_WIDTH; /* output line width */
+ ((db_tab_stop_width > 0) \
+ ? ((((i) + db_tab_stop_width) / db_tab_stop_width) *
db_tab_stop_width) \
+ : (i))
+db_expr_t db_max_line = DB_MAX_LINE; /* output max lines */
+db_expr_t db_max_width = DB_MAX_WIDTH; /* output line width */
/*
* Force pending whitespace.
@@ -85,6 +88,12 @@ db_force_whitespace(void)
last_print = db_last_non_space;
while (last_print < db_output_position) {
+ if (db_tab_stop_width <= 0) {
+ /* Use spaces because NEXT_TAB() cannot advance at this width.
*/
+ cnputc(' ');
+ last_print++;
+ continue;
+ }
next_tab = NEXT_TAB(last_print);
if (next_tab <= db_output_position) {
cnputc('\t');