From: Andrew Burgess Date: Thu, 15 Jan 2026 10:28:45 +0000 (+0000) Subject: gdb: fix handling of raw ANSI escape sequences printed from Python X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=48d2b03a7c17d02799c5a6f2b3db096b59c017e4;p=thirdparty%2Fbinutils-gdb.git 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 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33748 Approved-By: Tom Tromey --- 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 . + +# 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) {