summaryrefslogtreecommitdiff
path: root/core/bash/bash53-019
blob: e70e5e99514be649ebf1e704634a1370b4f32a01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
			     BASH PATCH REPORT
			     =================

Bash-Release:	5.3
Patch-ID:	bash53-019

Bug-Reported-by:	zheng <charname@qq.com>
Bug-Reference-ID:	<tencent_19D6EE3366FEA3EF2C5FD6C23DF303156D09@qq.com>
Bug-Reference-URL:	https://lists.gnu.org/archive/html/bug-bash/2026-08/msg00010.html

Bug-Description:

On some systems, macOS in particular, isalpha(3) returns true for bytes
between 128 and 255. Bash uses this to determine whether or not these
characters are permitted to be part of a shell identifier, and can
consume one byte too many when determining the end of a variable name.

Patch (apply with `patch -p0'):

*** ../bash-5.3-patched/syntax.h	Mon Sep 14 10:20:05 2020
--- syntax.h	Thu Aug  6 14:11:25 2026
***************
*** 64,67 ****
--- 64,69 ----
  #define CSUBSTOP	0x1000	/* values of OP for ${word[:]OPstuff} */
  #define CBLANK		0x2000	/* whitespace (blank) character */
+ #define CNAME		0x4000	/* POSIX name character ([_0-9a-zA-Z]) */
+ #define CNAMESTART	0x8000	/* POSIX name start character ([_a-zA-Z]) */
  
  /* Defines for use by the rest of the shell. */
*** ../bash-5.3-patched/mksyntax.c	Thu May 16 15:35:55 2024
--- mksyntax.c	Wed Aug  5 15:27:45 2026
***************
*** 61,64 ****
--- 61,66 ----
  	{ CSUBSTOP,	"CSUBSTOP" },
  	{ CBLANK,	"CBLANK" },
+ 	{ CNAME,	"CNAME" },
+ 	{ CNAMESTART,	"CNAMESTART" }
  };
  	
***************
*** 199,202 ****
--- 201,243 ----
  }
  
+ static void
+ setnamechars(void)
+ {
+   lsyntax['_'] |= CNAME|CNAMESTART;
+ 
+   lsyntax['0'] |= CNAME; lsyntax['1'] |= CNAME; lsyntax['2'] |= CNAME;
+   lsyntax['3'] |= CNAME; lsyntax['4'] |= CNAME; lsyntax['5'] |= CNAME;
+   lsyntax['6'] |= CNAME; lsyntax['7'] |= CNAME; lsyntax['8'] |= CNAME;
+   lsyntax['9'] |= CNAME;
+ 
+   lsyntax['a'] |= CNAME|CNAMESTART; lsyntax['b'] |= CNAME|CNAMESTART;
+   lsyntax['c'] |= CNAME|CNAMESTART; lsyntax['d'] |= CNAME|CNAMESTART;
+   lsyntax['e'] |= CNAME|CNAMESTART; lsyntax['f'] |= CNAME|CNAMESTART;
+   lsyntax['g'] |= CNAME|CNAMESTART; lsyntax['h'] |= CNAME|CNAMESTART;
+   lsyntax['i'] |= CNAME|CNAMESTART; lsyntax['j'] |= CNAME|CNAMESTART;
+   lsyntax['k'] |= CNAME|CNAMESTART; lsyntax['l'] |= CNAME|CNAMESTART;
+   lsyntax['m'] |= CNAME|CNAMESTART; lsyntax['n'] |= CNAME|CNAMESTART;
+   lsyntax['o'] |= CNAME|CNAMESTART; lsyntax['p'] |= CNAME|CNAMESTART;
+   lsyntax['q'] |= CNAME|CNAMESTART; lsyntax['r'] |= CNAME|CNAMESTART;
+   lsyntax['s'] |= CNAME|CNAMESTART; lsyntax['t'] |= CNAME|CNAMESTART;
+   lsyntax['u'] |= CNAME|CNAMESTART; lsyntax['v'] |= CNAME|CNAMESTART;
+   lsyntax['w'] |= CNAME|CNAMESTART; lsyntax['x'] |= CNAME|CNAMESTART;
+   lsyntax['y'] |= CNAME|CNAMESTART; lsyntax['z'] |= CNAME|CNAMESTART;
+ 
+   lsyntax['A'] |= CNAME|CNAMESTART; lsyntax['B'] |= CNAME|CNAMESTART;
+   lsyntax['C'] |= CNAME|CNAMESTART; lsyntax['D'] |= CNAME|CNAMESTART;
+   lsyntax['E'] |= CNAME|CNAMESTART; lsyntax['F'] |= CNAME|CNAMESTART;
+   lsyntax['G'] |= CNAME|CNAMESTART; lsyntax['H'] |= CNAME|CNAMESTART;
+   lsyntax['I'] |= CNAME|CNAMESTART; lsyntax['J'] |= CNAME|CNAMESTART;
+   lsyntax['K'] |= CNAME|CNAMESTART; lsyntax['L'] |= CNAME|CNAMESTART;
+   lsyntax['M'] |= CNAME|CNAMESTART; lsyntax['N'] |= CNAME|CNAMESTART;
+   lsyntax['O'] |= CNAME|CNAMESTART; lsyntax['P'] |= CNAME|CNAMESTART;
+   lsyntax['Q'] |= CNAME|CNAMESTART; lsyntax['R'] |= CNAME|CNAMESTART;
+   lsyntax['S'] |= CNAME|CNAMESTART; lsyntax['T'] |= CNAME|CNAMESTART;
+   lsyntax['U'] |= CNAME|CNAMESTART; lsyntax['V'] |= CNAME|CNAMESTART;
+   lsyntax['W'] |= CNAME|CNAMESTART; lsyntax['X'] |= CNAME|CNAMESTART;
+   lsyntax['Y'] |= CNAME|CNAMESTART; lsyntax['Z'] |= CNAME|CNAMESTART;
+ }
+ 
  /* load up the correct flag values in lsyntax */
  static void
***************
*** 235,238 ****
--- 276,281 ----
  
    addblanks ();
+ 
+   setnamechars ();
  }
  
*** ../bash-5.3-patched/general.h	Tue Jul  7 11:13:48 2026
--- general.h	Thu Aug  6 14:07:22 2026
***************
*** 111,116 ****
  
  /* Define exactly what a legal shell identifier consists of. */
! #define legal_variable_starter(c) (ISALPHA(c) || (c == '_'))
! #define legal_variable_char(c)	(ISALNUM(c) || c == '_')
  
  /* Definitions used in subst.c and by the `read' builtin for field
--- 111,121 ----
  
  /* Define exactly what a legal shell identifier consists of. */
! #if 0
! #define legal_variable_starter(c) (c < 128 && (ISALPHA(c) || c == '_'))
! #define legal_variable_char(c)	(c < 128 && (ISALNUM(c) || c == '_'))
! #else
! #define legal_variable_starter(c) (sh_syntaxtab[c] & CNAMESTART)
! #define legal_variable_char(c)	(sh_syntaxtab[c] & CNAME)
! #endif
  
  /* Definitions used in subst.c and by the `read' builtin for field
*** ../bash-5.3/patchlevel.h	2020-06-22 14:51:03.000000000 -0400
--- patchlevel.h	2020-10-01 11:01:28.000000000 -0400
***************
*** 26,30 ****
     looks for to find the patch level (for the sccs version string). */
  
! #define PATCHLEVEL 18
  
  #endif /* _PATCHLEVEL_H_ */
--- 26,30 ----
     looks for to find the patch level (for the sccs version string). */
  
! #define PATCHLEVEL 19
  
  #endif /* _PATCHLEVEL_H_ */