NetBSD Problem Report #59549

From wiz@exadelic.gatalith.at  Thu Jul 24 13:58:29 2025
Return-Path: <wiz@exadelic.gatalith.at>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
	 client-signature RSA-PSS (2048 bits) client-digest SHA256)
	(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 62D481A923C
	for <gnats-bugs@gnats.NetBSD.org>; Thu, 24 Jul 2025 13:58:29 +0000 (UTC)
Message-Id: <20250724135823.7F99A2EBBAA6@exadelic.gatalith.at>
Date: Thu, 24 Jul 2025 15:58:23 +0200 (CEST)
From: Thomas Klausner <wiz@NetBSD.org>
Reply-To: Thomas Klausner <wiz@NetBSD.org>
To: gnats-bugs@NetBSD.org
Subject: gdb is not ctype(3) safe
X-Send-Pr-Version: 3.95

>Number:         59549
>Notify-List:    riastradh@NetBSD.org
>Category:       toolchain
>Synopsis:       gdb is not ctype(3) safe
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    toolchain-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jul 24 14:00:01 +0000 2025
>Last-Modified:  Wed Aug 06 13:40:01 +0000 2025
>Originator:     Thomas Klausner
>Release:        NetBSD 10.99.14
>Organization:

>Environment:


Architecture: x86_64
Machine: amd64
>Description:
While debugging a program that was not using the ctype(3) interface correctly,
gdb dumped core as well.

This is the program failing:
(gdb) r
Starting program: /usr/pkg/bin/Guitar
[New process 28508]
ctype(3) isupper: invalid input: -61

And this is gdb failing:

Thread 10 "gdb worker" received signal SIGABRT, Aborted.
[Switching to LWP 16996 of process 28508]
0x000075433d78b4da in _lwp_kill () from /usr/lib/libc.so.12
(gdb) bt
#0  0x000075433d78b4da in _lwp_kill () from /usr/lib/libc.so.12
#1  0x000075433d796914 in abort () at /usr/src/lib/libc/stdlib/abort.c:74
#2  0x000075433d786c13 in ctype_nasaldemon (func=func@entry=0x75433d7b4098 <__func__.7> "isupper", c=<optimized out>) at /usr/src/lib/libc/gen/isctype.c:65
#3  0x000075433d787035 in ctype_check (c=<optimized out>, func=0x75433d7b4098 <__func__.7> "isupper") at /usr/src/lib/libc/gen/isctype.c:73
#4  isupper (c=<optimized out>) at /usr/src/lib/libc/gen/isctype.c:102
#5  0x000000000088bd82 in ada_decode[abi:cxx11](char const*, bool, bool, bool) () at /usr/src/external/gpl3/gdb/lib/libgdb/../../dist/gdb/ada-lang.c:1563
#6  0x0000000000bdb235 in ada_language::sniff_from_mangled_name () at /usr/src/external/gpl3/gdb/lib/libgdb/../../dist/gdb/ada-lang.c:13531
#7  0x00000000006d15f9 in symbol_find_demangled_name () at /usr/src/external/gpl3/gdb/lib/libgdb/../../dist/gdb/symtab.c:961
#8  0x000000000072a0f0 in operator() () at /usr/src/external/gpl3/gdb/lib/libgdb/../../dist/gdb/minsyms.c:1494
#9  0x0000000000ba76b1 in std::function<void()>::operator() () at /usr/obj/amd64.gcc.20250624/usr/include/g++/bits/std_function.h:591
#10 std::__invoke_impl<void, std::function<void()>&> () at /usr/obj/amd64.gcc.20250624/usr/include/g++/bits/invoke.h:61
#11 std::__invoke_r<void, std::function<void()>&> () at /usr/obj/amd64.gcc.20250624/usr/include/g++/bits/invoke.h:111
#12 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}::operator()() const () at /usr/obj/amd64.gcc.20250624/usr/include/g++/future:1489
#13 std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void>::operator()() const () at /usr/obj/amd64.gcc.20250624/usr/include/g++/future:1430
#14 std::__invoke_impl<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void>&>(std::__invoke_other, std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void>&) ()
    at /usr/obj/amd64.gcc.20250624/usr/include/g++/bits/invoke.h:61
#15 std::__invoke_r<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void>&>(std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void>&) ()
    at /usr/obj/amd64.gcc.20250624/usr/include/g++/bits/invoke.h:116
#16 std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> (), std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void> >::_M_invoke(std::_Any_data const&) ()
    at /usr/obj/amd64.gcc.20250624/usr/include/g++/bits/std_function.h:291
#17 0x0000000000ba762f in std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>()>::operator() ()
    at /usr/obj/amd64.gcc.20250624/usr/include/g++/bits/std_function.h:591
#18 std::__future_base::_State_baseV2::_M_do_set () at /usr/obj/amd64.gcc.20250624/usr/include/g++/future:587
#19 0x000075433dcae711 in pthread_once (once_control=0x7542fffd0388, routine=0x75433db44bca <std::__once_proxy()>) at /usr/src/lib/libpthread/pthread_once.c:66
#20 0x0000000000ba7b1f in __gthread_once () at /usr/obj/amd64.gcc.20250624/usr/include/g++/bits/gthr-default.h:703
#21 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>()>*, bool*> () at /usr/obj/amd64.gcc.20250624/usr/include/g++/mutex:891
#22 0x0000000000a8bd99 in std::__future_base::_State_baseV2::_M_set_result () at /usr/obj/amd64.gcc.20250624/usr/include/g++/future:426
#23 std::__future_base::_Task_state<std::function<void()>, std::allocator<int>, void()>::_M_run () at /usr/obj/amd64.gcc.20250624/usr/include/g++/future:1492
#24 std::packaged_task<void()>::operator() () at /usr/obj/amd64.gcc.20250624/usr/include/g++/future:1626
#25 gdb::thread_pool::thread_function () at /usr/src/external/gpl3/gdb/lib/libgdbsupport/../../dist/gdbsupport/thread-pool.cc:245
#26 0x000075433db43d3b in std::execute_native_thread_routine (__p=0x75433d3c6d80) at /usr/src/external/gpl3/gcc/dist/libstdc++-v3/src/c++11/thread.cc:82
#27 0x000075433dcb32e1 in pthread__create_tramp (cookie=0x75433d3a9800) at /usr/src/lib/libpthread/pthread.c:605
#28 0x000075433d6706e0 in ?? () from /usr/lib/libc.so.12
#29 0x0000000000200000 in ?? ()
#30 0x0000000000000000 in ?? ()
(gdb)

I'm still confused why
/usr/src/external/gpl3/gdb/lib/libgdb/../../dist/gdb/ada-lang.c:1563
is in the backtrace, but when you read that file, you can see that it
calls isupper(), isalpha() and isdigit() on both 'const char' and
'std::string' in many many places, without checking the range or
casting to 'unsigned char' first.

>How-To-Repeat:
cd /usr/pkgsrc/wip/Guitar
make install
gdb --args gdb Guitar
r

>Fix:

Please.

>Release-Note:

>Audit-Trail:
From: Martin Husemann <martin@duskware.de>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Thu, 24 Jul 2025 16:08:44 +0200

 On Thu, Jul 24, 2025 at 02:00:01PM +0000, Thomas Klausner wrote:
 > I'm still confused why
 > /usr/src/external/gpl3/gdb/lib/libgdb/../../dist/gdb/ada-lang.c:1563
 > is in the backtrace, but when you read that file, you can see that it
 > calls isupper(), isalpha() and isdigit() on both 'const char' and
 > 'std::string' in many many places, without checking the range or
 > casting to 'unsigned char' first.

 You need a symbol name with non-ASCII characters to trigger it.
 The calls probably all are wrong on any machine with default signed chars.

 Can you go up to frame #5 and print the first argument (which should be
 the symbol name it is looking up)?

 Martin

From: Thomas Klausner <wiz@NetBSD.org>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Fri, 25 Jul 2025 10:37:23 +0200

 martin and didn't find a way to get more information about the symbol
 name.

 I grepped the Guitar source code for ä since that was martin's best
 guess for what triggered the problem, but got no match.

 It's still unclear why gdb even triggers the ada demangler.
  Thomas

