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');

Reply via email to