[binutils-gdb] gdb: fix handling of raw ANSI escape sequences printed from Python

Andrew Burgess aburgess@sourceware.org
Thu Jan 15 17:44:50 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=48d2b03a7c17d02799c5a6f2b3db096b59c017e4

commit 48d2b03a7c17d02799c5a6f2b3db096b59c017e4
Author: Andrew Burgess <aburgess@redhat.com>
Date:   Thu Jan 15 10:28:45 2026 +0000

    gdb: fix handling of raw ANSI escape sequences printed from Python
    
    Bug PR gdb/33748 reports a regression with print styled output from
    Python when using ANSI escape sequences to apply the styling.  This
    regression was introduced by commit:
    
      commit 3825c972a636852600b47c242826313f4b9963b8
      Date:   Wed Jun 18 15:02:29 2025 +0100
    
          gdb: allow gdb.Color to work correctly with pagination
    
    Prior to this commit GDB would always forward any ANSI escape
    sequences directly to the output stream, but this meant that GDB
    didn't know which style was currently in effect.
    
    The above commit changed GDB so that we would parse the ANSI escape
    sequence, and then apply it to the output stream, this allowed GDB to
    track which style was in use, which in turn meant that GDB could
    correctly suspend the style and reapply it when the pager was
    activated.
    
    The problem though is that ANSI escape sequences can be built up in
    parts.  For example, a user can emit the sequence to change the
    foreground blue, and then later emit the sequence to change the text
    to bold.  The result is output that is both blue and bold.
    
    In the above commit, when parsing an incoming ANSI sequence, GDB was
    always starting from the default styling state.  The result of parsing
    the ANSI sequence was then being applied.  In our above example, this
    meant that when parsing the sequence for bold text we would "forget"
    that the current style had a blue foreground color.
    
    This can be easily fixed by starting from the current style, rather
    than the default style.
    
    This fix was suggested by Patryk Sondej who originally reported the
    bug.
    
    Co-Authored-By: Patryk Sondej <patryk.sondej@gmail.com>
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33748
    
    Approved-By: Tom Tromey <tom@tromey.com>

Diff:
---
 gdb/testsuite/gdb.python/py-color-via-ansi-esc.exp | 70 ++++++++++++++++++++++
 gdb/utils.c                                        |  5 +-
 2 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/gdb/testsuite/gdb.python/py-color-via-ansi-esc.exp b/gdb/testsuite/gdb.python/py-color-via-ansi-esc.exp
new file mode 100644
index 00000000000..9aac552fe1a
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-color-via-ansi-esc.exp
@@ -0,0 +1,70 @@
+# Copyright (C) 2026 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.  It tests styled output from
+# Python via raw ANSI escape sequences.
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+require {!is_remote host}
+
+# Start with a fresh GDB, but enable color support.
+with_ansi_styling_terminal {
+    clean_restart
+}
+
+# Create two variables in the parent scope called ${NAME} and
+# ${NAME}_re.  The variable ${NAME} will be the string for the ANSI
+# escape sequence containing VALUE, and ${NAME}_re will be the regular
+# expression to match that same sequence.
+proc setup_ansi { name value } {
+    upvar 1 $name var
+    upvar 1 ${name}_re var_re
+
+    set var "\\033\[${value}m"
+    set var_re "\033\\\[${value}m"
+}
+
+# Different colors.
+setup_ansi red 31
+setup_ansi green 32
+setup_ansi blue 34
+
+# Different intensities.
+setup_ansi normal 22
+setup_ansi bold 1
+setup_ansi dim 2
+
+# Italic.
+setup_ansi italic 3
+setup_ansi no_italic 23
+
+# Underline.
+setup_ansi underline 4
+setup_ansi no_underline 24
+
+# Restore all settings to default.
+setup_ansi default 0
+
+gdb_test_no_output "python flag=\"OUTPUT=\""
+
+gdb_test "python print('%s${blue}blue ${bold}blue+bold ${green}green+bold ${normal}green ${red}red${default}' % (flag))" \
+    "OUTPUT=${blue_re}blue ${bold_re}blue\\+bold ${green_re}green\\+bold ${normal_re}green ${red_re}red${default_re}" \
+    "foreground colors and bold"
+
+gdb_test "python print('%snormal ${italic}italic ${underline}italic+underline ${no_underline}italic ${no_italic}normal' % (flag))" \
+    "OUTPUT=normal ${italic_re}italic ${underline_re}italic\\+underline ${no_underline_re}italic ${no_italic_re}normal" \
+    "italic and underline"
diff --git a/gdb/utils.c b/gdb/utils.c
index 876aad1c448..8c5f34b9687 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -1703,8 +1703,11 @@ pager_file::puts (const char *linebuffer)
 	      /* We don't consider escape sequences as characters, so we
 		 don't increment chars_printed here.  */
 
+	      /* This style sequence might not set every style attribute,
+		 so start with the currently applied style, and update
+		 that.  */
 	      size_t style_len;
-	      ui_file_style style;
+	      ui_file_style style = m_applied_style;
 	      if (style.parse (linebuffer, &style_len)
 		  && style_len <= skip_bytes)
 		{


More information about the Gdb-cvs mailing list