From 3041b9313e360af215e235e4d07f9557a22ffd13 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Sat, 12 Feb 2022 18:41:34 -0700 Subject: [PATCH] Fix a latent bug in print_wchar print_wchar keeps track of when escape sequences are emitted, to force an escape sequence if needed by a subsequent character. For example for the string concatenation "\0" "1", gdb will print "\000\061" -- because printing "\0001" might be confusing. However, this code has two errors. First, this logic is not needed for octal escapes, because there is a length limit of 3 for octal escapes, and gdb always prints these with "%.3o". Second, though, this *is* needed for hex escapes, because those do not have a length limit. This patch fixes these problems and adds the appropriate tests. --- gdb/gdb_wchar.h | 4 ++-- gdb/testsuite/gdb.base/charset.exp | 8 ++++++++ gdb/valprint.c | 22 ++++++++++++++-------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/gdb/gdb_wchar.h b/gdb/gdb_wchar.h index ba5baf3a2a0..8c6e4fc9fd6 100644 --- a/gdb/gdb_wchar.h +++ b/gdb/gdb_wchar.h @@ -66,7 +66,7 @@ typedef wint_t gdb_wint_t; #define gdb_wcslen wcslen #define gdb_iswprint iswprint -#define gdb_iswdigit iswdigit +#define gdb_iswxdigit iswxdigit #define gdb_btowc btowc #define gdb_WEOF WEOF @@ -103,7 +103,7 @@ typedef int gdb_wint_t; #define gdb_wcslen strlen #define gdb_iswprint isprint -#define gdb_iswdigit isdigit +#define gdb_iswxdigit isxdigit #define gdb_btowc /* empty */ #define gdb_WEOF EOF diff --git a/gdb/testsuite/gdb.base/charset.exp b/gdb/testsuite/gdb.base/charset.exp index 5df2ec1a8de..359968df696 100644 --- a/gdb/testsuite/gdb.base/charset.exp +++ b/gdb/testsuite/gdb.base/charset.exp @@ -503,6 +503,11 @@ gdb_test "print '\\9'" " = \[0-9\]+ '9'" # An octal escape can only be 3 digits. gdb_test "print \"\\1011\"" " = \"A1\"" +# The final digit does not need to be escaped here. +foreach val {0 1 2 3 4 5 6 7 8 9 a b c d e f} { + gdb_test "print \"\\0\" \"${val}\"" " = \"\\\\000${val}\"" +} + # Tests for wide- or unicode- strings. L is the prefix letter to use, # either "L" (for wide strings), "u" (for UTF-16), or "U" (for UTF-32). # NAME is used in the test names and should be related to the prefix @@ -519,6 +524,9 @@ proc test_wide_or_unicode {L name} { gdb_test "print $L\"\" \"abcdef\" \"g\"" \ "$L\"abcdefg\"" \ "concatenate three strings with empty $name string" + gdb_test "print $L\"\\xffef\" $L\"f\"" \ + "$L\"\\\\xffef\\\\146\"" \ + "test multi-char escape sequence case for $name" gdb_test "print $L'a'" "= \[0-9\]+ $L'a'" \ "basic $name character" diff --git a/gdb/valprint.c b/gdb/valprint.c index 5a2f4dfc62a..f079f31fa7b 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -2108,9 +2108,7 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, break; default: { - if (gdb_iswprint (w) && (!need_escape || (!gdb_iswdigit (w) - && w != LCST ('8') - && w != LCST ('9')))) + if (gdb_iswprint (w) && !(need_escape && gdb_iswxdigit (w))) { gdb_wchar_t wchar = w; @@ -2132,10 +2130,19 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, /* If the value fits in 3 octal digits, print it that way. Otherwise, print it as a hex escape. */ if (value <= 0777) - xsnprintf (octal, sizeof (octal), "\\%.3o", - (int) (value & 0777)); + { + xsnprintf (octal, sizeof (octal), "\\%.3o", + (int) (value & 0777)); + *need_escapep = false; + } else - xsnprintf (octal, sizeof (octal), "\\x%lx", (long) value); + { + xsnprintf (octal, sizeof (octal), "\\x%lx", (long) value); + /* A hex escape might require the next character + to be escaped, because, unlike with octal, + hex escapes have no length limit. */ + *need_escapep = true; + } append_string_as_wide (octal, output); } /* If we somehow have extra bytes, print them now. */ @@ -2144,11 +2151,10 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, char octal[5]; xsnprintf (octal, sizeof (octal), "\\%.3o", orig[i] & 0xff); + *need_escapep = false; append_string_as_wide (octal, output); ++i; } - - *need_escapep = true; } break; } -- 2.30.2