Article View: gnu.bash.bug
Article #887FIX: Bash bombs on Meta-B on Cray
From: Arne Henrik Juul
Date: Thu, 10 Sep 1992 18:48
Date: Thu, 10 Sep 1992 18:48
246 lines
8567 bytes
8567 bytes
After some debugging, I have found the cause for the bug that was
posted here recently, which caused bash to fail on certain commands.
The problem is in the readline code: It uses a common field in its
keymap entry structure to refer to both a new keymap (for ESC
commands, Control-X commands etc.) and a function (for normal keys).
But this is *not* done as a union, because it then becomes difficult
(maybe impossible) to initalize in the way wanted, as the comment in
the keymaps.h file says:
typedef struct _keymap_entry {
char type;
Function *function;
} KEYMAP_ENTRY;
/* I wanted to make the above structure contain a union of:
union { Function *function; struct _keymap_entry *keymap; } value;
but this made it impossible for me to create a static array.
Maybe I need C lessons. */
The function field is also used as a Keymap variable (really a
(struct _keymap_entry *)) in various places, and it is initalized by
taking a KEYMAP_ENTRY_ARRAY and just casting it to (Function *).
When it is again used (in rl_dispatch) it is cast back to (Keymap).
On the Cray, this just does not work properly, and I'm not sure if it
is required to - casting between pointer to structure and pointer to
function and back is not very clean. The net effect is that the
pointer is divided by four, as far as I can see. This makes bash jump
off into never-never land, quite literally, by following a bogus
(Function *) pointer.
The easy workaround is just to add another field to the struct
_keymap_entry, like this:
typedef struct _keymap_entry {
char type;
Function *function;
struct _keymap_entry *map;
} KEYMAP_ENTRY;
This wastes some space (but who cares about 60KB on the Cray :-), but
it works. The real problem is to find all occurences of
(something).function and find out if it needs to be replaced with
-----------.map. I have done this some places, but I may have missed
some.
There may be a related problem with the macro stuff which *also* seems
to overload the same field, but I didn't worry about that for now - I
don't use macros in bash anyway :-)
At the end find enclosed my current diffs for this problem, use at own
risk, warranty void if used, totally untested etc.
Regards,
Arne H. Juul -- arnej@lise.unit.no -- University of Trondheim, Norway
diff -rc bash-1.12.dist/lib/readline/emacs_keymap.c bash-1.12.ok/lib/readline/emacs_keymap.c
*** bash-1.12.dist/lib/readline/emacs_keymap.c Tue Jul 9 13:10:28 1991
--- bash-1.12.ok/lib/readline/emacs_keymap.c Thu Sep 10 04:54:33 1992
***************
*** 56,65 ****
{ ISFUNC, rl_unix_line_discard }, /* Control-u */
{ ISFUNC, rl_quoted_insert }, /* Control-v */
{ ISFUNC, rl_unix_word_rubout }, /* Control-w */
! { ISKMAP, (Function *)emacs_ctlx_keymap }, /* Control-x */
{ ISFUNC, rl_yank }, /* Control-y */
{ ISFUNC, (Function *)0x0 }, /* Control-z */
! { ISKMAP, (Function *)emacs_meta_keymap }, /* Control-[ */
{ ISFUNC, (Function *)0x0 }, /* Control-\ */
{ ISFUNC, (Function *)0x0 }, /* Control-] */
{ ISFUNC, (Function *)0x0 }, /* Control-^ */
--- 56,65 ----
{ ISFUNC, rl_unix_line_discard }, /* Control-u */
{ ISFUNC, rl_quoted_insert }, /* Control-v */
{ ISFUNC, rl_unix_word_rubout }, /* Control-w */
! { ISKMAP, 0, emacs_ctlx_keymap }, /* Control-x */
{ ISFUNC, rl_yank }, /* Control-y */
{ ISFUNC, (Function *)0x0 }, /* Control-z */
! { ISKMAP, 0, emacs_meta_keymap }, /* Control-[ */
{ ISFUNC, (Function *)0x0 }, /* Control-\ */
{ ISFUNC, (Function *)0x0 }, /* Control-] */
{ ISFUNC, (Function *)0x0 }, /* Control-^ */
diff -rc bash-1.12.dist/lib/readline/keymaps.c bash-1.12.ok/lib/readline/keymaps.c
*** bash-1.12.dist/lib/readline/keymaps.c Sun Aug 4 18:54:07 1991
--- bash-1.12.ok/lib/readline/keymaps.c Thu Sep 10 04:55:20 1992
***************
*** 120,126 ****
break;
case ISKMAP:
! rl_discard_keymap ((Keymap)map[i].function);
break;
case ISMACR:
--- 120,126 ----
break;
case ISKMAP:
! rl_discard_keymap (map[i].map);
break;
case ISMACR:
diff -rc bash-1.12.dist/lib/readline/keymaps.h bash-1.12.ok/lib/readline/keymaps.h
*** bash-1.12.dist/lib/readline/keymaps.h Tue Jul 9 13:10:30 1991
--- bash-1.12.ok/lib/readline/keymaps.h Thu Sep 10 04:53:40 1992
***************
*** 18,23 ****
--- 18,24 ----
typedef struct _keymap_entry {
char type;
Function *function;
+ struct _keymap_entry *map;
} KEYMAP_ENTRY;
/* I wanted to make the above structure contain a union of:
diff -rc bash-1.12.dist/lib/readline/vi_keymap.c bash-1.12.ok/lib/readline/vi_keymap.c
*** bash-1.12.dist/lib/readline/vi_keymap.c Tue Jul 9 13:10:32 1991
--- bash-1.12.ok/lib/readline/vi_keymap.c Thu Sep 10 04:57:56 1992
***************
*** 59,65 ****
{ ISFUNC, rl_yank }, /* Control-y */
{ ISFUNC, (Function *)0x0 }, /* Control-z */
! { ISKMAP, (Function *)vi_escape_keymap }, /* Control-[ */
{ ISFUNC, (Function *)0x0 }, /* Control-\ */
{ ISFUNC, (Function *)0x0 }, /* Control-] */
{ ISFUNC, (Function *)0x0 }, /* Control-^ */
--- 59,65 ----
{ ISFUNC, rl_yank }, /* Control-y */
{ ISFUNC, (Function *)0x0 }, /* Control-z */
! { ISKMAP, 0, vi_escape_keymap }, /* Control-[ */
{ ISFUNC, (Function *)0x0 }, /* Control-\ */
{ ISFUNC, (Function *)0x0 }, /* Control-] */
{ ISFUNC, (Function *)0x0 }, /* Control-^ */
*** bash-1.12.dist/lib/readline/readline.c Sun Jan 26 19:31:11 1992
--- bash-1.12.ok/lib/readline/readline.c Thu Sep 10 21:31:08 1992
***************
*** 844,850 ****
{
if (map[ESC].type == ISKMAP)
{
! map = (Keymap)map[ESC].function;
key -= 128;
rl_dispatch (key, map);
}
--- 844,850 ----
{
if (map[ESC].type == ISKMAP)
{
! map = map[ESC].map;
key -= 128;
rl_dispatch (key, map);
}
***************
*** 885,897 ****
break;
case ISKMAP:
! if (map[key].function != (Function *)NULL)
{
int newkey;
rl_key_sequence_length++;
newkey = rl_read_key ();
! rl_dispatch (newkey, (Keymap)map[key].function);
}
else
{
--- 885,897 ----
break;
case ISKMAP:
! if (map[key].map != NULL)
{
int newkey;
rl_key_sequence_length++;
newkey = rl_read_key ();
! rl_dispatch (newkey, map[key].map);
}
else
{
***************
*** 5312,5318 ****
{
if (keymap[ESC].type == ISKMAP)
{
! Keymap escmap = (Keymap)keymap[ESC].function;
key -= 128;
escmap[key].type = ISFUNC;
--- 5312,5318 ----
{
if (keymap[ESC].type == ISKMAP)
{
! Keymap escmap = keymap[ESC].map;
key -= 128;
escmap[key].type = ISFUNC;
***************
*** 5435,5443 ****
free ((char *)map[i].function);
map[keys[i]].type = ISKMAP;
! map[keys[i]].function = (Function *)rl_make_bare_keymap ();
}
! map = (Keymap)map[keys[i]].function;
}
else
{
--- 5435,5443 ----
free ((char *)map[i].function);
map[keys[i]].type = ISKMAP;
! map[keys[i]].map = rl_make_bare_keymap ();
}
! map = map[keys[i]].map;
}
else
{
***************
*** 6131,6139 ****
/* Find the list of keyseqs in this map which have FUNCTION as
their target. Add the key sequences found to RESULT. */
! if (map[key].function)
seqs =
! invoking_keyseqs_in_map (function, (Keymap)map[key].function);
if (seqs)
{
--- 6131,6139 ----
/* Find the list of keyseqs in this map which have FUNCTION as
their target. Add the key sequences found to RESULT. */
! if (map[key].map)
seqs =
! invoking_keyseqs_in_map (function, map[key].map);
if (seqs)
{
Technical Details
Message-ID:
<1992Sep10.204806@kari.fm.unit.no>Path:
arc1-ca.pugleaf.net!sparky!uunet!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!kari.fm.unit.no!arnejShow Full Headers
Complete Article Headers
Newsgroups: gnu.bash.bug Path: arc1-ca.pugleaf.net!sparky!uunet!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!kari.fm.unit.no!arnej From: arnej@kari.fm.unit.no (Arne Henrik Juul) Subject: FIX: Bash bombs on Meta-B on Cray Message-ID: <1992Sep10.204806@kari.fm.unit.no> Followup-To: gnu.bash.bug Keywords: bash,cray,bug Sender: gnulists@ai.mit.edu Reply-To: arnej@lise.unit.no Organization: Norwegian Institute of Technology Distribution: gnu Date: Thu, 10 Sep 1992 18:48:06 GMT Approved: bug-bash@prep.ai.mit.edu Lines: 247