From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Fri, 25 Jul 2025 09:24:09 +0000 (UTC)

 On Fri, 25 Jul 2025, Thomas Klausner via gnats wrote:

 > It's still unclear why gdb even triggers the ada demangler.
 >

 Source language must be `auto' (`show language'), and gdb must be trying the
 languages it knows about (`set language<CR>'), starting with `ada'.

 Set it to `c++':

 (gdb) set language c++

 -RVP

From: Martin Husemann <martin@duskware.de>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Fri, 25 Jul 2025 11:42:22 +0200

 All the ctype usage in that source file looks wrong to me.

 Other parts of gdb carefully use ISLOWER() and simmilar macros (locale
 independent?) - not sure if that would be a good idea here.

 All the isupper(), islower(), isdigit() calls require a (unsigned char) cast.

 This should be reported upstream.

 Martin

From: Thomas Klausner <wiz@NetBSD.org>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Fri, 25 Jul 2025 12:08:43 +0200

 On Fri, Jul 25, 2025 at 09:25:01AM +0000, RVP via gnats wrote:
 >  Source language must be `auto' (`show language'), and gdb must be trying the
 >  languages it knows about (`set language<CR>'), starting with `ada'.
 >  
 >  Set it to `c++':
 >  
 >  (gdb) set language c++

 I tried both that and 'c' but no luck:

 #2  0x000076f563494c13 in ctype_nasaldemon (func=func@entry=0x76f5634c2098 <__func__.7> "isupper", c=<optimized out>) at /disk/storage-202410/archive/foreign/src/lib/libc/gen/isctype.c:65
 #3  0x000076f563495035 in ctype_check (c=<optimized out>, func=0x76f5634c2098 <__func__.7> "isupper") at /disk/storage-202410/archive/foreign/src/lib/libc/gen/isctype.c:73
 #4  isupper (c=<optimized out>) at /disk/storage-202410/archive/foreign/src/lib/libc/gen/isctype.c:102
 #5  0x00000000008a2d82 in ada_decode[abi:cxx11](char const*, bool, bool, bool) () at /disk/storage-202410/archive/foreign/src/external/gpl3/gdb/lib/libgdb/../../dist/gdb/ada-lang.c:1563
 #6  0x0000000000bf2235 in ada_language::sniff_from_mangled_name () at /disk/storage-202410/archive/foreign/src/external/gpl3/gdb/lib/libgdb/../../dist/gdb/ada-lang.c:13531
 #7  0x00000000006e85f9 in symbol_find_demangled_name () at /disk/storage-202410/archive/foreign/src/external/gpl3/gdb/lib/libgdb/../../dist/gdb/symtab.c:961

  Thomas

From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Fri, 25 Jul 2025 10:18:16 +0000 (UTC)

 On Fri, 25 Jul 2025, Thomas Klausner via gnats wrote:

 > I tried both that and 'c' but no luck:
 > [...]
 > #6  0x0000000000bf2235 in ada_language::sniff_from_mangled_name () at /disk/storage-202410/archive/foreign/src/external/gpl3/gdb/lib/libgdb/../../dist/gdb/ada-lang.c:13531
 > #7  0x00000000006e85f9 in symbol_find_demangled_name () at /disk/storage-202410/archive/foreign/src/external/gpl3/gdb/lib/libgdb/../../dist/gdb/symtab.c:961
 >

 Try:

 (gdb) set demangle-style gnu-v3

 -RVP

From: Thomas Klausner <wiz@NetBSD.org>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Fri, 25 Jul 2025 12:21:50 +0200

 On Fri, Jul 25, 2025 at 10:20:02AM +0000, RVP via gnats wrote:
 >  (gdb) set demangle-style gnu-v3

 No change, even with both that and language set to c++.
  Thomas

From: Christos Zoulas <christos@zoulas.com>
To: gnats-bugs@netbsd.org
Cc: toolchain-manager@netbsd.org,
 gnats-admin@netbsd.org,
 netbsd-bugs@netbsd.org,
 Thomas Klausner <wiz@NetBSD.org>
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Fri, 25 Jul 2025 08:46:01 -0400

 --Apple-Mail=_2894989C-6E5A-4568-A409-088E55B38E25
 Content-Type: multipart/mixed;
 	boundary="Apple-Mail=_52E1FB37-8163-4E28-B245-A16157BF10ED"


 --Apple-Mail=_52E1FB37-8163-4E28-B245-A16157BF10ED
 Content-Disposition: attachment;
 	filename=gdb.patch
 Content-Type: application/octet-stream;
 	name=gdb.patch;
 	x-unix-mode=0644
 Content-Transfer-Encoding: 7bit

 Index: dist/gdb/ada-lang.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/ada-lang.c,v
 retrieving revision 1.9
 diff -u -p -u -r1.9 ada-lang.c
 --- dist/gdb/ada-lang.c	12 Aug 2024 22:09:29 -0000	1.9
 +++ dist/gdb/ada-lang.c	25 Jul 2025 12:44:27 -0000
 @@ -867,7 +867,7 @@ is_compiler_suffix (const char *str)
  {
    gdb_assert (*str == '[');
    ++str;
 -  while (*str != '\0' && isalpha (*str))
 +  while (*str != '\0' && isalpha ((unsigned char)*str))
      ++str;
    /* We accept a missing "]" in order to support completion.  */
    return *str == '\0' || (str[0] == ']' && str[1] == '\0');
 @@ -1159,7 +1159,7 @@ ada_encode (const char *decoded, bool fo
  static int
  is_lower_alphanum (const char c)
  {
 -  return (isdigit (c) || (isalpha (c) && islower (c)));
 +  return (isdigit ((unsigned char)c) || (isalpha ((unsigned char)c) && islower ((unsigned char)c)));
  }

  /* ENCODED is the linkage name of a symbol and LEN contains its length.
 @@ -1177,11 +1177,11 @@ is_lower_alphanum (const char c)
  static void
  ada_remove_trailing_digits (const char *encoded, int *len)
  {
 -  if (*len > 1 && isdigit (encoded[*len - 1]))
 +  if (*len > 1 && isdigit ((unsigned char)encoded[*len - 1]))
      {
        int i = *len - 2;

 -      while (i > 0 && isdigit (encoded[i]))
 +      while (i > 0 && isdigit ((unsigned char)encoded[i]))
  	i--;
        if (i >= 0 && encoded[i] == '.')
  	*len = i;
 @@ -1212,7 +1212,7 @@ ada_remove_po_subprogram_suffix (const c

    if (*len > 1
        && encoded[*len - 1] == 'N'
 -      && (isdigit (encoded[*len - 2]) || islower (encoded[*len - 2])))
 +      && (isdigit ((unsigned char)encoded[*len - 2]) || islower ((unsigned char)encoded[*len - 2])))
      *len = *len - 1;
  }

 @@ -1224,7 +1224,7 @@ static int
  remove_compiler_suffix (const char *encoded, int *len)
  {
    int offset = *len - 1;
 -  while (offset > 0 && isalpha (encoded[offset]))
 +  while (offset > 0 && isalpha ((unsigned char)encoded[offset]))
      --offset;
    if (offset > 0 && encoded[offset] == '.')
      {
 @@ -1244,7 +1244,7 @@ convert_hex (const char *str, int n, uin

    for (int i = 0; i < n; ++i)
      {
 -      if (!isxdigit (str[i]))
 +      if (!isxdigit ((unsigned char)str[i]))
  	return false;
        result <<= 4;
        result |= fromhex (str[i]);
 @@ -1376,11 +1376,11 @@ ada_decode (const char *encoded, bool wr

    /* Remove trailing __{digit}+ or trailing ${digit}+.  */

 -  if (len0 > 1 && isdigit (encoded[len0 - 1]))
 +  if (len0 > 1 && isdigit ((unsigned char)encoded[len0 - 1]))
      {
        i = len0 - 2;
 -      while ((i >= 0 && isdigit (encoded[i]))
 -	     || (i >= 1 && encoded[i] == '_' && isdigit (encoded[i - 1])))
 +      while ((i >= 0 && isdigit ((unsigned char)encoded[i]))
 +	     || (i >= 1 && encoded[i] == '_' && isdigit ((unsigned char)encoded[i - 1])))
  	i -= 1;
        if (i > 1 && encoded[i] == '_' && encoded[i - 1] == '_')
  	len0 = i - 1;
 @@ -1391,7 +1391,7 @@ ada_decode (const char *encoded, bool wr
    /* The first few characters that are not alphabetic are not part
       of any encoding we use, so we can copy them over verbatim.  */

 -  for (i = 0; i < len0 && !isalpha (encoded[i]); i += 1)
 +  for (i = 0; i < len0 && !isalpha ((unsigned char)encoded[i]); i += 1)
      decoded.push_back (encoded[i]);

    at_start_name = 1;
 @@ -1407,7 +1407,7 @@ ada_decode (const char *encoded, bool wr
  	      int op_len = strlen (ada_opname_table[k].encoded);
  	      if ((strncmp (ada_opname_table[k].encoded + 1, encoded + i + 1,
  			    op_len - 1) == 0)
 -		  && !isalnum (encoded[i + op_len]))
 +		  && !isalnum ((unsigned char)encoded[i + op_len]))
  		{
  		  decoded.append (ada_opname_table[k].decoded);
  		  at_start_name = 0;
 @@ -1432,11 +1432,11 @@ ada_decode (const char *encoded, bool wr

        if (len0 - i > 5 && encoded [i] == '_' && encoded [i+1] == '_'
  	  && encoded [i+2] == 'B' && encoded [i+3] == '_'
 -	  && isdigit (encoded [i+4]))
 +	  && isdigit ((unsigned char)encoded [i+4]))
  	{
  	  int k = i + 5;

 -	  while (k < len0 && isdigit (encoded[k]))
 +	  while (k < len0 && isdigit ((unsigned char)encoded[k]))
  	    k++;  /* Skip any extra digit.  */

  	  /* Double-check that the "__B_{DIGITS}+" sequence we found
 @@ -1459,11 +1459,11 @@ ada_decode (const char *encoded, bool wr
  	 internally generated.  */

        if (len0 - i > 3 && encoded [i] == '_' && encoded[i+1] == 'E'
 -	  && isdigit (encoded[i+2]))
 +	  && isdigit ((unsigned char)encoded[i+2]))
  	{
  	  int k = i + 3;

 -	  while (k < len0 && isdigit (encoded[k]))
 +	  while (k < len0 && isdigit ((unsigned char)encoded[k]))
  	    k++;

  	  if (k < len0
 @@ -1497,7 +1497,7 @@ ada_decode (const char *encoded, bool wr
  	    i++;
  	}

 -      if (wide && i < len0 + 3 && encoded[i] == 'U' && isxdigit (encoded[i + 1]))
 +      if (wide && i < len0 + 3 && encoded[i] == 'U' && isxdigit ((unsigned char)encoded[i + 1]))
  	{
  	  if (convert_from_hex_encoded (decoded, &encoded[i + 1], 2))
  	    {
 @@ -1505,7 +1505,7 @@ ada_decode (const char *encoded, bool wr
  	      continue;
  	    }
  	}
 -      else if (wide && i < len0 + 5 && encoded[i] == 'W' && isxdigit (encoded[i + 1]))
 +      else if (wide && i < len0 + 5 && encoded[i] == 'W' && isxdigit ((unsigned char)encoded[i + 1]))
  	{
  	  if (convert_from_hex_encoded (decoded, &encoded[i + 1], 4))
  	    {
 @@ -1514,7 +1514,7 @@ ada_decode (const char *encoded, bool wr
  	    }
  	}
        else if (wide && i < len0 + 10 && encoded[i] == 'W' && encoded[i + 1] == 'W'
 -	       && isxdigit (encoded[i + 2]))
 +	       && isxdigit ((unsigned char)encoded[i + 2]))
  	{
  	  if (convert_from_hex_encoded (decoded, &encoded[i + 2], 8))
  	    {
 @@ -1523,7 +1523,7 @@ ada_decode (const char *encoded, bool wr
  	    }
  	}

 -      if (encoded[i] == 'X' && i != 0 && isalnum (encoded[i - 1]))
 +      if (encoded[i] == 'X' && i != 0 && isalnum ((unsigned char)encoded[i - 1]))
  	{
  	  /* This is a X[bn]* sequence not separated from the previous
  	     part of the name with a non-alpha-numeric character (in other
 @@ -1560,7 +1560,7 @@ ada_decode (const char *encoded, bool wr
    if (operators)
      {
        for (i = 0; i < decoded.length(); ++i)
 -	if (isupper (decoded[i]) || decoded[i] == ' ')
 +	if (isupper ((unsigned char)decoded[i]) || decoded[i] == ' ')
  	  goto Suppress;
      }

 @@ -3438,9 +3438,9 @@ encoded_ordered_before (const char *N0, 
      {
        int k0, k1;

 -      for (k0 = strlen (N0) - 1; k0 > 0 && isdigit (N0[k0]); k0 -= 1)
 +      for (k0 = strlen (N0) - 1; k0 > 0 && isdigit ((unsigned char)N0[k0]); k0 -= 1)
  	;
 -      for (k1 = strlen (N1) - 1; k1 > 0 && isdigit (N1[k1]); k1 -= 1)
 +      for (k1 = strlen (N1) - 1; k1 > 0 && isdigit ((unsigned char)N1[k1]); k1 -= 1)
  	;
        if ((N0[k0] == '_' || N0[k0] == '$') && N0[k0 + 1] != '\000'
  	  && (N1[k1] == '_' || N1[k1] == '$') && N1[k1 + 1] != '\000')
 @@ -5767,10 +5767,10 @@ is_name_suffix (const char *str)

    /* Skip optional leading __[0-9]+.  */

 -  if (len > 3 && str[0] == '_' && str[1] == '_' && isdigit (str[2]))
 +  if (len > 3 && str[0] == '_' && str[1] == '_' && isdigit ((unsigned char)str[2]))
      {
        str += 3;
 -      while (isdigit (str[0]))
 +      while (isdigit ((unsigned char)str[0]))
  	str += 1;
      }

 @@ -5779,7 +5779,7 @@ is_name_suffix (const char *str)
    if (str[0] == '.' || str[0] == '$')
      {
        matching = str + 1;
 -      while (isdigit (matching[0]))
 +      while (isdigit ((unsigned char)matching[0]))
  	matching += 1;
        if (matching[0] == '\0')
  	return 1;
 @@ -5790,7 +5790,7 @@ is_name_suffix (const char *str)
    if (len > 3 && str[0] == '_' && str[1] == '_' && str[2] == '_')
      {
        matching = str + 3;
 -      while (isdigit (matching[0]))
 +      while (isdigit ((unsigned char)matching[0]))
  	matching += 1;
        if (matching[0] == '\0')
  	return 1;
 @@ -5819,10 +5819,10 @@ is_name_suffix (const char *str)
  #endif

    /* _E[0-9]+[bs]$ */
 -  if (len > 3 && str[0] == '_' && str [1] == 'E' && isdigit (str[2]))
 +  if (len > 3 && str[0] == '_' && str [1] == 'E' && isdigit ((unsigned char)str[2]))
      {
        matching = str + 3;
 -      while (isdigit (matching[0]))
 +      while (isdigit ((unsigned char)matching[0]))
  	matching += 1;
        if ((matching[0] == 'b' || matching[0] == 's')
  	  && matching [1] == '\0')
 @@ -5872,17 +5872,17 @@ is_name_suffix (const char *str)
  	    return 1;
  	  return 0;
  	}
 -      if (!isdigit (str[2]))
 +      if (!isdigit ((unsigned char)str[2]))
  	return 0;
        for (k = 3; str[k] != '\0'; k += 1)
 -	if (!isdigit (str[k]) && str[k] != '_')
 +	if (!isdigit ((unsigned char)str[k]) && str[k] != '_')
  	  return 0;
        return 1;
      }
 -  if (str[0] == '$' && isdigit (str[1]))
 +  if (str[0] == '$' && isdigit ((unsigned char)str[1]))
      {
        for (k = 2; str[k] != '\0'; k += 1)
 -	if (!isdigit (str[k]) && str[k] != '_')
 +	if (!isdigit ((unsigned char)str[k]) && str[k] != '_')
  	  return 0;
        return 1;
      }
 @@ -5905,7 +5905,7 @@ is_valid_name_for_wild_match (const char
      return 0;

    for (i=0; decoded_name[i] != '\0'; i++)
 -    if (isalpha (decoded_name[i]) && !islower (decoded_name[i]))
 +    if (isalpha ((unsigned char)decoded_name[i]) && !islower ((unsigned char)decoded_name[i]))
        return 0;

    return 1;
 @@ -6129,7 +6129,7 @@ ada_lookup_name_info::matches
  	 angle bracket notation.  */
        const char *tmp;

 -      for (tmp = sym_name; *tmp != '\0' && !isupper (*tmp); tmp++);
 +      for (tmp = sym_name; *tmp != '\0' && !isupper ((unsigned char)*tmp); tmp++);
        if (*tmp != '\0')
  	match = false;
      }
 @@ -6244,7 +6244,7 @@ ada_is_ignored_field (struct type *type,
        {
  	/* Wrapper field.  */
        }
 -    else if (isupper (name[0]))
 +    else if (isupper ((unsigned char)name[0]))
        return 1;
    }

 @@ -6753,14 +6753,14 @@ ada_scan_number (const char str[], int k
  {
    ULONGEST RU;

 -  if (!isdigit (str[k]))
 +  if (!isdigit ((unsigned char)str[k]))
      return 0;

    /* Do it the hard way so as not to make any assumption about
       the relationship of unsigned long (%lu scan format code) and
       LONGEST.  */
    RU = 0;
 -  while (isdigit (str[k]))
 +  while (isdigit ((unsigned char)str[k]))
      {
        RU = RU * 10 + (str[k] - '0');
        k += 1;
 @@ -7417,10 +7417,10 @@ field_alignment (struct type *type, int 

    len = strlen (name);

 -  if (!isdigit (name[len - 1]))
 +  if (!isdigit ((unsigned char)name[len - 1]))
      return 1;

 -  if (isdigit (name[len - 2]))
 +  if (isdigit ((unsigned char)name[len - 2]))
      align_offset = len - 2;
    else
      align_offset = len - 1;
 @@ -8998,7 +8998,7 @@ ada_enum_name (const char *name)
      {
        while ((tmp = strstr (name, "__")) != NULL)
  	{
 -	  if (isdigit (tmp[2]))
 +	  if (isdigit ((unsigned char)tmp[2]))
  	    break;
  	  else
  	    name = tmp + 2;
 @@ -9030,7 +9030,7 @@ ada_enum_name (const char *name)
        else
  	return name;

 -      if (isascii (v) && isprint (v))
 +      if (isascii ((unsigned char)v) && isprint ((unsigned char)v))
  	storage = string_printf ("'%c'", v);
        else if (name[1] == 'U')
  	storage = string_printf ("'[\"%02x\"]'", v);
 @@ -12542,7 +12542,7 @@ catch_ada_exception_command_split (const

    args = skip_spaces (args);
    if (startswith (args, "if")
 -      && (isspace (args[2]) || args[2] == '\0'))
 +      && (isspace ((unsigned char)args[2]) || args[2] == '\0'))
      {
        args += 2;
        args = skip_spaces (args);
 @@ -12815,7 +12815,7 @@ catch_ada_assert_command_split (const ch

    /* Check whether a condition was provided.  */
    if (startswith (args, "if")
 -      && (isspace (args[2]) || args[2] == '\0'))
 +      && (isspace ((unsigned char)args[2]) || args[2] == '\0'))
      {
        args += 2;
        args = skip_spaces (args);
 @@ -13216,7 +13216,7 @@ do_full_match (const char *symbol_search
  	      && symbol_search_name[1] == '_')
  	    {
  	      symbol_search_name += 2;
 -	      while (isdigit (*symbol_search_name))
 +	      while (isdigit ((unsigned char)*symbol_search_name))
  		++symbol_search_name;
  	      if (symbol_search_name[0] == '_'
  		  && symbol_search_name[1] == '_')
 Index: dist/gdb/ada-typeprint.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/ada-typeprint.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 ada-typeprint.c
 --- dist/gdb/ada-typeprint.c	12 Aug 2024 21:38:07 -0000	1.1.1.11
 +++ dist/gdb/ada-typeprint.c	25 Jul 2025 12:44:27 -0000
 @@ -72,7 +72,7 @@ decoded_type_name (struct type *type)
        if (s == name_buffer)
  	return name_buffer;

 -      if (!islower (s[1]))
 +      if (!islower ((unsigned char)s[1]))
  	return NULL;

        for (s = q = name_buffer; *s != '\0'; q += 1)

 --Apple-Mail=_52E1FB37-8163-4E28-B245-A16157BF10ED
 Content-Transfer-Encoding: quoted-printable
 Content-Type: text/plain;
 	charset=utf-8



 I am not committing this because it is too intrusive, but see if it =
 helps you.

 christos

 > On Jul 25, 2025, at 6:25=E2=80=AFAM, Thomas Klausner via gnats =
 <gnats-admin@NetBSD.org> wrote:
 >=20
 > The following reply was made to PR toolchain/59549; it has been noted =
 by GNATS.
 >=20
 > From: Thomas Klausner <wiz@NetBSD.org>
 > To: gnats-bugs@netbsd.org
 > Cc:=20
 > Subject: Re: toolchain/59549: gdb is not ctype(3) safe
 > Date: Fri, 25 Jul 2025 12:21:50 +0200
 >=20
 > On Fri, Jul 25, 2025 at 10:20:02AM +0000, RVP via gnats wrote:
 >> (gdb) set demangle-style gnu-v3
 >=20
 > No change, even with both that and language set to c++.
 >  Thomas
 >=20


 --Apple-Mail=_52E1FB37-8163-4E28-B245-A16157BF10ED--

 --Apple-Mail=_2894989C-6E5A-4568-A409-088E55B38E25
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
 	filename=signature.asc
 Content-Type: application/pgp-signature;
 	name=signature.asc
 Content-Description: Message signed with OpenPGP

 -----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - http://gpgtools.org

 iF0EARECAB0WIQS+BJlbqPkO0MDBdsRxESqxbLM7OgUCaIN8iQAKCRBxESqxbLM7
 Oj/vAKCrWCDTD2WzD5B0pTe8A5ssQJEGWQCg3Ki54hKccGsZJpQ+o1WbnX0m9OY=
 =0XdV
 -----END PGP SIGNATURE-----

 --Apple-Mail=_2894989C-6E5A-4568-A409-088E55B38E25--

From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Fri, 25 Jul 2025 13:49:37 +0000 (UTC)

 On Fri, 25 Jul 2025, Thomas Klausner via gnats wrote:

 > No change, even with both that and language set to c++.
 >

 Can you see if there are really any Ada frames in either executable:

 readelf -wi <exe|exe.debug> | fgrep DW_AT_language | fgrep -i ada

 (for stripped binaries, you'll have to use the .debug files in
 /usr/libdata/debug/usr/...)

 -RVP

From: Thomas Klausner <wiz@NetBSD.org>
To: NetBSD bugtracking <gnats-bugs@NetBSD.org>
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Sat, 26 Jul 2025 09:12:26 +0200

 On Fri, Jul 25, 2025 at 01:50:02PM +0000, RVP via gnats wrote:
 >  Can you see if there are really any Ada frames in either executable:
 >  
 >  readelf -wi <exe|exe.debug> | fgrep DW_AT_language | fgrep -i ada
 >  
 >  (for stripped binaries, you'll have to use the .debug files in
 >  /usr/libdata/debug/usr/...)

 I don't think so:

 # readelf -wi /usr/libdata/debug/usr/bin/gdb.debug | fgrep DW_AT_language | fgrep -i ada
 readelf: Error: Unable to find program interpreter name
     <1dadae>   DW_AT_language    : 4    (C++)
     <2ada1e>   DW_AT_language    : 4    (C++)
 # readelf -wi /usr/pkg/bin/Guitar | fgrep DW_AT_language | fgrep -i ada
 #

  Thomas

From: Thomas Klausner <wiz@NetBSD.org>
To: Christos Zoulas <christos@zoulas.com>
Cc: NetBSD bugtracking <gnats-bugs@NetBSD.org>
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Sat, 26 Jul 2025 11:55:29 +0200

 On Fri, Jul 25, 2025 at 08:46:01AM -0400, Christos Zoulas wrote:
 > I am not committing this because it is too intrusive, but see if it helps you.

 Thank you!

 Now I don't need to double up the gdb's, the gdb running Guitar
 doesn't dump core any longer.

 The backtrace of Guitar when it segfaults looks wrong though:

 Thread 12 "" received signal SIGSEGV, Segmentation fault.
 [Switching to LWP 26550 of process 27435]
 0x000000000069d346 in __gmtime_r50 (t=0x7cb9f8ffe7f8, tm=0x7cba003bdf80 <tm>) at file/src/gmtime_r.c:13
 warning: 13     file/src/gmtime_r.c: No such file or directory
 (gdb) bt
 #0  0x000000000069d346 in __gmtime_r50 (t=0x7cb9f8ffe7f8, tm=0x7cba003bdf80 <tm>) at file/src/gmtime_r.c:13
 #1  0x000000000069d366 in __gmtime_r50 (t=<optimized out>, tm=0x7cba003bdf80 <tm>) at file/src/gmtime_r.c:14
 #2  0x000000000069d366 in __gmtime_r50 (t=<optimized out>, tm=0x7cba003bdf80 <tm>) at file/src/gmtime_r.c:14
 ... and so on for more than 15000 frames, until I stopped it...

 (gdb) p *t
 $1 = 1753523442
 (gdb) p *tm
 $2 = {tm_sec = 42, tm_min = 50, tm_hour = 11, tm_mday = 26, tm_mon = 6, tm_year = 125, tm_wday = 6, tm_yday = 206, tm_isdst = 1, tm_gmtoff = 7200, tm_zone = 0x7cb9fb1d846c "CEST"}

 Probably stack corruption, because why else would the same function be there >15000 times.
  Thomas

From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Sat, 26 Jul 2025 12:06:11 +0000 (UTC)

 On Sat, 26 Jul 2025, Thomas Klausner via gnats wrote:

 > The backtrace of Guitar when it segfaults looks wrong though:
 >
 > Thread 12 "" received signal SIGSEGV, Segmentation fault.
 > [Switching to LWP 26550 of process 27435]
 > 0x000000000069d346 in __gmtime_r50 (t=0x7cb9f8ffe7f8, tm=0x7cba003bdf80 <tm>) at file/src/gmtime_r.c:13
 > warning: 13     file/src/gmtime_r.c: No such file or directory
 > (gdb) bt
 > #0  0x000000000069d346 in __gmtime_r50 (t=0x7cb9f8ffe7f8, tm=0x7cba003bdf80 <tm>) at file/src/gmtime_r.c:13
 > #1  0x000000000069d366 in __gmtime_r50 (t=<optimized out>, tm=0x7cba003bdf80 <tm>) at file/src/gmtime_r.c:14
 > #2  0x000000000069d366 in __gmtime_r50 (t=<optimized out>, tm=0x7cba003bdf80 <tm>) at file/src/gmtime_r.c:14
 > ... and so on for more than 15000 frames, until I stopped it...
 >
 > (gdb) p *t
 > $1 = 1753523442
 > (gdb) p *tm
 > $2 = {tm_sec = 42, tm_min = 50, tm_hour = 11, tm_mday = 26, tm_mon = 6, tm_year = 125, tm_wday = 6, tm_yday = 206, tm_isdst = 1, tm_gmtoff = 7200, tm_zone = 0x7cb9fb1d846c "CEST"}
 >
 > Probably stack corruption, because why else would the same function be there >15000 times.
 >

 No, that's the trouble: it _is_ being called recursively because:

 Guitar-1.3.0/filetype/file/src/gmtime_r.c has:

   11 struct tm *
   12 gmtime_r(const time_t *t, struct tm *tm)
   13 {
   14         struct tm *tmp = gmtime(t);
              [...]
   19 }

 and src/lib/libc/time/localtime.c has:

 1871 struct tm * 
 1872 gmtime(const time_t *timep) 
 1873 { 
 1874 # if !SUPPORT_C89 
 1875   static struct tm tm; 
 1876 # endif 
 1877   return gmtime_r(timep, &tm); 
 1878 }

 This will call gmtime_r() back in Guitar; which will call gmtime() in libc ...


 This object (gmtime_r.o) shouldn't unconditionally be added into libfiletype.a
 in Guitar-1.3.0/filetype/Makefile.

 Remove it, and _this_ crash should go away.

 -RVP

From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Sat, 26 Jul 2025 12:39:23 +0000 (UTC)

 This only works on Linux because the implementations are very different:

 https://sourceware.org/git/?p=glibc.git;a=blob;f=time/gmtime.c

 FreeBSD'll have trouble too:

 https://github.com/freebsd/freebsd-src/blob/main/contrib/tzcode/localtime.c#L1744

 -RVP

From: Taylor R Campbell <riastradh@NetBSD.org>
To: Thomas Klausner <wiz@NetBSD.org>
Cc: gnats-bugs@NetBSD.org, netbsd-bugs@NetBSD.org
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Sat, 26 Jul 2025 12:50:03 +0000

 > #7  0x00000000006d15f9 in symbol_find_demangled_name () at /usr/src/exter=
 nal/gpl3/gdb/lib/libgdb/../../dist/gdb/symtab.c:961

    948    if (gsymbol->language () !=3D language_unknown)
    949      {
    950        const struct language_defn *lang =3D language_def (gsymbol->l=
 anguage ());
    951 =20
    952        lang->sniff_from_mangled_name (mangled, &demangled);
    953        return demangled;
    954      }
    955 =20
    956    for (i =3D language_unknown; i < nr_languages; ++i)
    957      {
    958        enum language l =3D (enum language) i;
    959        const struct language_defn *lang =3D language_def (l);
    960 =20
 =3D> 961        if (lang->sniff_from_mangled_name (mangled, &demangled))

 If gdb doesn't know the language _of this symbol_ for demangling, it
 will try all the languages' demangling methods, whether or not there's
 any specific reason for Ada to be involved in this.

 We should just patch gdb locally and file an upstream bug, basic case
 of clear undefined behaviour that is triggered in real-world use.
 Christos's patch looks fine to me (but I did not check whether there
 are any missing cases).

 I suggest filing a separate PR for the wip/Guitar issue.

From: Christos Zoulas <christos@zoulas.com>
To: gnats-bugs@netbsd.org
Cc: toolchain-manager@netbsd.org,
 gnats-admin@netbsd.org,
 netbsd-bugs@netbsd.org,
 Thomas Klausner <wiz@NetBSD.org>,
 "riastradh@netbsd.org" <riastradh@NetBSD.org>
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Sat, 26 Jul 2025 10:06:15 -0400

 --Apple-Mail=_5CF4A1EA-AC4A-4740-AFCA-2C5E7D0C672C
 Content-Transfer-Encoding: 7bit
 Content-Type: text/plain;
 	charset=us-ascii


 > We should just patch gdb locally and file an upstream bug, basic case
 > of clear undefined behaviour that is triggered in real-world use.
 > Christos's patch looks fine to me (but I did not check whether there
 > are any missing cases).
 > 

 There are a few more missing, I thought of changing all of the ctype
 macros to gdb_isfoo() instead of all the local casts. I think we should
 let upstream fix it first.

 christos


 --Apple-Mail=_5CF4A1EA-AC4A-4740-AFCA-2C5E7D0C672C
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
 	filename=signature.asc
 Content-Type: application/pgp-signature;
 	name=signature.asc
 Content-Description: Message signed with OpenPGP

 -----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - http://gpgtools.org

 iF0EARECAB0WIQS+BJlbqPkO0MDBdsRxESqxbLM7OgUCaITg1wAKCRBxESqxbLM7
 OjyFAKCXKgokgQhcf7ARW/ISqobW0acTvwCg4br0Ogsy/zlfqRp8Husg6OZLweM=
 =PzPO
 -----END PGP SIGNATURE-----

 --Apple-Mail=_5CF4A1EA-AC4A-4740-AFCA-2C5E7D0C672C--

From: Valery Ushakov <uwe@stderr.spb.ru>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Sun, 27 Jul 2025 02:20:15 +0300

 >  and src/lib/libc/time/localtime.c has:
 >
 >  1871 struct tm *
 >  1872 gmtime(const time_t *timep)
 >  1873 {
 >  1874 # if !SUPPORT_C89
 >  1875   static struct tm tm;
 >  1876 # endif
 >  1877   return gmtime_r(timep, &tm);
 >  1878 }

 Shouldn't libc gmtime call gmtime_r via its libc-internal name here?

 -uwe

From: Robert Elz <kre@munnari.OZ.AU>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Sun, 27 Jul 2025 15:07:13 +0700

     Date:        Sat, 26 Jul 2025 23:25:02 +0000 (UTC)
     From:        "Valery Ushakov via gnats" <gnats-admin@NetBSD.org>
     Message-ID:  <20250726232502.5BBA51A923F@mollari.NetBSD.org>

   |  Shouldn't libc gmtime call gmtime_r via its libc-internal name here?

 It does, via the #define in src/lib/libc/include/namespace.h

 But I agree, something related to what the application is doing with
 gmtime_r() in its sources, combined with the RENAME() in <time.h> is
 likely the underlying problem here.   Most likely the application should
 not be defining its own gmtime_r (when one is provided in libc) at all.

 kre

From: Thomas Klausner <wiz@NetBSD.org>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Sun, 27 Jul 2025 11:53:24 +0200

 On Sat, Jul 26, 2025 at 12:10:01PM +0000, RVP via gnats wrote:
 >  No, that's the trouble: it _is_ being called recursively because:

 Thanks. I've disabled the contents of the file on NetBSD, and Guitar
 seems to work fine now - imported to pkgsrc/devel/Guitar.
  Thomas

From: Taylor R Campbell <riastradh@NetBSD.org>
To: Christos Zoulas <christos@zoulas.com>
Cc: gnats-bugs@netbsd.org, toolchain-manager@netbsd.org,
	gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, Thomas Klausner <wiz@NetBSD.org>
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Sun, 27 Jul 2025 13:31:22 +0000

 > Date: Sat, 26 Jul 2025 10:06:15 -0400
 > From: Christos Zoulas <christos@zoulas.com>
 > 
 > > We should just patch gdb locally and file an upstream bug, basic case
 > > of clear undefined behaviour that is triggered in real-world use.
 > > Christos's patch looks fine to me (but I did not check whether there
 > > are any missing cases).
 > 
 > There are a few more missing, I thought of changing all of the ctype
 > macros to gdb_isfoo() instead of all the local casts.

 Let's let upstream decide how they want to tidy things up (there is
 already a `safe-ctype.h' in binutils with uppercase macros instead,
 restricted to char inputs that are never EOF, but I don't know whether
 it's appropriate here).

 >                                                       I think we should
 > let upstream fix it first.

 This is actively interfering with development and debugging on NetBSD,
 so it is a high priority to work around while we wait for upstream.
 We should just make sure that we're not applying this to any cases
 that might legitimately have EOF in the domain.

 If upstream does it differently, no big deal, we can just replace our
 local patch by their different patch later.

From: Robert Elz <kre@munnari.OZ.AU>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Sun, 27 Jul 2025 20:57:06 +0700

     Date:        Sun, 27 Jul 2025 09:55:01 +0000 (UTC)
     From:        "Thomas Klausner via gnats" <gnats-admin@NetBSD.org>
     Message-ID:  <20250727095501.E477E1A923E@mollari.NetBSD.org>

   |  On Sat, Jul 26, 2025 at 12:10:01PM +0000, RVP via gnats wrote:
   |  >  No, that's the trouble: it _is_ being called recursively because:
   |  
   |  Thanks. I've disabled the contents of the file on NetBSD, and Guitar
   |  seems to work fine now - imported to pkgsrc/devel/Guitar.

 For anyone following this aspect of this PR (the part which has
 nothing whatever to do with gdb or ctype(3)) for why it all happened
 (unless you are just satisfied with "application bug") and whether
 or not we should do something to prevent this kind of thing happening
 again is continued in PR lib/59559


From: Christos Zoulas <christos@zoulas.com>
To: Taylor R Campbell <riastradh@NetBSD.org>
Cc: gnats-bugs@netbsd.org,
 toolchain-manager@netbsd.org,
 gnats-admin@netbsd.org,
 netbsd-bugs@netbsd.org,
 Thomas Klausner <wiz@NetBSD.org>
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Sun, 27 Jul 2025 14:22:55 -0400

 --Apple-Mail=_9F645710-321D-4E88-9A06-695AF34D42B9
 Content-Type: multipart/mixed;
 	boundary="Apple-Mail=_145FE431-B621-4842-9035-ABBBDB7599B6"


 --Apple-Mail=_145FE431-B621-4842-9035-ABBBDB7599B6
 Content-Transfer-Encoding: quoted-printable
 Content-Type: text/plain;
 	charset=us-ascii

 The full patch is 2K lines long (attached). I will apply it if someone =
 else here says I should :-)

 christos


 --Apple-Mail=_145FE431-B621-4842-9035-ABBBDB7599B6
 Content-Disposition: attachment;
 	filename=gdb.patch
 Content-Type: application/octet-stream;
 	name=gdb.patch;
 	x-unix-mode=0644
 Content-Transfer-Encoding: 7bit

 ? a.out
 ? foo.cc
 ? o
 Index: aarch64-linux-tdep.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/aarch64-linux-tdep.c,v
 retrieving revision 1.1.1.10
 diff -u -p -u -r1.1.1.10 aarch64-linux-tdep.c
 --- aarch64-linux-tdep.c	12 Aug 2024 21:37:58 -0000	1.1.1.10
 +++ aarch64-linux-tdep.c	27 Jul 2025 18:20:55 -0000
 @@ -1665,9 +1665,9 @@ aarch64_linux_core_read_description (str
  static int
  aarch64_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
  {
 -  return (*s == '#' || isdigit (*s) /* Literal number.  */
 +  return (*s == '#' || isdigit ((unsigned char)*s) /* Literal number.  */
  	  || *s == '[' /* Register indirection.  */
 -	  || isalpha (*s)); /* Register value.  */
 +	  || isalpha ((unsigned char)*s)); /* Register value.  */
  }

  /* This routine is used to parse a special token in AArch64's assembly.
 @@ -1698,7 +1698,7 @@ aarch64_stap_parse_special_token (struct
        start = tmp;

        /* Register name.  */
 -      while (isalnum (*tmp))
 +      while (isalnum ((unsigned char)*tmp))
  	++tmp;

        if (*tmp != ',')
 @@ -1726,7 +1726,7 @@ aarch64_stap_parse_special_token (struct
        else if (*tmp == '+')
  	++tmp;

 -      if (!isdigit (*tmp))
 +      if (!isdigit ((unsigned char)*tmp))
  	return {};

        displacement = strtol (tmp, &endp, 10);
 Index: ada-lang.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/ada-lang.c,v
 retrieving revision 1.9
 diff -u -p -u -r1.9 ada-lang.c
 --- ada-lang.c	12 Aug 2024 22:09:29 -0000	1.9
 +++ ada-lang.c	27 Jul 2025 18:20:55 -0000
 @@ -867,7 +867,7 @@ is_compiler_suffix (const char *str)
  {
    gdb_assert (*str == '[');
    ++str;
 -  while (*str != '\0' && isalpha (*str))
 +  while (*str != '\0' && isalpha ((unsigned char)*str))
      ++str;
    /* We accept a missing "]" in order to support completion.  */
    return *str == '\0' || (str[0] == ']' && str[1] == '\0');
 @@ -1159,7 +1159,7 @@ ada_encode (const char *decoded, bool fo
  static int
  is_lower_alphanum (const char c)
  {
 -  return (isdigit (c) || (isalpha (c) && islower (c)));
 +  return (isdigit ((unsigned char)c) || (isalpha ((unsigned char)c) && islower ((unsigned char)c)));
  }

  /* ENCODED is the linkage name of a symbol and LEN contains its length.
 @@ -1177,11 +1177,11 @@ is_lower_alphanum (const char c)
  static void
  ada_remove_trailing_digits (const char *encoded, int *len)
  {
 -  if (*len > 1 && isdigit (encoded[*len - 1]))
 +  if (*len > 1 && isdigit ((unsigned char)encoded[*len - 1]))
      {
        int i = *len - 2;

 -      while (i > 0 && isdigit (encoded[i]))
 +      while (i > 0 && isdigit ((unsigned char)encoded[i]))
  	i--;
        if (i >= 0 && encoded[i] == '.')
  	*len = i;
 @@ -1212,7 +1212,7 @@ ada_remove_po_subprogram_suffix (const c

    if (*len > 1
        && encoded[*len - 1] == 'N'
 -      && (isdigit (encoded[*len - 2]) || islower (encoded[*len - 2])))
 +      && (isdigit ((unsigned char)encoded[*len - 2]) || islower ((unsigned char)encoded[*len - 2])))
      *len = *len - 1;
  }

 @@ -1224,7 +1224,7 @@ static int
  remove_compiler_suffix (const char *encoded, int *len)
  {
    int offset = *len - 1;
 -  while (offset > 0 && isalpha (encoded[offset]))
 +  while (offset > 0 && isalpha ((unsigned char)encoded[offset]))
      --offset;
    if (offset > 0 && encoded[offset] == '.')
      {
 @@ -1244,7 +1244,7 @@ convert_hex (const char *str, int n, uin

    for (int i = 0; i < n; ++i)
      {
 -      if (!isxdigit (str[i]))
 +      if (!isxdigit ((unsigned char)str[i]))
  	return false;
        result <<= 4;
        result |= fromhex (str[i]);
 @@ -1376,11 +1376,11 @@ ada_decode (const char *encoded, bool wr

    /* Remove trailing __{digit}+ or trailing ${digit}+.  */

 -  if (len0 > 1 && isdigit (encoded[len0 - 1]))
 +  if (len0 > 1 && isdigit ((unsigned char)encoded[len0 - 1]))
      {
        i = len0 - 2;
 -      while ((i >= 0 && isdigit (encoded[i]))
 -	     || (i >= 1 && encoded[i] == '_' && isdigit (encoded[i - 1])))
 +      while ((i >= 0 && isdigit ((unsigned char)encoded[i]))
 +	     || (i >= 1 && encoded[i] == '_' && isdigit ((unsigned char)encoded[i - 1])))
  	i -= 1;
        if (i > 1 && encoded[i] == '_' && encoded[i - 1] == '_')
  	len0 = i - 1;
 @@ -1391,7 +1391,7 @@ ada_decode (const char *encoded, bool wr
    /* The first few characters that are not alphabetic are not part
       of any encoding we use, so we can copy them over verbatim.  */

 -  for (i = 0; i < len0 && !isalpha (encoded[i]); i += 1)
 +  for (i = 0; i < len0 && !isalpha ((unsigned char)encoded[i]); i += 1)
      decoded.push_back (encoded[i]);

    at_start_name = 1;
 @@ -1407,7 +1407,7 @@ ada_decode (const char *encoded, bool wr
  	      int op_len = strlen (ada_opname_table[k].encoded);
  	      if ((strncmp (ada_opname_table[k].encoded + 1, encoded + i + 1,
  			    op_len - 1) == 0)
 -		  && !isalnum (encoded[i + op_len]))
 +		  && !isalnum ((unsigned char)encoded[i + op_len]))
  		{
  		  decoded.append (ada_opname_table[k].decoded);
  		  at_start_name = 0;
 @@ -1432,11 +1432,11 @@ ada_decode (const char *encoded, bool wr

        if (len0 - i > 5 && encoded [i] == '_' && encoded [i+1] == '_'
  	  && encoded [i+2] == 'B' && encoded [i+3] == '_'
 -	  && isdigit (encoded [i+4]))
 +	  && isdigit ((unsigned char)encoded [i+4]))
  	{
  	  int k = i + 5;

 -	  while (k < len0 && isdigit (encoded[k]))
 +	  while (k < len0 && isdigit ((unsigned char)encoded[k]))
  	    k++;  /* Skip any extra digit.  */

  	  /* Double-check that the "__B_{DIGITS}+" sequence we found
 @@ -1459,11 +1459,11 @@ ada_decode (const char *encoded, bool wr
  	 internally generated.  */

        if (len0 - i > 3 && encoded [i] == '_' && encoded[i+1] == 'E'
 -	  && isdigit (encoded[i+2]))
 +	  && isdigit ((unsigned char)encoded[i+2]))
  	{
  	  int k = i + 3;

 -	  while (k < len0 && isdigit (encoded[k]))
 +	  while (k < len0 && isdigit ((unsigned char)encoded[k]))
  	    k++;

  	  if (k < len0
 @@ -1497,7 +1497,7 @@ ada_decode (const char *encoded, bool wr
  	    i++;
  	}

 -      if (wide && i < len0 + 3 && encoded[i] == 'U' && isxdigit (encoded[i + 1]))
 +      if (wide && i < len0 + 3 && encoded[i] == 'U' && isxdigit ((unsigned char)encoded[i + 1]))
  	{
  	  if (convert_from_hex_encoded (decoded, &encoded[i + 1], 2))
  	    {
 @@ -1505,7 +1505,7 @@ ada_decode (const char *encoded, bool wr
  	      continue;
  	    }
  	}
 -      else if (wide && i < len0 + 5 && encoded[i] == 'W' && isxdigit (encoded[i + 1]))
 +      else if (wide && i < len0 + 5 && encoded[i] == 'W' && isxdigit ((unsigned char)encoded[i + 1]))
  	{
  	  if (convert_from_hex_encoded (decoded, &encoded[i + 1], 4))
  	    {
 @@ -1514,7 +1514,7 @@ ada_decode (const char *encoded, bool wr
  	    }
  	}
        else if (wide && i < len0 + 10 && encoded[i] == 'W' && encoded[i + 1] == 'W'
 -	       && isxdigit (encoded[i + 2]))
 +	       && isxdigit ((unsigned char)encoded[i + 2]))
  	{
  	  if (convert_from_hex_encoded (decoded, &encoded[i + 2], 8))
  	    {
 @@ -1523,7 +1523,7 @@ ada_decode (const char *encoded, bool wr
  	    }
  	}

 -      if (encoded[i] == 'X' && i != 0 && isalnum (encoded[i - 1]))
 +      if (encoded[i] == 'X' && i != 0 && isalnum ((unsigned char)encoded[i - 1]))
  	{
  	  /* This is a X[bn]* sequence not separated from the previous
  	     part of the name with a non-alpha-numeric character (in other
 @@ -1560,7 +1560,7 @@ ada_decode (const char *encoded, bool wr
    if (operators)
      {
        for (i = 0; i < decoded.length(); ++i)
 -	if (isupper (decoded[i]) || decoded[i] == ' ')
 +	if (isupper ((unsigned char)decoded[i]) || decoded[i] == ' ')
  	  goto Suppress;
      }

 @@ -3438,9 +3438,9 @@ encoded_ordered_before (const char *N0, 
      {
        int k0, k1;

 -      for (k0 = strlen (N0) - 1; k0 > 0 && isdigit (N0[k0]); k0 -= 1)
 +      for (k0 = strlen (N0) - 1; k0 > 0 && isdigit ((unsigned char)N0[k0]); k0 -= 1)
  	;
 -      for (k1 = strlen (N1) - 1; k1 > 0 && isdigit (N1[k1]); k1 -= 1)
 +      for (k1 = strlen (N1) - 1; k1 > 0 && isdigit ((unsigned char)N1[k1]); k1 -= 1)
  	;
        if ((N0[k0] == '_' || N0[k0] == '$') && N0[k0 + 1] != '\000'
  	  && (N1[k1] == '_' || N1[k1] == '$') && N1[k1 + 1] != '\000')
 @@ -5767,10 +5767,10 @@ is_name_suffix (const char *str)

    /* Skip optional leading __[0-9]+.  */

 -  if (len > 3 && str[0] == '_' && str[1] == '_' && isdigit (str[2]))
 +  if (len > 3 && str[0] == '_' && str[1] == '_' && isdigit ((unsigned char)str[2]))
      {
        str += 3;
 -      while (isdigit (str[0]))
 +      while (isdigit ((unsigned char)str[0]))
  	str += 1;
      }

 @@ -5779,7 +5779,7 @@ is_name_suffix (const char *str)
    if (str[0] == '.' || str[0] == '$')
      {
        matching = str + 1;
 -      while (isdigit (matching[0]))
 +      while (isdigit ((unsigned char)matching[0]))
  	matching += 1;
        if (matching[0] == '\0')
  	return 1;
 @@ -5790,7 +5790,7 @@ is_name_suffix (const char *str)
    if (len > 3 && str[0] == '_' && str[1] == '_' && str[2] == '_')
      {
        matching = str + 3;
 -      while (isdigit (matching[0]))
 +      while (isdigit ((unsigned char)matching[0]))
  	matching += 1;
        if (matching[0] == '\0')
  	return 1;
 @@ -5819,10 +5819,10 @@ is_name_suffix (const char *str)
  #endif

    /* _E[0-9]+[bs]$ */
 -  if (len > 3 && str[0] == '_' && str [1] == 'E' && isdigit (str[2]))
 +  if (len > 3 && str[0] == '_' && str [1] == 'E' && isdigit ((unsigned char)str[2]))
      {
        matching = str + 3;
 -      while (isdigit (matching[0]))
 +      while (isdigit ((unsigned char)matching[0]))
  	matching += 1;
        if ((matching[0] == 'b' || matching[0] == 's')
  	  && matching [1] == '\0')
 @@ -5872,17 +5872,17 @@ is_name_suffix (const char *str)
  	    return 1;
  	  return 0;
  	}
 -      if (!isdigit (str[2]))
 +      if (!isdigit ((unsigned char)str[2]))
  	return 0;
        for (k = 3; str[k] != '\0'; k += 1)
 -	if (!isdigit (str[k]) && str[k] != '_')
 +	if (!isdigit ((unsigned char)str[k]) && str[k] != '_')
  	  return 0;
        return 1;
      }
 -  if (str[0] == '$' && isdigit (str[1]))
 +  if (str[0] == '$' && isdigit ((unsigned char)str[1]))
      {
        for (k = 2; str[k] != '\0'; k += 1)
 -	if (!isdigit (str[k]) && str[k] != '_')
 +	if (!isdigit ((unsigned char)str[k]) && str[k] != '_')
  	  return 0;
        return 1;
      }
 @@ -5905,7 +5905,7 @@ is_valid_name_for_wild_match (const char
      return 0;

    for (i=0; decoded_name[i] != '\0'; i++)
 -    if (isalpha (decoded_name[i]) && !islower (decoded_name[i]))
 +    if (isalpha ((unsigned char)decoded_name[i]) && !islower ((unsigned char)decoded_name[i]))
        return 0;

    return 1;
 @@ -6129,7 +6129,7 @@ ada_lookup_name_info::matches
  	 angle bracket notation.  */
        const char *tmp;

 -      for (tmp = sym_name; *tmp != '\0' && !isupper (*tmp); tmp++);
 +      for (tmp = sym_name; *tmp != '\0' && !isupper ((unsigned char)*tmp); tmp++);
        if (*tmp != '\0')
  	match = false;
      }
 @@ -6244,7 +6244,7 @@ ada_is_ignored_field (struct type *type,
        {
  	/* Wrapper field.  */
        }
 -    else if (isupper (name[0]))
 +    else if (isupper ((unsigned char)name[0]))
        return 1;
    }

 @@ -6753,14 +6753,14 @@ ada_scan_number (const char str[], int k
  {
    ULONGEST RU;

 -  if (!isdigit (str[k]))
 +  if (!isdigit ((unsigned char)str[k]))
      return 0;

    /* Do it the hard way so as not to make any assumption about
       the relationship of unsigned long (%lu scan format code) and
       LONGEST.  */
    RU = 0;
 -  while (isdigit (str[k]))
 +  while (isdigit ((unsigned char)str[k]))
      {
        RU = RU * 10 + (str[k] - '0');
        k += 1;
 @@ -7417,10 +7417,10 @@ field_alignment (struct type *type, int 

    len = strlen (name);

 -  if (!isdigit (name[len - 1]))
 +  if (!isdigit ((unsigned char)name[len - 1]))
      return 1;

 -  if (isdigit (name[len - 2]))
 +  if (isdigit ((unsigned char)name[len - 2]))
      align_offset = len - 2;
    else
      align_offset = len - 1;
 @@ -8998,7 +8998,7 @@ ada_enum_name (const char *name)
      {
        while ((tmp = strstr (name, "__")) != NULL)
  	{
 -	  if (isdigit (tmp[2]))
 +	  if (isdigit ((unsigned char)tmp[2]))
  	    break;
  	  else
  	    name = tmp + 2;
 @@ -9030,7 +9030,7 @@ ada_enum_name (const char *name)
        else
  	return name;

 -      if (isascii (v) && isprint (v))
 +      if (isascii ((unsigned char)v) && isprint ((unsigned char)v))
  	storage = string_printf ("'%c'", v);
        else if (name[1] == 'U')
  	storage = string_printf ("'[\"%02x\"]'", v);
 @@ -12542,7 +12542,7 @@ catch_ada_exception_command_split (const

    args = skip_spaces (args);
    if (startswith (args, "if")
 -      && (isspace (args[2]) || args[2] == '\0'))
 +      && (isspace ((unsigned char)args[2]) || args[2] == '\0'))
      {
        args += 2;
        args = skip_spaces (args);
 @@ -12815,7 +12815,7 @@ catch_ada_assert_command_split (const ch

    /* Check whether a condition was provided.  */
    if (startswith (args, "if")
 -      && (isspace (args[2]) || args[2] == '\0'))
 +      && (isspace ((unsigned char)args[2]) || args[2] == '\0'))
      {
        args += 2;
        args = skip_spaces (args);
 @@ -13216,7 +13216,7 @@ do_full_match (const char *symbol_search
  	      && symbol_search_name[1] == '_')
  	    {
  	      symbol_search_name += 2;
 -	      while (isdigit (*symbol_search_name))
 +	      while (isdigit ((unsigned char)*symbol_search_name))
  		++symbol_search_name;
  	      if (symbol_search_name[0] == '_'
  		  && symbol_search_name[1] == '_')
 Index: ada-typeprint.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/ada-typeprint.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 ada-typeprint.c
 --- ada-typeprint.c	12 Aug 2024 21:38:07 -0000	1.1.1.11
 +++ ada-typeprint.c	27 Jul 2025 18:20:55 -0000
 @@ -72,7 +72,7 @@ decoded_type_name (struct type *type)
        if (s == name_buffer)
  	return name_buffer;

 -      if (!islower (s[1]))
 +      if (!islower ((unsigned char)s[1]))
  	return NULL;

        for (s = q = name_buffer; *s != '\0'; q += 1)
 Index: ada-valprint.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/ada-valprint.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 ada-valprint.c
 --- ada-valprint.c	12 Aug 2024 21:38:16 -0000	1.1.1.11
 +++ ada-valprint.c	27 Jul 2025 18:20:55 -0000
 @@ -268,7 +268,7 @@ ada_emit_char (int c, struct type *type,
       The UCHAR_MAX check is necessary because the isascii function
       requires that its argument have a value of an unsigned char,
       or EOF (EOF is obviously not printable).  */
 -  if (c <= UCHAR_MAX && isascii (c) && isprint (c))
 +  if (c <= UCHAR_MAX && isascii ((unsigned char)c) && isprint (c))
      {
        if (c == quoter && c == '"')
  	gdb_printf (stream, "\"\"");
 Index: arm-linux-tdep.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/arm-linux-tdep.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 arm-linux-tdep.c
 --- arm-linux-tdep.c	12 Aug 2024 21:37:55 -0000	1.1.1.11
 +++ arm-linux-tdep.c	27 Jul 2025 18:20:55 -0000
 @@ -1165,10 +1165,10 @@ arm_linux_displaced_step_copy_insn (stru
  static int
  arm_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
  {
 -  return (*s == '#' || *s == '$' || isdigit (*s) /* Literal number.  */
 +  return (*s == '#' || *s == '$' || isdigit ((unsigned char)*s) /* Literal number.  */
  	  || *s == '[' /* Register indirection or
  			  displacement.  */
 -	  || isalpha (*s)); /* Register value.  */
 +	  || isalpha ((unsigned char)*s)); /* Register value.  */
  }

  /* This routine is used to parse a special token in ARM's assembly.
 @@ -1200,7 +1200,7 @@ arm_stap_parse_special_token (struct gdb
        start = tmp;

        /* Register name.  */
 -      while (isalnum (*tmp))
 +      while (isalnum ((unsigned char)*tmp))
  	++tmp;

        if (*tmp != ',')
 @@ -1210,7 +1210,7 @@ arm_stap_parse_special_token (struct gdb
        regname = (char *) alloca (len + 2);

        offset = 0;
 -      if (isdigit (*start))
 +      if (isdigit ((unsigned char)*start))
  	{
  	  /* If we are dealing with a register whose name begins with a
  	     digit, it means we should prefix the name with the letter
 Index: auto-load.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/auto-load.c,v
 retrieving revision 1.1.1.10
 diff -u -p -u -r1.1.1.10 auto-load.c
 --- auto-load.c	12 Aug 2024 21:38:07 -0000	1.1.1.10
 +++ auto-load.c	27 Jul 2025 18:20:55 -0000
 @@ -979,7 +979,7 @@ execute_script_contents (struct auto_loa
        buf = name_holder.c_str ();
        for (p = buf; *p != '\0'; ++p)
  	{
 -	  if (isspace (*p))
 +	  if (isspace ((unsigned char)*p))
  	    break;
  	}
        /* We don't allow nameless scripts, they're not helpful to the user.  */
 Index: break-catch-exec.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/break-catch-exec.c,v
 retrieving revision 1.1.1.2
 diff -u -p -u -r1.1.1.2 break-catch-exec.c
 --- break-catch-exec.c	12 Aug 2024 21:37:57 -0000	1.1.1.2
 +++ break-catch-exec.c	27 Jul 2025 18:20:55 -0000
 @@ -164,7 +164,7 @@ ep_parse_optional_if_clause (const char 
  {
    const char *cond_string;

 -  if (((*arg)[0] != 'i') || ((*arg)[1] != 'f') || !isspace ((*arg)[2]))
 +  if (((*arg)[0] != 'i') || ((*arg)[1] != 'f') || !isspace ((unsigned char)(*arg)[2]))
      return NULL;

    /* Skip the "if" keyword.  */
 @@ -204,7 +204,7 @@ catch_exec_command_1 (const char *arg, i
       First, check if there's an if clause.  */
    cond_string = ep_parse_optional_if_clause (&arg);

 -  if ((*arg != '\0') && !isspace (*arg))
 +  if ((*arg != '\0') && !isspace ((unsigned char)*arg))
      error (_("Junk at end of arguments."));

    std::unique_ptr<exec_catchpoint> c
 Index: break-catch-fork.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/break-catch-fork.c,v
 retrieving revision 1.1.1.2
 diff -u -p -u -r1.1.1.2 break-catch-fork.c
 --- break-catch-fork.c	12 Aug 2024 21:38:03 -0000	1.1.1.2
 +++ break-catch-fork.c	27 Jul 2025 18:20:55 -0000
 @@ -221,7 +221,7 @@ catch_fork_command_1 (const char *arg, i
       First, check if there's an if clause.  */
    cond_string = ep_parse_optional_if_clause (&arg);

 -  if ((*arg != '\0') && !isspace (*arg))
 +  if ((*arg != '\0') && !isspace ((unsigned char)*arg))
      error (_("Junk at end of arguments."));

    /* If this target supports it, create a fork or vfork catchpoint
 Index: break-catch-syscall.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/break-catch-syscall.c,v
 retrieving revision 1.1.1.7
 diff -u -p -u -r1.1.1.7 break-catch-syscall.c
 --- break-catch-syscall.c	12 Aug 2024 21:38:07 -0000	1.1.1.7
 +++ break-catch-syscall.c	27 Jul 2025 18:20:55 -0000
 @@ -370,7 +370,7 @@ catch_syscall_split_args (const char *ar
        /* Skip whitespace.  */
        arg = skip_spaces (arg);

 -      for (i = 0; i < 127 && arg[i] && !isspace (arg[i]); ++i)
 +      for (i = 0; i < 127 && arg[i] && !isspace ((unsigned char)arg[i]); ++i)
  	cur_name[i] = arg[i];
        cur_name[i] = '\0';
        arg += i;
 Index: break-catch-throw.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/break-catch-throw.c,v
 retrieving revision 1.1.1.9
 diff -u -p -u -r1.1.1.9 break-catch-throw.c
 --- break-catch-throw.c	12 Aug 2024 21:37:54 -0000	1.1.1.9
 +++ break-catch-throw.c	27 Jul 2025 18:20:55 -0000
 @@ -424,7 +424,7 @@ catch_exception_event (enum exception_ev

    cond_string = ep_parse_optional_if_clause (&arg);

 -  if ((*arg != '\0') && !isspace (*arg))
 +  if ((*arg != '\0') && !isspace ((unsigned char)*arg))
      error (_("Junk at end of arguments."));

    if (ex_event != EX_EVENT_THROW
 Index: breakpoint.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/breakpoint.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 breakpoint.c
 --- breakpoint.c	12 Aug 2024 21:37:52 -0000	1.1.1.11
 +++ breakpoint.c	27 Jul 2025 18:20:56 -0000
 @@ -1264,7 +1264,7 @@ condition_completer (struct cmd_list_ele
  	{
  	  tracker.advance_custom_word_point_by (1);
  	  /* We don't support completion of history indices.  */
 -	  if (!isdigit (text[1]))
 +	  if (!isdigit ((unsigned char)text[1]))
  	    complete_internalvar (tracker, &text[1]);
  	  return;
  	}
 @@ -10445,7 +10445,7 @@ watch_command_1 (const char *arg, int ac
        int len;

        len = exp_end - exp_start;
 -      while (len > 0 && isspace (exp_start[len - 1]))
 +      while (len > 0 && isspace ((unsigned char)exp_start[len - 1]))
  	len--;
        error (_("Cannot watch constant value `%.*s'."), len, exp_start);
      }
 @@ -14067,7 +14067,7 @@ strace_command (const char *arg, int fro

    /* Decide if we are dealing with a static tracepoint marker (`-m'),
       or with a normal static tracepoint.  */
 -  if (arg && startswith (arg, "-m") && isspace (arg[2]))
 +  if (arg && startswith (arg, "-m") && isspace ((unsigned char)arg[2]))
      {
        ops = &strace_marker_breakpoint_ops;
        locspec = new_linespec_location_spec (&arg,
 Index: btrace.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/btrace.c,v
 retrieving revision 1.1.1.10
 diff -u -p -u -r1.1.1.10 btrace.c
 --- btrace.c	12 Aug 2024 21:37:52 -0000	1.1.1.10
 +++ btrace.c	27 Jul 2025 18:20:56 -0000
 @@ -2881,7 +2881,7 @@ get_uint (const char **arg)
    begin = *arg;
    pos = skip_spaces (begin);

 -  if (!isdigit (*pos))
 +  if (!isdigit ((unsigned char)*pos))
      error (_("Expected positive number, got: %s."), pos);

    number = strtoul (pos, &end, 10);
 @@ -2900,7 +2900,7 @@ get_context_size (const char **arg)
  {
    const char *pos = skip_spaces (*arg);

 -  if (!isdigit (*pos))
 +  if (!isdigit ((unsigned char)*pos))
      error (_("Expected positive number, got: %s."), pos);

    char *end;
 Index: coff-pe-read.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/coff-pe-read.c,v
 retrieving revision 1.1.1.10
 diff -u -p -u -r1.1.1.10 coff-pe-read.c
 --- coff-pe-read.c	12 Aug 2024 21:37:55 -0000	1.1.1.10
 +++ coff-pe-read.c	27 Jul 2025 18:20:56 -0000
 @@ -190,7 +190,7 @@ add_pe_forwarded_sym (minimal_symbol_rea
        int i;

        for (i = 0; i < forward_dll_name_len; i++)
 -	forward_qualified_name[i] = tolower (forward_qualified_name[i]);
 +	forward_qualified_name[i] = tolower ((unsignec char)forward_qualified_name[i]);
        msymbol = lookup_bound_minimal_symbol (forward_qualified_name.c_str ());
      }

 Index: coffread.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/coffread.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 coffread.c
 --- coffread.c	12 Aug 2024 21:37:55 -0000	1.1.1.11
 +++ coffread.c	27 Jul 2025 18:20:56 -0000
 @@ -242,7 +242,7 @@ coff_locate_sections (bfd *abfd, asectio
        /* We can have multiple .stab sections if linked with
  	 --split-by-reloc.  */
        for (s = name + sizeof ".stab" - 1; *s != '\0'; s++)
 -	if (!isdigit (*s))
 +	if (!isdigit ((unsigned char)*s))
  	  break;
        if (*s == '\0')
  	csi->stabsects->push_back (sectp);
 @@ -431,9 +431,9 @@ is_import_fixup_symbol (struct coff_symb
    /* The name must start with "__fu<digits>__".  */
    if (!startswith (cs->c_name, "__fu"))
      return 0;
 -  if (! isdigit (cs->c_name[4]))
 +  if (! isdigit ((unsigned char)cs->c_name[4]))
      return 0;
 -  for (i = 5; cs->c_name[i] != '\0' && isdigit (cs->c_name[i]); i++)
 +  for (i = 5; cs->c_name[i] != '\0' && isdigit ((unsigned char)cs->c_name[i]); i++)
      /* Nothing, just incrementing index past all digits.  */;
    if (cs->c_name[i] != '_' || cs->c_name[i + 1] != '_')
      return 0;
 Index: exec.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/exec.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 exec.c
 --- exec.c	12 Aug 2024 21:38:09 -0000	1.1.1.11
 +++ exec.c	27 Jul 2025 18:20:56 -0000
 @@ -990,7 +990,7 @@ set_section_command (const char *args, i
      error (_("Must specify section name and its virtual address"));

    /* Parse out section name.  */
 -  for (secname = args; !isspace (*args); args++);
 +  for (secname = args; !isspace ((unsigned char)*args); args++);
    unsigned seclen = args - secname;

    /* Parse out new virtual address.  */
 Index: fbsd-nat.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/fbsd-nat.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 fbsd-nat.c
 --- fbsd-nat.c	12 Aug 2024 21:38:11 -0000	1.1.1.11
 +++ fbsd-nat.c	27 Jul 2025 18:20:56 -0000
 @@ -303,7 +303,7 @@ fbsd_nat_target::info_proc (const char *
        if (pid == 0)
  	error (_("No current process: you must name one."));
      }
 -  else if (built_argv.count () == 1 && isdigit (built_argv[0][0]))
 +  else if (built_argv.count () == 1 && isdigit ((unsigned char)built_argv[0][0]))
      pid = strtol (built_argv[0], NULL, 10);
    else
      error (_("Invalid arguments."));
 Index: findcmd.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/findcmd.c,v
 retrieving revision 1.1.1.10
 diff -u -p -u -r1.1.1.10 findcmd.c
 --- findcmd.c	12 Aug 2024 21:37:54 -0000	1.1.1.10
 +++ findcmd.c	27 Jul 2025 18:20:56 -0000
 @@ -76,12 +76,12 @@ parse_find_args (const char *args, ULONG
      {
        ++s;

 -      while (*s != '\0' && *s != '/' && !isspace (*s))
 +      while (*s != '\0' && *s != '/' && !isspace ((unsigned char)*s))
  	{
 -	  if (isdigit (*s))
 +	  if (isdigit ((unsigned char)*s))
  	    {
  	      max_count = atoi (s);
 -	      while (isdigit (*s))
 +	      while (isdigit ((unsigned char)*s))
  		++s;
  	      continue;
  	    }
 Index: gnu-nat.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/gnu-nat.c,v
 retrieving revision 1.1.1.10
 diff -u -p -u -r1.1.1.10 gnu-nat.c
 --- gnu-nat.c	12 Aug 2024 21:38:06 -0000	1.1.1.10
 +++ gnu-nat.c	27 Jul 2025 18:20:56 -0000
 @@ -2921,7 +2921,7 @@ set_sig_thread_cmd (const char *args, in
  {
    struct inf *inf = cur_inf ();

 -  if (!args || (!isdigit (*args) && strcmp (args, "none") != 0))
 +  if (!args || (!isdigit ((unsigned char)*args) && strcmp (args, "none") != 0))
      error (_("Illegal argument to \"set signal-thread\" command.\n"
  	     "Should be a thread ID, or \"none\"."));

 Index: gnu-v2-abi.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/gnu-v2-abi.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 gnu-v2-abi.c
 --- gnu-v2-abi.c	12 Aug 2024 21:37:52 -0000	1.1.1.11
 +++ gnu-v2-abi.c	27 Jul 2025 18:20:56 -0000
 @@ -46,7 +46,7 @@ static enum ctor_kinds
  gnuv2_is_constructor_name (const char *name)
  {
    if ((name[0] == '_' && name[1] == '_'
 -       && (isdigit (name[2]) || strchr ("Qt", name[2])))
 +       && (isdigit ((unsigned char)name[2]) || strchr ("Qt", name[2])))
        || startswith (name, "__ct__"))
      return complete_object_ctor;
    else
 Index: go-lang.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/go-lang.c,v
 retrieving revision 1.1.1.10
 diff -u -p -u -r1.1.1.10 go-lang.c
 --- go-lang.c	12 Aug 2024 21:37:54 -0000	1.1.1.10
 +++ go-lang.c	27 Jul 2025 18:20:56 -0000
 @@ -293,7 +293,7 @@ unpack_mangled_go_symbol (const char *ma
    while (p > buf)
      {
        int current = *(const unsigned char *) --p;
 -      int current_is_digit = isdigit (current);
 +      int current_is_digit = isdigit ((unsigned char)current);

        if (saw_digit)
  	{
 Index: i386-tdep.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/i386-tdep.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 i386-tdep.c
 --- i386-tdep.c	12 Aug 2024 21:37:55 -0000	1.1.1.11
 +++ i386-tdep.c	27 Jul 2025 18:20:56 -0000
 @@ -4048,9 +4048,9 @@ int
  i386_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
  {
    return (*s == '$' /* Literal number.  */
 -	  || (isdigit (*s) && s[1] == '(' && s[2] == '%') /* Displacement.  */
 +	  || (isdigit ((unsigned char)*s) && s[1] == '(' && s[2] == '%') /* Displacement.  */
  	  || (*s == '(' && s[1] == '%') /* Register indirection.  */
 -	  || (*s == '%' && isalpha (s[1]))); /* Register access.  */
 +	  || (*s == '%' && isalpha ((unsigned char)s[1]))); /* Register access.  */
  }

  /* Helper function for i386_stap_parse_special_token.
 @@ -4067,7 +4067,7 @@ i386_stap_parse_special_token_triplet (s
  {
    const char *s = p->arg;

 -  if (isdigit (*s) || *s == '-' || *s == '+')
 +  if (isdigit ((unsigned char)*s) || *s == '-' || *s == '+')
      {
        bool got_minus[3];
        int i;
 @@ -4139,7 +4139,7 @@ i386_stap_parse_special_token_triplet (s
        s += 2;
        start = s;

 -      while (isalnum (*s))
 +      while (isalnum ((unsigned char)*s))
  	++s;

        if (*s++ != ')')
 @@ -4200,7 +4200,7 @@ i386_stap_parse_special_token_three_arg_
  {
    const char *s = p->arg;

 -  if (isdigit (*s) || *s == '(' || *s == '-' || *s == '+')
 +  if (isdigit ((unsigned char)*s) || *s == '(' || *s == '-' || *s == '+')
      {
        bool offset_minus = false;
        long offset = 0;
 @@ -4218,10 +4218,10 @@ i386_stap_parse_special_token_three_arg_
  	  offset_minus = true;
  	}

 -      if (offset_minus && !isdigit (*s))
 +      if (offset_minus && !isdigit ((unsigned char)*s))
  	return {};

 -      if (isdigit (*s))
 +      if (isdigit ((unsigned char)*s))
  	{
  	  char *endp;

 @@ -4235,7 +4235,7 @@ i386_stap_parse_special_token_three_arg_
        s += 2;
        start = s;

 -      while (isalnum (*s))
 +      while (isalnum ((unsigned char)*s))
  	++s;

        if (*s != ',' || s[1] != '%')
 @@ -4251,7 +4251,7 @@ i386_stap_parse_special_token_three_arg_
        s += 2;
        start = s;

 -      while (isalnum (*s))
 +      while (isalnum ((unsigned char)*s))
  	++s;

        len_index = s - start;
 Index: ia64-linux-tdep.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/ia64-linux-tdep.c,v
 retrieving revision 1.1.1.10
 diff -u -p -u -r1.1.1.10 ia64-linux-tdep.c
 --- ia64-linux-tdep.c	12 Aug 2024 21:38:04 -0000	1.1.1.10
 +++ ia64-linux-tdep.c	27 Jul 2025 18:20:56 -0000
 @@ -127,9 +127,9 @@ ia64_linux_write_pc (struct regcache *re
  static int
  ia64_linux_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
  {
 -  return ((isdigit (*s) && s[1] == '[' && s[2] == 'r') /* Displacement.  */
 +  return ((isdigit ((unsigned char)*s) && s[1] == '[' && s[2] == 'r') /* Displacement.  */
  	  || *s == 'r' /* Register value.  */
 -	  || isdigit (*s));  /* Literal number.  */
 +	  || isdigit ((unsigned char)*s));  /* Literal number.  */
  }

  /* Core file support. */
 Index: infcmd.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/infcmd.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 infcmd.c
 --- infcmd.c	12 Aug 2024 21:37:58 -0000	1.1.1.11
 +++ infcmd.c	27 Jul 2025 18:20:56 -0000
 @@ -207,7 +207,7 @@ strip_bg_char (const char *args, int *bg
    if (p[-1] == '&')
      {
        p--;
 -      while (p > args && isspace (p[-1]))
 +      while (p > args && isspace ((unsigned char)p[-1]))
  	p--;

        *bg_char_p = 1;
 @@ -2308,12 +2308,12 @@ registers_info (const char *addr_exp, in
  	 resembling a register following it.  */
        if (addr_exp[0] == '$')
  	addr_exp++;
 -      if (isspace ((*addr_exp)) || (*addr_exp) == '\0')
 +      if (isspace ((unsigned char)(*addr_exp)) || (*addr_exp) == '\0')
  	error (_("Missing register name"));

        /* Find the start/end of this register name/num/group.  */
        start = addr_exp;
 -      while ((*addr_exp) != '\0' && !isspace ((*addr_exp)))
 +      while ((*addr_exp) != '\0' && !isspace ((unsigned char)(*addr_exp)))
  	addr_exp++;
        end = addr_exp;

 Index: infrun.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/infrun.c,v
 retrieving revision 1.7
 diff -u -p -u -r1.7 infrun.c
 --- infrun.c	12 Aug 2024 22:09:30 -0000	1.7
 +++ infrun.c	27 Jul 2025 18:20:56 -0000
 @@ -9781,7 +9781,7 @@ handle_command (const char *args, int fr
    for (char *arg : built_argv)
      {
        wordlen = strlen (arg);
 -      for (digits = 0; isdigit (arg[digits]); digits++)
 +      for (digits = 0; isdigit ((unsigned char)arg[digits]); digits++)
  	{;
  	}
        allsigs = 0;
 Index: linespec.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/linespec.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 linespec.c
 --- linespec.c	12 Aug 2024 21:38:01 -0000	1.1.1.11
 +++ linespec.c	27 Jul 2025 18:20:57 -0000
 @@ -444,7 +444,7 @@ linespec_lexer_lex_number (linespec_pars
        ++(PARSER_STREAM (parser));
      }

 -  while (isdigit (*PARSER_STREAM (parser)))
 +  while (isdigit ((unsigned char)*PARSER_STREAM (parser)))
      {
        ++LS_TOKEN_STOKEN (*tokenp).length;
        ++(PARSER_STREAM (parser));
 @@ -453,7 +453,7 @@ linespec_lexer_lex_number (linespec_pars
    /* If the next character in the input buffer is not a space, comma,
       quote, or colon, this input does not represent a number.  */
    if (*PARSER_STREAM (parser) != '\0'
 -      && !isspace (*PARSER_STREAM (parser)) && *PARSER_STREAM (parser) != ','
 +      && !isspace ((unsigned char)*PARSER_STREAM (parser)) && *PARSER_STREAM (parser) != ','
        && *PARSER_STREAM (parser) != ':'
        && !strchr (linespec_quote_characters, *PARSER_STREAM (parser)))
      {
 @@ -497,7 +497,7 @@ linespec_lexer_lex_keyword (const char *
  	      if (i == FORCE_KEYWORD_INDEX && p[len] == '\0')
  		return linespec_keywords[i];

 -	      if (!isspace (p[len]))
 +	      if (!isspace ((unsigned char)p[len]))
  		continue;

  	      if (i == FORCE_KEYWORD_INDEX)
 @@ -509,7 +509,7 @@ linespec_lexer_lex_keyword (const char *
  		      int nextlen = strlen (linespec_keywords[j]);

  		      if (strncmp (p, linespec_keywords[j], nextlen) == 0
 -			  && isspace (p[nextlen]))
 +			  && isspace ((unsigned char)p[nextlen]))
  			return linespec_keywords[i];
  		    }
  		}
 @@ -523,7 +523,7 @@ linespec_lexer_lex_keyword (const char *
  		      int nextlen = strlen (linespec_keywords[j]);

  		      if (strncmp (p, linespec_keywords[j], nextlen) == 0
 -			  && isspace (p[nextlen]))
 +			  && isspace ((unsigned char)p[nextlen]))
  			return NULL;
  		    }
  		}
 @@ -748,7 +748,7 @@ linespec_lexer_lex_string (linespec_pars

        while (1)
  	{
 -	  if (isspace (*PARSER_STREAM (parser)))
 +	  if (isspace ((unsigned char)*PARSER_STREAM (parser)))
  	    {
  	      p = skip_spaces (PARSER_STREAM (parser));
  	      /* When we get here we know we've found something followed by
 @@ -826,14 +826,14 @@ linespec_lexer_lex_string (linespec_pars
  		{
  		  const char *op = PARSER_STREAM (parser);

 -		  while (op > start && isspace (op[-1]))
 +		  while (op > start && isspace ((unsigned char)op[-1]))
  		    op--;
  		  if (op - start >= CP_OPERATOR_LEN)
  		    {
  		      op -= CP_OPERATOR_LEN;
  		      if (strncmp (op, CP_OPERATOR_STR, CP_OPERATOR_LEN) == 0
  			  && (op == start
 -			      || !(isalnum (op[-1]) || op[-1] == '_')))
 +			      || !(isalnum ((unsigned char)op[-1]) || op[-1] == '_')))
  			{
  			  /* This is an operator name.  Keep going.  */
  			  ++(PARSER_STREAM (parser));
 @@ -1676,7 +1676,7 @@ linespec_parse_line_offset (const char *
    else
      line_offset.sign = LINE_OFFSET_NONE;

 -  if (*string != '\0' && !isdigit (*string))
 +  if (*string != '\0' && !isdigit ((unsigned char)*string))
      error (_("malformed line offset: \"%s\""), start);

    /* Right now, we only allow base 10 for offsets.  */
 Index: linux-fork.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/linux-fork.c,v
 retrieving revision 1.1.1.10
 diff -u -p -u -r1.1.1.10 linux-fork.c
 --- linux-fork.c	12 Aug 2024 21:38:15 -0000	1.1.1.10
 +++ linux-fork.c	27 Jul 2025 18:20:57 -0000
 @@ -285,7 +285,7 @@ fork_save_infrun_state (struct fork_info
        /* Now find actual file positions.  */
        rewinddir (d);
        while ((de = readdir (d)) != NULL)
 -	if (isdigit (de->d_name[0]))
 +	if (isdigit ((unsigned char)de->d_name[0]))
  	  {
  	    tmp = strtol (&de->d_name[0], NULL, 10);
  	    fp->filepos[tmp] = call_lseek (tmp, 0, SEEK_CUR);
 Index: linux-tdep.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/linux-tdep.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 linux-tdep.c
 --- linux-tdep.c	12 Aug 2024 21:38:04 -0000	1.1.1.11
 +++ linux-tdep.c	27 Jul 2025 18:20:57 -0000
 @@ -481,7 +481,7 @@ read_mapping (const char *line)

    p = skip_spaces (p);
    const char *permissions_start = p;
 -  while (*p && !isspace (*p))
 +  while (*p && !isspace ((unsigned char)*p))
      p++;
    mapping.permissions = {permissions_start, (size_t) (p - permissions_start)};

 @@ -489,7 +489,7 @@ read_mapping (const char *line)

    p = skip_spaces (p);
    const char *device_start = p;
 -  while (*p && !isspace (*p))
 +  while (*p && !isspace ((unsigned char)*p))
      p++;
    mapping.device = {device_start, (size_t) (p - device_start)};

 @@ -825,7 +825,7 @@ linux_info_proc (struct gdbarch *gdbarch
    char filename[100];
    fileio_error target_errno;

 -  if (args && isdigit (args[0]))
 +  if (args && isdigit ((unsigned char)args[0]))
      {
        char *tem;

 @@ -1952,7 +1952,7 @@ linux_fill_prpsinfo (struct elf_internal
       specifically under the entry of `/proc/[pid]/stat'.  */

    /* Getting rid of the PID, since we already have it.  */
 -  while (isdigit (*proc_stat))
 +  while (isdigit ((unsigned char)*proc_stat))
      ++proc_stat;

    proc_stat = skip_spaces (proc_stat);
 @@ -2024,10 +2024,10 @@ linux_fill_prpsinfo (struct elf_internal
      {
        /* Advancing the pointer to the beginning of the UID.  */
        tmpstr += sizeof ("Uid:");
 -      while (*tmpstr != '\0' && !isdigit (*tmpstr))
 +      while (*tmpstr != '\0' && !isdigit ((unsigned char)*tmpstr))
  	++tmpstr;

 -      if (isdigit (*tmpstr))
 +      if (isdigit ((unsigned char)*tmpstr))
  	p->pr_uid = strtol (tmpstr, &tmpstr, 10);
      }

 @@ -2037,10 +2037,10 @@ linux_fill_prpsinfo (struct elf_internal
      {
        /* Advancing the pointer to the beginning of the GID.  */
        tmpstr += sizeof ("Gid:");
 -      while (*tmpstr != '\0' && !isdigit (*tmpstr))
 +      while (*tmpstr != '\0' && !isdigit ((unsigned char)*tmpstr))
  	++tmpstr;

 -      if (isdigit (*tmpstr))
 +      if (isdigit ((unsigned char)*tmpstr))
  	p->pr_gid = strtol (tmpstr, &tmpstr, 10);
      }

 Index: location.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/location.c,v
 retrieving revision 1.4
 diff -u -p -u -r1.4 location.c
 --- location.c	12 Aug 2024 22:09:30 -0000	1.4
 +++ location.c	27 Jul 2025 18:20:57 -0000
 @@ -408,15 +408,15 @@ explicit_location_spec_lex_one (const ch
       whitespace or comma.  */
    if (*start == '-' || *start == '+')
      {
 -      while (*inp[0] != '\0' && *inp[0] != ',' && !isspace (*inp[0]))
 +      while (*inp[0] != '\0' && *inp[0] != ',' && !isspace ((unsigned char)*inp[0]))
  	++(*inp);
      }
    else
      {
        /* Handle numbers first, stopping at the next whitespace or ','.  */
 -      while (isdigit (*inp[0]))
 +      while (isdigit ((unsigned char)*inp[0]))
  	++(*inp);
 -      if (*inp[0] == '\0' || isspace (*inp[0]) || *inp[0] == ',')
 +      if (*inp[0] == '\0' || isspace ((unsigned char)*inp[0]) || *inp[0] == ',')
  	return gdb::unique_xmalloc_ptr<char> (savestring (start,
  							  *inp - start));

 @@ -425,7 +425,7 @@ explicit_location_spec_lex_one (const ch
        *inp = start;
        while ((*inp)[0]
  	     && (*inp)[0] != ','
 -	     && !(isspace ((*inp)[0])
 +	     && !(isspace ((unsigned char)(*inp)[0])
  		  || linespec_lexer_lex_keyword (&(*inp)[1])))
  	{
  	  /* Special case: C++ operator,.  */
 @@ -454,14 +454,14 @@ is_cp_operator (const char *start, const
      {
        const char *p = comma;

 -      while (p > start && isspace (p[-1]))
 +      while (p > start && isspace ((unsigned char)p[-1]))
  	p--;
        if (p - start >= CP_OPERATOR_LEN)
  	{
  	  p -= CP_OPERATOR_LEN;
  	  if (strncmp (p, CP_OPERATOR_STR, CP_OPERATOR_LEN) == 0
  	      && (p == start
 -		  || !(isalnum (p[-1]) || p[-1] == '_')))
 +		  || !(isalnum ((unsigned char)p[-1]) || p[-1] == '_')))
  	    {
  	      return true;
  	    }
 @@ -624,7 +624,7 @@ string_to_explicit_location_spec (const 
    if (argp == NULL
        || *argp == NULL
        || *argp[0] != '-'
 -      || !isalpha ((*argp)[1])
 +      || !isalpha ((unsigned char)(*argp)[1])
        || ((*argp)[0] == '-' && (*argp)[1] == 'p'))
      return NULL;

 @@ -728,7 +728,7 @@ string_to_explicit_location_spec (const 
  	}
        /* Only emit an "invalid argument" error for options
  	 that look like option strings.  */
 -      else if (opt.get ()[0] == '-' && !isdigit (opt.get ()[1]))
 +      else if (opt.get ()[0] == '-' && !isdigit ((unsigned char)opt.get ()[1]))
  	{
  	  if (completion_info == NULL)
  	    error (_("invalid explicit location argument, \"%s\""), opt.get ());
 Index: main.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/main.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 main.c
 --- main.c	12 Aug 2024 21:38:13 -0000	1.1.1.11
 +++ main.c	27 Jul 2025 18:20:57 -0000
 @@ -1245,7 +1245,7 @@ captured_main_1 (struct captured_main_ar
  	 If pid_or_core_arg's first character is a digit, try attach
  	 first and then corefile.  Otherwise try just corefile.  */

 -      if (isdigit (pid_or_core_arg[0]))
 +      if (isdigit ((unsigned char)pid_or_core_arg[0]))
  	{
  	  ret = catch_command_errors (attach_command, pid_or_core_arg,
  				      !batch_flag);
 Index: maint.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/maint.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 maint.c
 --- maint.c	12 Aug 2024 21:38:13 -0000	1.1.1.11
 +++ maint.c	27 Jul 2025 18:20:57 -0000
 @@ -554,9 +554,9 @@ maintenance_translate_address (const cha
    sect = NULL;
    p = arg;

 -  if (!isdigit (*p))
 +  if (!isdigit ((unsigned char)*p))
      {				/* See if we have a valid section name.  */
 -      while (*p && !isspace (*p))	/* Find end of section name.  */
 +      while (*p && !isspace ((unsigned char)*p))	/* Find end of section name.  */
  	p++;
        if (*p == '\000')		/* End of command?  */
  	error (_("Need to specify section name and address"));
 Index: netbsd-nat.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/netbsd-nat.c,v
 retrieving revision 1.5
 diff -u -p -u -r1.5 netbsd-nat.c
 --- netbsd-nat.c	15 Dec 2024 16:04:06 -0000	1.5
 +++ netbsd-nat.c	27 Jul 2025 18:20:57 -0000
 @@ -317,7 +317,7 @@ nbsd_nat_target::info_proc (const char *
        if (pid == 0)
  	error (_("No current process: you must name one."));
      }
 -  else if (built_argv.count () == 1 && isdigit (built_argv[0][0]))
 +  else if (built_argv.count () == 1 && isdigit ((unsigned char)built_argv[0][0]))
      pid = strtol (built_argv[0], NULL, 10);
    else
      error (_("Invalid arguments."));
 Index: objc-lang.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/objc-lang.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 objc-lang.c
 --- objc-lang.c	12 Aug 2024 21:37:57 -0000	1.1.1.11
 +++ objc-lang.c	27 Jul 2025 18:20:57 -0000
 @@ -841,9 +841,9 @@ parse_selector (char *method, char **sel

    for (;;)
      {
 -      if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':'))
 +      if (isalnum ((unsigned char)*s2) || (*s2 == '_') || (*s2 == ':'))
  	*s1++ = *s2;
 -      else if (isspace (*s2))
 +      else if (isspace ((unsigned char)*s2))
  	;
        else if ((*s2 == '\0') || (*s2 == '\''))
  	break;
 @@ -905,7 +905,7 @@ parse_method (char *method, char *type, 
    s1++;

    nclass = s1;
 -  while (isalnum (*s1) || (*s1 == '_'))
 +  while (isalnum ((unsigned char)*s1) || (*s1 == '_'))
      s1++;

    s2 = s1;
 @@ -916,7 +916,7 @@ parse_method (char *method, char *type, 
        s2++;
        s2 = skip_spaces (s2);
        ncategory = s2;
 -      while (isalnum (*s2) || (*s2 == '_'))
 +      while (isalnum ((unsigned char)*s2) || (*s2 == '_'))
  	s2++;
        *s2++ = '\0';
      }
 @@ -929,9 +929,9 @@ parse_method (char *method, char *type, 

    for (;;)
      {
 -      if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':'))
 +      if (isalnum ((unsigned char)*s2) || (*s2 == '_') || (*s2 == ':'))
  	*s1++ = *s2;
 -      else if (isspace (*s2))
 +      else if (isspace ((unsigned char)*s2))
  	;
        else if (*s2 == ']')
  	break;
 Index: p-typeprint.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/p-typeprint.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 p-typeprint.c
 --- p-typeprint.c	12 Aug 2024 21:38:14 -0000	1.1.1.11
 +++ p-typeprint.c	27 Jul 2025 18:20:57 -0000
 @@ -139,13 +139,13 @@ pascal_language::type_print_method_args 
      {
        gdb_puts (" (", stream);
        /* We must demangle this.  */
 -      while (isdigit (physname[0]))
 +      while (isdigit ((unsigned char)physname[0]))
  	{
  	  int len = 0;
  	  int i, j;
  	  char *argname;

 -	  while (isdigit (physname[len]))
 +	  while (isdigit ((unsigned char)physname[len]))
  	    {
  	      len++;
  	    }
 Index: ppc-linux-tdep.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/ppc-linux-tdep.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 ppc-linux-tdep.c
 --- ppc-linux-tdep.c	12 Aug 2024 21:37:53 -0000	1.1.1.11
 +++ ppc-linux-tdep.c	27 Jul 2025 18:20:57 -0000
 @@ -1696,10 +1696,10 @@ static int
  ppc_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
  {
    return (*s == 'i' /* Literal number.  */
 -	  || (isdigit (*s) && s[1] == '('
 -	      && isdigit (s[2])) /* Displacement.  */
 -	  || (*s == '(' && isdigit (s[1])) /* Register indirection.  */
 -	  || isdigit (*s)); /* Register value.  */
 +	  || (isdigit ((unsigned char)*s) && s[1] == '('
 +	      && isdigit ((unsigned char)s[2])) /* Displacement.  */
 +	  || (*s == '(' && isdigit ((unsigned char)s[1])) /* Register indirection.  */
 +	  || isdigit ((unsigned char)*s)); /* Register value.  */
  }

  /* Implementation of `gdbarch_stap_parse_special_token', as defined in
 @@ -1709,7 +1709,7 @@ static expr::operation_up
  ppc_stap_parse_special_token (struct gdbarch *gdbarch,
  			      struct stap_parse_info *p)
  {
 -  if (isdigit (*p->arg))
 +  if (isdigit ((unsigned char)*p->arg))
      {
        /* This temporary pointer is needed because we have to do a lookahead.
  	  We could be dealing with a register displacement, and in such case
 @@ -1718,7 +1718,7 @@ ppc_stap_parse_special_token (struct gdb
        char *regname;
        int len;

 -      while (isdigit (*s))
 +      while (isdigit ((unsigned char)*s))
  	++s;

        if (*s == '(')
 Index: probe.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/probe.c,v
 retrieving revision 1.1.1.10
 diff -u -p -u -r1.1.1.10 probe.c
 --- probe.c	12 Aug 2024 21:37:57 -0000	1.1.1.10
 +++ probe.c	27 Jul 2025 18:20:57 -0000
 @@ -826,7 +826,7 @@ probe_is_linespec_by_keyword (const char
        const char *keyword = *csp;
        size_t len = strlen (keyword);

 -      if (strncmp (s, keyword, len) == 0 && isspace (s[len]))
 +      if (strncmp (s, keyword, len) == 0 && isspace ((unsigned char)s[len]))
  	{
  	  *linespecp += len + 1;
  	  return 1;
 Index: procfs.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/procfs.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 procfs.c
 --- procfs.c	12 Aug 2024 21:38:00 -0000	1.1.1.11
 +++ procfs.c	27 Jul 2025 18:20:57 -0000
 @@ -3299,7 +3299,7 @@ procfs_target::info_proc (const char *ar
    gdb_argv built_argv (args);
    for (char *arg : built_argv)
      {
 -      if (isdigit (arg[0]))
 +      if (isdigit ((unsigned char)arg[0]))
  	{
  	  pid = strtoul (arg, &tmp, 10);
  	  if (*tmp == '/')
 @@ -3410,7 +3410,7 @@ proc_trace_syscalls (const char *args, i
      error_no_arg (_("system call to trace"));

    pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
 -  if (isdigit (args[0]))
 +  if (isdigit ((unsigned char)args[0]))
      {
        const int syscallnum = atoi (args);

 Index: producer.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/producer.c,v
 retrieving revision 1.1.1.4
 diff -u -p -u -r1.1.1.4 producer.c
 --- producer.c	12 Aug 2024 21:37:52 -0000	1.1.1.4
 +++ producer.c	27 Jul 2025 18:20:57 -0000
 @@ -66,9 +66,9 @@ producer_is_gcc (const char *producer, i
  	 "GNU Fortran 4.8.2 20140120 (Red Hat 4.8.2-16) -mtune=generic ..."
  	 "GNU C++14 5.0.0 20150123 (experimental)"
        */
 -      while (*cs && !isspace (*cs))
 +      while (*cs && !isspace ((unsigned char)*cs))
  	cs++;
 -      if (*cs && isspace (*cs))
 +      if (*cs && isspace ((unsigned char)*cs))
  	cs++;
        if (sscanf (cs, "%d.%d", major, minor) == 2)
  	return 1;
 Index: record.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/record.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 record.c
 --- record.c	12 Aug 2024 21:37:54 -0000	1.1.1.11
 +++ record.c	27 Jul 2025 18:20:57 -0000
 @@ -423,7 +423,7 @@ get_insn_number (const char **arg)
    begin = *arg;
    pos = skip_spaces (begin);

 -  if (!isdigit (*pos))
 +  if (!isdigit ((unsigned char)*pos))
      error (_("Expected positive number, got: %s."), pos);

    number = strtoulst (pos, &end, 10);
 @@ -443,7 +443,7 @@ get_context_size (const char **arg)

    pos = skip_spaces (*arg);

 -  if (!isdigit (*pos))
 +  if (!isdigit ((unsigned char)*pos))
      error (_("Expected positive number, got: %s."), pos);

    long result = strtol (pos, &end, 10);
 @@ -483,7 +483,7 @@ get_insn_history_modifiers (const char *

        for (; *args; ++args)
  	{
 -	  if (isspace (*args))
 +	  if (isspace ((unsigned char)*args))
  	    break;

  	  if (*args == '/')
 @@ -624,7 +624,7 @@ get_call_history_modifiers (const char *

        for (; *args; ++args)
  	{
 -	  if (isspace (*args))
 +	  if (isspace ((unsigned char)*args))
  	    break;

  	  if (*args == '/')
 Index: remote.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/remote.c,v
 retrieving revision 1.11
 diff -u -p -u -r1.11 remote.c
 --- remote.c	12 Aug 2024 22:09:30 -0000	1.11
 +++ remote.c	27 Jul 2025 18:20:57 -0000
 @@ -2510,7 +2510,7 @@ packet_check_result (const char *buf, bo
        /* The stub recognized the packet request.  Check that the
  	 operation succeeded.  */
        if (buf[0] == 'E'
 -	  && isxdigit (buf[1]) && isxdigit (buf[2])
 +	  && isxdigit ((unsigned char)buf[1]) && isxdigit ((unsigned char)buf[2])
  	  && buf[3] == '\0')
  	/* "Enn"  - definitely an error.  */
  	return packet_result::make_numeric_error (buf + 1);
 @@ -11826,7 +11826,7 @@ remote_target::xfer_partial (enum target
    while (annex[i] && (i < (get_remote_packet_size () - 8)))
      {
        /* Bad caller may have sent forbidden characters.  */
 -      gdb_assert (isprint (annex[i]) && annex[i] != '$' && annex[i] != '#');
 +      gdb_assert (isprint ((unsigned char)annex[i]) && annex[i] != '$' && annex[i] != '#');
        *p2++ = annex[i];
        i++;
      }
 @@ -12073,7 +12073,7 @@ private:
      for (int i = 0; i < buf.size (); ++i)
        {
  	gdb_byte c = buf[i];
 -	if (isprint (c))
 +	if (isprint ((unsigned char)c))
  	  gdb_putc (c, &stb);
  	else
  	  gdb_printf (&stb, "\\x%02x", (unsigned char) c);
 Index: rust-lang.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/rust-lang.c,v
 retrieving revision 1.1.1.6
 diff -u -p -u -r1.1.1.6 rust-lang.c
 --- rust-lang.c	12 Aug 2024 21:38:01 -0000	1.1.1.6
 +++ rust-lang.c	27 Jul 2025 18:20:57 -0000
 @@ -1777,7 +1777,7 @@ rust_language::emitchar (int ch, struct 
      gdb_puts ("\\t", stream);
    else if (ch == '\0')
      gdb_puts ("\\0", stream);
 -  else if (ch >= 32 && ch <= 127 && isprint (ch))
 +  else if (ch >= 32 && ch <= 127 && isprint ((unsigned char)ch))
      gdb_putc (ch, stream);
    else if (ch <= 255)
      gdb_printf (stream, "\\x%02x", ch);
 Index: s12z-tdep.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/s12z-tdep.c,v
 retrieving revision 1.1.1.4
 diff -u -p -u -r1.1.1.4 s12z-tdep.c
 --- s12z-tdep.c	12 Aug 2024 21:38:02 -0000	1.1.1.4
 +++ s12z-tdep.c	27 Jul 2025 18:20:57 -0000
 @@ -515,7 +515,7 @@ s12z_print_ccw_info (struct gdbarch *gdb
  	    gdb_putc (ccw_bits[b], file);
  	}
        else
 -	gdb_putc (tolower (ccw_bits[b]), file);
 +	gdb_putc (tolower ((unsignec char)ccw_bits[b]), file);
      }
    gdb_putc ('\n', file);
  }
 Index: serial.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/serial.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 serial.c
 --- serial.c	12 Aug 2024 21:38:12 -0000	1.1.1.11
 +++ serial.c	27 Jul 2025 18:20:57 -0000
 @@ -116,7 +116,7 @@ serial_logchar (struct ui_file *stream, 
  	    break;
  	  default:
  	    gdb_printf (stream,
 -			isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF);
 +			isprint ((unsigned char)ch) ? "%c" : "\\x%02x", ch & 0xFF);
  	    break;
  	  }
      }
 Index: solib-rocm.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/solib-rocm.c,v
 retrieving revision 1.1.1.1
 diff -u -p -u -r1.1.1.1 solib-rocm.c
 --- solib-rocm.c	12 Aug 2024 21:38:03 -0000	1.1.1.1
 +++ solib-rocm.c	27 Jul 2025 18:20:57 -0000
 @@ -458,8 +458,8 @@ rocm_bfd_iovec_open (bfd *abfd, inferior
    for (size_t i = 0; i < path.length (); ++i)
      if (path[i] == '%'
  	&& i < path.length () - 2
 -	&& std::isxdigit (path[i + 1])
 -	&& std::isxdigit (path[i + 2]))
 +	&& std::isxdigit ((unsigned char)path[i + 1])
 +	&& std::isxdigit ((unsigned char)path[i + 2]))
        {
  	std::string_view hex_digits = path.substr (i + 1, 2);
  	decoded_path += std::stoi (std::string (hex_digits), 0, 16);
 Index: stabsread.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/stabsread.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 stabsread.c
 --- stabsread.c	12 Aug 2024 21:38:04 -0000	1.1.1.11
 +++ stabsread.c	27 Jul 2025 18:20:57 -0000
 @@ -580,7 +580,7 @@ process_reference (const char **string)
    p = *string + 1;

    /* Read number as reference id.  */
 -  while (*p && isdigit (*p))
 +  while (*p && isdigit ((unsigned char)*p))
      {
        refnum = refnum * 10 + *p - '0';
        p++;
 @@ -764,7 +764,7 @@ define_symbol (CORE_ADDR valu, const cha
       deftypes we know how to handle is a local.  */
    if (!strchr ("cfFGpPrStTvVXCR", *p))
  #else
 -  if (isdigit (*p) || *p == '(' || *p == '-')
 +  if (isdigit ((unsigned char)*p) || *p == '(' || *p == '-')
  #endif
      deftype = 'l';
    else
 @@ -1853,7 +1853,7 @@ again:
        break;

      case '@':
 -      if (isdigit (**pp) || **pp == '(' || **pp == '-')
 +      if (isdigit ((unsigned char)**pp) || **pp == '(' || **pp == '-')
  	{			/* Member (class & variable) type */
  	  /* FIXME -- we should be doing smash_to_XXX types here.  */

 Index: stack.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/stack.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 stack.c
 --- stack.c	12 Aug 2024 21:38:09 -0000	1.1.1.11
 +++ stack.c	27 Jul 2025 18:20:58 -0000
 @@ -3059,7 +3059,7 @@ frame_apply_level_cmd_completer (struct 

    /* Check if we're past a valid LEVEL already.  */
    if (levels.finished ()
 -      && cmd > text && !isspace (cmd[-1]))
 +      && cmd > text && !isspace ((unsigned char)cmd[-1]))
      return;

    /* We're past LEVELs, advance word point.  */
 @@ -3093,7 +3093,7 @@ frame_apply_cmd_completer (struct cmd_li
      return;

    /* Check if we're past a valid COUNT already.  */
 -  if (cmd > text && !isspace (cmd[-1]))
 +  if (cmd > text && !isspace ((unsigned char)cmd[-1]))
      return;

    /* We're past COUNT, advance word point.  */
 Index: stap-probe.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/stap-probe.c,v
 retrieving revision 1.1.1.10
 diff -u -p -u -r1.1.1.10 stap-probe.c
 --- stap-probe.c	12 Aug 2024 21:37:55 -0000	1.1.1.10
 +++ stap-probe.c	27 Jul 2025 18:20:58 -0000
 @@ -577,14 +577,14 @@ stap_is_integer_prefix (struct gdbarch *
        if (r != NULL)
  	*r = "";

 -      return isdigit (*s) > 0;
 +      return isdigit ((unsigned char)*s) > 0;
      }

    for (p = t; *p != NULL; ++p)
      {
        size_t len = strlen (*p);

 -      if ((len == 0 && isdigit (*s))
 +      if ((len == 0 && isdigit ((unsigned char)*s))
  	  || (len > 0 && strncasecmp (s, *p, len) == 0))
  	{
  	  /* Integers may or may not have a prefix.  The "len == 0"
 @@ -734,7 +734,7 @@ stap_parse_register_operand (struct stap

    struct type *long_type = builtin_type (gdbarch)->builtin_long;
    operation_up disp_op;
 -  if (isdigit (*p->arg))
 +  if (isdigit ((unsigned char)*p->arg))
      {
        /* The value of the displacement.  */
        long displacement;
 @@ -769,14 +769,14 @@ stap_parse_register_operand (struct stap
    start = p->arg;

    /* We assume the register name is composed by letters and numbers.  */
 -  while (isalnum (*p->arg))
 +  while (isalnum ((unsigned char)*p->arg))
      ++p->arg;

    std::string regname (start, p->arg - start);

    /* We only add the GDB's register prefix/suffix if we are dealing with
       a numeric register.  */
 -  if (isdigit (*start))
 +  if (isdigit ((unsigned char)*start))
      {
        if (gdb_reg_prefix != NULL)
  	regname = gdb_reg_prefix + regname;
 @@ -923,7 +923,7 @@ stap_parse_single_operand (struct stap_p
        if (p->inside_paren_p)
  	tmp = skip_spaces (tmp);

 -      while (isdigit (*tmp))
 +      while (isdigit ((unsigned char)*tmp))
  	{
  	  /* We skip the digit here because we are only interested in
  	     knowing what kind of unary operation this is.  The digit
 @@ -961,7 +961,7 @@ stap_parse_single_operand (struct stap_p
  		      (std::move (result)));
  	}
      }
 -  else if (isdigit (*p->arg))
 +  else if (isdigit ((unsigned char)*p->arg))
      {
        /* A temporary variable, needed for lookahead.  */
        const char *tmp = p->arg;
 @@ -1044,7 +1044,7 @@ stap_parse_argument_conditionally (struc

    expr::operation_up result;
    if (*p->arg == '-' || *p->arg == '~' || *p->arg == '+' || *p->arg == '!'
 -      || isdigit (*p->arg)
 +      || isdigit ((unsigned char)*p->arg)
        || gdbarch_stap_is_single_operand (p->gdbarch, p->arg))
      result = stap_parse_single_operand (p);
    else if (*p->arg == '(')
 @@ -1113,7 +1113,7 @@ stap_parse_argument_1 (struct stap_parse
       This loop shall continue until we run out of characters in the input,
       or until we find a close-parenthesis, which means that we've reached
       the end of a sub-expression.  */
 -  while (*p->arg != '\0' && *p->arg != ')' && !isspace (*p->arg))
 +  while (*p->arg != '\0' && *p->arg != ')' && !isspace ((unsigned char)*p->arg))
      {
        const char *tmp_exp_buf;
        enum exp_opcode opcode;
 @@ -1272,8 +1272,8 @@ stap_probe::parse_arguments (struct gdba
  	 Where `N' can be [+,-][1,2,4,8].  This is not mandatory, so
  	 we check it here.  If we don't find it, go to the next
  	 state.  */
 -      if ((cur[0] == '-' && isdigit (cur[1]) && cur[2] == '@')
 -	  || (isdigit (cur[0]) && cur[1] == '@'))
 +      if ((cur[0] == '-' && isdigit ((unsigned char)cur[1]) && cur[2] == '@')
 +	  || (isdigit ((unsigned char)cur[0]) && cur[1] == '@'))
  	{
  	  if (*cur == '-')
  	    {
 Index: symfile.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/symfile.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 symfile.c
 --- symfile.c	12 Aug 2024 21:38:09 -0000	1.1.1.11
 +++ symfile.c	27 Jul 2025 18:20:58 -0000
 @@ -2736,7 +2736,7 @@ set_ext_lang_command (const char *args,
      error (_("'%s': Filename extension must begin with '.'"), ext_args.c_str ());

    /* Find end of first arg.  */
 -  while (*end != '\0' && !isspace (*end))
 +  while (*end != '\0' && !isspace ((unsigned char)*end))
      end++;

    if (*end == '\0')
 Index: symtab.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/symtab.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 symtab.c
 --- symtab.c	12 Aug 2024 21:38:15 -0000	1.1.1.11
 +++ symtab.c	27 Jul 2025 18:20:58 -0000
 @@ -4302,7 +4302,7 @@ operator_chars (const char *p, const cha

    /* Don't get faked out by `operator' being part of a longer
       identifier.  */
 -  if (isalpha (*p) || *p == '_' || *p == '$' || *p == '\0')
 +  if (isalpha ((unsigned char)*p) || *p == '_' || *p == '$' || *p == '\0')
      return *end;

    /* Allow some whitespace between `operator' and the operator symbol.  */
 @@ -4311,11 +4311,11 @@ operator_chars (const char *p, const cha

    /* Recognize 'operator TYPENAME'.  */

 -  if (isalpha (*p) || *p == '_' || *p == '$')
 +  if (isalpha ((unsigned char)*p) || *p == '_' || *p == '$')
      {
        const char *q = p + 1;

 -      while (isalnum (*q) || *q == '_' || *q == '$')
 +      while (isalnum ((unsigned char)*q) || *q == '_' || *q == '$')
  	q++;
        *end = q;
        return p;
 @@ -5087,7 +5087,7 @@ global_symbol_searcher::search () const
  	  int fix = -1;		/* -1 means ok; otherwise number of
  				    spaces needed.  */

 -	  if (isalpha (*opname) || *opname == '_' || *opname == '$')
 +	  if (isalpha ((unsigned char)*opname) || *opname == '_' || *opname == '$')
  	    {
  	      /* There should 1 space between 'operator' and 'TYPENAME'.  */
  	      if (opname[-1] != ' ' || opname[-2] == ' ')
 @@ -5576,7 +5576,7 @@ rbreak_command (const char *regexp, int 
  	  local_name = (char *) alloca (colon_index + 1);
  	  memcpy (local_name, regexp, colon_index);
  	  local_name[colon_index--] = 0;
 -	  while (isspace (local_name[colon_index]))
 +	  while (isspace ((unsigned char)local_name[colon_index]))
  	    local_name[colon_index--] = 0;
  	  file_name = local_name;
  	  regexp = skip_spaces (colon + 1);
 @@ -5794,7 +5794,7 @@ language_search_unquoted_string (const c
  {
    for (; p > text; --p)
      {
 -      if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0')
 +      if (isalnum ((unsigned char)p[-1]) || p[-1] == '_' || p[-1] == '\0')
  	continue;
        else
  	{
 @@ -5814,7 +5814,7 @@ language_search_unquoted_string (const c
  		     Unfortunately we have to find it now to decide.  */

  		  while (t > text)
 -		    if (isalnum (t[-1]) || t[-1] == '_' ||
 +		    if (isalnum ((unsigned char)t[-1]) || t[-1] == '_' ||
  			t[-1] == ' '    || t[-1] == ':' ||
  			t[-1] == '('    || t[-1] == ')')
  		      --t;
 @@ -6022,7 +6022,7 @@ default_collect_symbol_completion_matche
  	     which are in symbols.  */
  	  while (p > text)
  	    {
 -	      if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0'
 +	      if (isalnum ((unsigned char)p[-1]) || p[-1] == '_' || p[-1] == '\0'
  		  || p[-1] == ':' || strchr (break_on, p[-1]) != NULL)
  		--p;
  	      else
 Index: thread.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/thread.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 thread.c
 --- thread.c	12 Aug 2024 21:38:11 -0000	1.1.1.11
 +++ thread.c	27 Jul 2025 18:20:58 -0000
 @@ -1774,7 +1774,7 @@ thread_apply_command_completer (cmd_list

    /* Check if we're past a valid thread ID list already.  */
    if (parser.finished ()
 -      && cmd > text && !isspace (cmd[-1]))
 +      && cmd > text && !isspace ((unsigned char)cmd[-1]))
      return;

    /* We're past the thread ID list, advance word point.  */
 @@ -1837,7 +1837,7 @@ thread_apply_command (const char *tidlis
    if (*cmd == '\0')
      error (_("Please specify a command following the thread ID list"));

 -  if (tidlist == cmd || isdigit (cmd[0]))
 +  if (tidlist == cmd || isdigit ((unsigned char)cmd[0]))
      invalid_thread_id_error (cmd);

    scoped_restore_current_thread restore_thread;
 Index: tid-parse.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/tid-parse.c,v
 retrieving revision 1.1.1.6
 diff -u -p -u -r1.1.1.6 tid-parse.c
 --- tid-parse.c	12 Aug 2024 21:38:09 -0000	1.1.1.6
 +++ tid-parse.c	27 Jul 2025 18:20:58 -0000
 @@ -142,7 +142,7 @@ tid_range_parser::finished () const
  	 or we are not in a range and not in front of an integer, negative
  	 integer, convenience var or negative convenience var.  */
        return (*m_cur_tok == '\0'
 -	      || !(isdigit (*m_cur_tok)
 +	      || !(isdigit ((unsigned char)*m_cur_tok)
  		   || *m_cur_tok == '$'
  		   || *m_cur_tok == '*'));
      case STATE_THREAD_RANGE:
 @@ -219,7 +219,7 @@ tid_range_parser::get_tid_or_range (int 
  	  m_qualified = true;
  	  p = dot + 1;

 -	  if (isspace (*p))
 +	  if (isspace ((unsigned char)*p))
  	    return false;
  	}
        else
 @@ -230,7 +230,7 @@ tid_range_parser::get_tid_or_range (int 
  	}

        m_range_parser.init (p);
 -      if (p[0] == '*' && (p[1] == '\0' || isspace (p[1])))
 +      if (p[0] == '*' && (p[1] == '\0' || isspace ((unsigned char)p[1])))
  	{
  	  /* Setup the number range parser to return numbers in the
  	     whole [1,INT_MAX] range.  */
 Index: tracepoint.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/tracepoint.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 tracepoint.c
 --- tracepoint.c	12 Aug 2024 21:37:56 -0000	1.1.1.11
 +++ tracepoint.c	27 Jul 2025 18:20:58 -0000
 @@ -308,12 +308,12 @@ validate_trace_state_variable_name (cons

    /* All digits in the name is reserved for value history
       references.  */
 -  for (p = name; isdigit (*p); p++)
 +  for (p = name; isdigit ((unsigned char)*p); p++)
      ;
    if (*p == '\0')
      error (_("$%s is not a valid trace state variable name"), name);

 -  for (p = name; isalnum (*p) || *p == '_'; p++)
 +  for (p = name; isalnum ((unsigned char)*p) || *p == '_'; p++)
      ;
    if (*p != '\0')
      error (_("$%s is not a valid trace state variable name"), name);
 @@ -339,7 +339,7 @@ trace_variable_command (const char *args
      error (_("Name of trace variable should start with '$'"));

    name_start = p;
 -  while (isalnum (*p) || *p == '_')
 +  while (isalnum ((unsigned char)*p) || *p == '_')
      p++;
    std::string name (name_start, p - name_start);

 Index: typeprint.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/typeprint.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 typeprint.c
 --- typeprint.c	12 Aug 2024 21:38:07 -0000	1.1.1.11
 +++ typeprint.c	27 Jul 2025 18:20:58 -0000
 @@ -450,7 +450,7 @@ whatis_exp (const char *exp, int show)
  	{
  	  int seen_one = 0;

 -	  for (++exp; *exp && !isspace (*exp); ++exp)
 +	  for (++exp; *exp && !isspace ((unsigned char)*exp); ++exp)
  	    {
  	      switch (*exp)
  		{
 @@ -496,7 +496,7 @@ whatis_exp (const char *exp, int show)

  	  if (!*exp && !seen_one)
  	    error (_("flag expected"));
 -	  if (!isspace (*exp))
 +	  if (!isspace ((unsigned char)*exp))
  	    error (_("expected space after format"));
  	  exp = skip_spaces (exp);
  	}
 Index: value.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/value.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 value.c
 --- value.c	12 Aug 2024 21:38:06 -0000	1.1.1.11
 +++ value.c	27 Jul 2025 18:20:58 -0000
 @@ -3659,11 +3659,11 @@ value_from_history_ref (const char *h, c
      len = 2;

    /* Find length of numeral string.  */
 -  for (; isdigit (h[len]); len++)
 +  for (; isdigit ((unsigned char)h[len]); len++)
      ;

    /* Make sure numeral string is not part of an identifier.  */
 -  if (h[len] == '_' || isalpha (h[len]))
 +  if (h[len] == '_' || isalpha ((unsigned char)h[len]))
      return NULL;

    /* Now collect the index value.  */
 Index: windows-nat.c
 ===================================================================
 RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/windows-nat.c,v
 retrieving revision 1.1.1.11
 diff -u -p -u -r1.1.1.11 windows-nat.c
 --- windows-nat.c	12 Aug 2024 21:37:57 -0000	1.1.1.11
 +++ windows-nat.c	27 Jul 2025 18:20:58 -0000
 @@ -2541,7 +2541,7 @@ redir_set_redirection (const char *s, in
    /* cmd.exe recognizes "&N" only immediately after the redirection symbol.  */
    if (*s != '&')
      {
 -      while (isspace (*s))  /* skip whitespace before file name */
 +      while (isspace ((unsigned char)*s))  /* skip whitespace before file name */
  	s++;
        *d++ = ' ';	    /* separate file name with a single space */
      }
 @@ -2568,7 +2568,7 @@ redir_set_redirection (const char *s, in
  	    s++;
  	  *d++ = *s++;
  	}
 -      else if (isspace (*s) && !quote)
 +      else if (isspace ((unsigned char)*s) && !quote)
  	break;
        else
  	*d++ = *s++;
 @@ -2604,7 +2604,7 @@ redirect_inferior_handles (const char *c
    int quote = 0;
    bool retval = false;

 -  while (isspace (*s))
 +  while (isspace ((unsigned char)*s))
      *d++ = *s++;

    while (*s)

 --Apple-Mail=_145FE431-B621-4842-9035-ABBBDB7599B6
 Content-Transfer-Encoding: quoted-printable
 Content-Type: text/plain;
 	charset=utf-8





 > On Jul 27, 2025, at 9:31=E2=80=AFAM, Taylor R Campbell =
 <riastradh@NetBSD.org> wrote:
 >=20
 >> Date: Sat, 26 Jul 2025 10:06:15 -0400
 >> From: Christos Zoulas <christos@zoulas.com>
 >>=20
 >>> We should just patch gdb locally and file an upstream bug, basic =
 case
 >>> of clear undefined behaviour that is triggered in real-world use.
 >>> Christos's patch looks fine to me (but I did not check whether there
 >>> are any missing cases).
 >>=20
 >> There are a few more missing, I thought of changing all of the ctype
 >> macros to gdb_isfoo() instead of all the local casts.
 >=20
 > Let's let upstream decide how they want to tidy things up (there is
 > already a `safe-ctype.h' in binutils with uppercase macros instead,
 > restricted to char inputs that are never EOF, but I don't know whether
 > it's appropriate here).
 >=20
 >>                                                      I think we =
 should
 >> let upstream fix it first.
 >=20
 > This is actively interfering with development and debugging on NetBSD,
 > so it is a high priority to work around while we wait for upstream.
 > We should just make sure that we're not applying this to any cases
 > that might legitimately have EOF in the domain.
 >=20
 > If upstream does it differently, no big deal, we can just replace our
 > local patch by their different patch later.


 --Apple-Mail=_145FE431-B621-4842-9035-ABBBDB7599B6--

 --Apple-Mail=_9F645710-321D-4E88-9A06-695AF34D42B9
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
 	filename=signature.asc
 Content-Type: application/pgp-signature;
 	name=signature.asc
 Content-Description: Message signed with OpenPGP

 -----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - http://gpgtools.org

 iF0EARECAB0WIQS+BJlbqPkO0MDBdsRxESqxbLM7OgUCaIZufwAKCRBxESqxbLM7
 OmceAKDkHPAzkNnwGotGg8rxqK8Dzxl6/QCcCWTvfX5cG0sYvYzsRR9IQUnBxcU=
 =68i4
 -----END PGP SIGNATURE-----

 --Apple-Mail=_9F645710-321D-4E88-9A06-695AF34D42B9--

From: Martin Husemann <martin@duskware.de>
To: Christos Zoulas <christos@zoulas.com>
Cc: Taylor R Campbell <riastradh@NetBSD.org>, gnats-bugs@netbsd.org,
	toolchain-manager@netbsd.org, gnats-admin@netbsd.org,
	netbsd-bugs@netbsd.org, Thomas Klausner <wiz@NetBSD.org>
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Sun, 27 Jul 2025 20:43:19 +0200

 On Sun, Jul 27, 2025 at 02:22:55PM -0400, Christos Zoulas wrote:
 > The full patch is 2K lines long (attached). I will apply it if someone else here says I should :-)

 LGTM, please commit it!

 Martin

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/59549 CVS commit: src/external/gpl3/gdb/dist/gdb
Date: Sun, 27 Jul 2025 16:40:24 -0400

 Module Name:	src
 Committed By:	christos
 Date:		Sun Jul 27 20:40:23 UTC 2025

 Modified Files:
 	src/external/gpl3/gdb/dist/gdb: aarch64-linux-tdep.c ada-lang.c
 	    ada-typeprint.c ada-valprint.c arm-linux-tdep.c auto-load.c
 	    break-catch-exec.c break-catch-fork.c break-catch-syscall.c
 	    break-catch-throw.c breakpoint.c btrace.c coff-pe-read.c coffread.c
 	    exec.c fbsd-nat.c findcmd.c gnu-nat.c gnu-v2-abi.c go-lang.c
 	    i386-tdep.c ia64-linux-tdep.c infcmd.c infrun.c linespec.c
 	    linux-fork.c linux-tdep.c location.c main.c maint.c netbsd-nat.c
 	    objc-lang.c p-typeprint.c ppc-linux-tdep.c probe.c procfs.c
 	    producer.c record.c remote.c rust-lang.c s12z-tdep.c serial.c
 	    solib-rocm.c stabsread.c stack.c stap-probe.c symfile.c symtab.c
 	    thread.c tid-parse.c tracepoint.c typeprint.c value.c windows-nat.c

 Log Message:
 PR/59549: Thomas Klausner: Cast ctype(3) macro arguments to unsigned char to
 avoid crashes for negative non -1 values.


 To generate a diff of this commit:
 cvs rdiff -u -r1.1.1.10 -r1.2 \
     src/external/gpl3/gdb/dist/gdb/aarch64-linux-tdep.c \
     src/external/gpl3/gdb/dist/gdb/auto-load.c \
     src/external/gpl3/gdb/dist/gdb/btrace.c \
     src/external/gpl3/gdb/dist/gdb/coff-pe-read.c \
     src/external/gpl3/gdb/dist/gdb/findcmd.c \
     src/external/gpl3/gdb/dist/gdb/gnu-nat.c \
     src/external/gpl3/gdb/dist/gdb/go-lang.c \
     src/external/gpl3/gdb/dist/gdb/ia64-linux-tdep.c \
     src/external/gpl3/gdb/dist/gdb/linux-fork.c \
     src/external/gpl3/gdb/dist/gdb/probe.c \
     src/external/gpl3/gdb/dist/gdb/stap-probe.c
 cvs rdiff -u -r1.9 -r1.10 src/external/gpl3/gdb/dist/gdb/ada-lang.c
 cvs rdiff -u -r1.1.1.11 -r1.2 src/external/gpl3/gdb/dist/gdb/ada-typeprint.c \
     src/external/gpl3/gdb/dist/gdb/ada-valprint.c \
     src/external/gpl3/gdb/dist/gdb/arm-linux-tdep.c \
     src/external/gpl3/gdb/dist/gdb/breakpoint.c \
     src/external/gpl3/gdb/dist/gdb/coffread.c \
     src/external/gpl3/gdb/dist/gdb/exec.c \
     src/external/gpl3/gdb/dist/gdb/fbsd-nat.c \
     src/external/gpl3/gdb/dist/gdb/gnu-v2-abi.c \
     src/external/gpl3/gdb/dist/gdb/i386-tdep.c \
     src/external/gpl3/gdb/dist/gdb/infcmd.c \
     src/external/gpl3/gdb/dist/gdb/linespec.c \
     src/external/gpl3/gdb/dist/gdb/linux-tdep.c \
     src/external/gpl3/gdb/dist/gdb/main.c \
     src/external/gpl3/gdb/dist/gdb/maint.c \
     src/external/gpl3/gdb/dist/gdb/objc-lang.c \
     src/external/gpl3/gdb/dist/gdb/p-typeprint.c \
     src/external/gpl3/gdb/dist/gdb/ppc-linux-tdep.c \
     src/external/gpl3/gdb/dist/gdb/procfs.c \
     src/external/gpl3/gdb/dist/gdb/record.c \
     src/external/gpl3/gdb/dist/gdb/serial.c \
     src/external/gpl3/gdb/dist/gdb/stabsread.c \
     src/external/gpl3/gdb/dist/gdb/stack.c \
     src/external/gpl3/gdb/dist/gdb/symfile.c \
     src/external/gpl3/gdb/dist/gdb/symtab.c \
     src/external/gpl3/gdb/dist/gdb/thread.c \
     src/external/gpl3/gdb/dist/gdb/tracepoint.c \
     src/external/gpl3/gdb/dist/gdb/typeprint.c \
     src/external/gpl3/gdb/dist/gdb/value.c \
     src/external/gpl3/gdb/dist/gdb/windows-nat.c
 cvs rdiff -u -r1.1.1.2 -r1.2 \
     src/external/gpl3/gdb/dist/gdb/break-catch-exec.c \
     src/external/gpl3/gdb/dist/gdb/break-catch-fork.c
 cvs rdiff -u -r1.1.1.7 -r1.2 \
     src/external/gpl3/gdb/dist/gdb/break-catch-syscall.c
 cvs rdiff -u -r1.1.1.9 -r1.2 \
     src/external/gpl3/gdb/dist/gdb/break-catch-throw.c
 cvs rdiff -u -r1.7 -r1.8 src/external/gpl3/gdb/dist/gdb/infrun.c
 cvs rdiff -u -r1.4 -r1.5 src/external/gpl3/gdb/dist/gdb/location.c
 cvs rdiff -u -r1.5 -r1.6 src/external/gpl3/gdb/dist/gdb/netbsd-nat.c
 cvs rdiff -u -r1.1.1.4 -r1.2 src/external/gpl3/gdb/dist/gdb/producer.c \
     src/external/gpl3/gdb/dist/gdb/s12z-tdep.c
 cvs rdiff -u -r1.11 -r1.12 src/external/gpl3/gdb/dist/gdb/remote.c
 cvs rdiff -u -r1.1.1.6 -r1.2 src/external/gpl3/gdb/dist/gdb/rust-lang.c \
     src/external/gpl3/gdb/dist/gdb/tid-parse.c
 cvs rdiff -u -r1.1.1.1 -r1.2 src/external/gpl3/gdb/dist/gdb/solib-rocm.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: Thomas Klausner <wiz@NetBSD.org>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: toolchain/59549: gdb is not ctype(3) safe
Date: Wed, 6 Aug 2025 15:37:27 +0200

 On Sun, Jul 27, 2025 at 01:35:01PM +0000, Taylor R Campbell via gnats wrote:
 > The following reply was made to PR toolchain/59549; it has been noted by GNATS.
 > 
 > From: Taylor R Campbell <riastradh@NetBSD.org>
 > To: Christos Zoulas <christos@zoulas.com>
 > Cc: gnats-bugs@netbsd.org, toolchain-manager@netbsd.org,
 > 	gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, Thomas Klausner <wiz@NetBSD.org>
 > Subject: Re: toolchain/59549: gdb is not ctype(3) safe
 > Date: Sun, 27 Jul 2025 13:31:22 +0000
 > 
 >  > Date: Sat, 26 Jul 2025 10:06:15 -0400
 >  > From: Christos Zoulas <christos@zoulas.com>
 >  > 
 >  > > We should just patch gdb locally and file an upstream bug, basic case
 >  > > of clear undefined behaviour that is triggered in real-world use.
 >  > > Christos's patch looks fine to me (but I did not check whether there
 >  > > are any missing cases).
 >  > 
 >  > There are a few more missing, I thought of changing all of the ctype
 >  > macros to gdb_isfoo() instead of all the local casts.
 >  
 >  Let's let upstream decide how they want to tidy things up (there is
 >  already a `safe-ctype.h' in binutils with uppercase macros instead,
 >  restricted to char inputs that are never EOF, but I don't know whether
 >  it's appropriate here).
 >  
 >  >                                                       I think we should
 >  > let upstream fix it first.
 >  
 >  This is actively interfering with development and debugging on NetBSD,
 >  so it is a high priority to work around while we wait for upstream.
 >  We should just make sure that we're not applying this to any cases
 >  that might legitimately have EOF in the domain.
 >  
 >  If upstream does it differently, no big deal, we can just replace our
 >  local patch by their different patch later.

 Tom Tromey has resolved this in upstream now:
 https://sourceware.org/pipermail/gdb-patches/2025-August/219746.html
 https://sourceware.org/pipermail/gdb-patches/2025-August/219747.html
 https://sourceware.org/pipermail/gdb-patches/2025-August/219748.html
 https://sourceware.org/pipermail/gdb-patches/2025-August/219749.html

  Thomas

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.47 2022/09/11 19:34:41 kim Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2025 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.