[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Bash 2.05 mishandles large array subscripts on 64-bit hosts
From: |
Paul Eggert |
Subject: |
Bash 2.05 mishandles large array subscripts on 64-bit hosts |
Date: |
Sun, 29 Apr 2001 16:57:36 -0700 (PDT) |
Configuration Information [Automatically generated, do not change]:
Machine: sparc
OS: solaris2.7
Compiler: cc -xarch=v9
Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='sparc'
-DCONF_OSTYPE='solaris2.7' -DCONF_MACHTYPE='sparc-sun-solaris2.7'
-DCONF_VENDOR='sun' -DSHELL -DHAVE_CONFIG_H -D_LARGEFILE_SOURCE
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -I. -I.. -I../include -I../lib
-I/tmp/prefix/include -g
uname output: SunOS sic.twinsun.com 5.7 Generic_106541-15 sun4u sparc
SUNW,UltraSPARC-IIi-Engine
Machine Type: sparc-sun-solaris2.7
Bash Version: 2.05
Patch Level: 0
Release Status: release
Description:
Bash 2.05 silently restricts array subscripts to be 'int', even
though it internally does arithmetic with 'long'. This causes
problems on hosts where 'long' is wider than 'int'. For example,
on 64-bit Solaris Bash silently treats 'a[4294967296]' as if it
were 'a[0]'.
Bash should allow any integer that it can compute to be an
array subscript.
Repeat-By:
$ a[0]=zero
$ a[2147483648]=foo
bash: a[2147483648]: bad array subscript
$ a[4294967296]=bar
$ echo "a[0]=${a[0]} a[2147483648]=${a[2147483648]}
a[4294967296]=${a[4294967296]}"
bash: a: bad array subscript
a[0]=bar a[2147483648]= a[4294967296]=bar
Here's what the behavior should look like instead:
$ a[0]=zero
$ a[2147483648]=foo
$ a[4294967296]=bar
$ echo "a[0]=${a[0]} a[2147483648]=${a[2147483648]}
a[4294967296]=${a[4294967296]}"
a[0]=zero a[2147483648]=foo a[4294967296]=bar
Fix:
2001-04-29 Paul Eggert <eggert@twinsun.com>
Remove arbitrary restrictions of Bash array indices to 'int';
now they can be any nonnegative 'long' value. The distinction
matters on hosts with 32-bit int and 64-bit long'.
* subst.h (array_expand_index): Return arrayind_t, not int.
* array.h (arrayind_t): Now 'long', not 'int'.
(array_subrange): Index args are now arrayind_t, not int.
* variables.h (bind_array_variable):
Pass index as arrayind_t, not as int.
* array.c (dup_array_subrange, array_subrange):
Array index values are now arrayind_t, not int.
(print_element): Print array indexes as long, not int.
* variables.c:
(null_array_assign, assign_dirstack, bind_array_variable):
Pass index as arrayind_t, not as int.
(assign_array_var_from_word_list, assign_array_var_from_string):
Use arrayind_t for array indices, not int.
* subst.c (pos_params, quoted_substring):
Now prototyped, since the caller's
args may be wider than the parameters on modern hosts.
(do_array_element_assignment, array_expand_index, array_value_internal,
array_length_reference, verify_substring_values):
Use arrayind_t for array indices, not int.
(array_expand_index): Return arrayind_t, not int.
(array_length_reference): Store char in char var, not in int or
arrayind_t var.
(verify_substring_values): Store values as long, not int.
(parameter_brace_substring): Likewise.
===================================================================
RCS file: array.h,v
retrieving revision 2.5
retrieving revision 2.5.0.1
diff -pu -r2.5 -r2.5.0.1
--- array.h 1999/08/05 11:01:14 2.5
+++ array.h 2001/04/29 23:39:20 2.5.0.1
@@ -24,7 +24,7 @@
#include "stdc.h"
-typedef int arrayind_t;
+typedef long arrayind_t;
enum atype {array_indexed, array_assoc};
@@ -67,7 +67,7 @@ extern char *quoted_array_assignment_str
extern char *array_to_string __P((ARRAY *, char *, int));
extern ARRAY *string_to_array __P((char *, char *));
-extern char *array_subrange __P((ARRAY *, int, int, int));
+extern char *array_subrange __P((ARRAY *, arrayind_t, arrayind_t, int));
extern char *array_pat_subst __P((ARRAY *, char *, char *, int));
extern ARRAY *array_quote __P((ARRAY *));
===================================================================
RCS file: array.c,v
retrieving revision 2.5
retrieving revision 2.5.0.1
diff -pu -r2.5 -r2.5.0.1
--- array.c 2000/11/03 16:20:00 2.5
+++ array.c 2001/04/29 23:39:20 2.5.0.1
@@ -159,7 +159,7 @@ ARRAY_ELEMENT *s, *e;
{
ARRAY *a;
ARRAY_ELEMENT *p, *n;
- int i;
+ arrayind_t i;
a = new_array ();
a->type = array->type;
@@ -525,10 +525,11 @@ ARRAY *array;
char *
array_subrange (a, start, end, quoted)
ARRAY *a;
-int start, end, quoted;
+arrayind_t start, end;
+int quoted;
{
ARRAY_ELEMENT *h, *p;
- int i;
+ arrayind_t i;
p = array_head (a);
if (p == 0 || array_empty (a) || start > array_num_elements (a))
@@ -577,7 +578,7 @@ int mflags;
print_element(ae)
ARRAY_ELEMENT *ae;
{
- printf("array[%d] = %s\n",(int)element_index(ae), element_value(ae));
+ printf("array[%ld] = %s\n", element_index(ae), element_value(ae));
}
print_array(a)
===================================================================
RCS file: subst.h,v
retrieving revision 2.5.0.1
retrieving revision 2.5.0.2
diff -pu -r2.5.0.1 -r2.5.0.2
--- subst.h 2001/04/29 05:03:42 2.5.0.1
+++ subst.h 2001/04/29 23:39:20 2.5.0.2
@@ -192,7 +192,7 @@ extern void unlink_fifo_list __P((void))
extern WORD_LIST *list_string_with_quotes __P((char *));
#if defined (ARRAY_VARS)
-extern int array_expand_index __P((char *, int));
+extern arrayind_t array_expand_index __P((char *, int));
extern int valid_array_reference __P((char *));
extern char *get_array_value __P((char *, int));
extern SHELL_VAR *array_variable_part __P((char *, char **, int *));
===================================================================
RCS file: subst.c,v
retrieving revision 2.5.0.5
retrieving revision 2.5.0.6
diff -pu -r2.5.0.5 -r2.5.0.6
--- subst.c 2001/04/29 05:03:42 2.5.0.5
+++ subst.c 2001/04/29 23:39:20 2.5.0.6
@@ -150,6 +150,7 @@ static WORD_LIST *garglist = (WORD_LIST
static char *make_quoted_char ();
static void remove_quoted_nulls ();
static char *param_expand ();
+static char *pos_params __P((char *, int, int, int));
static char *maybe_expand_string ();
static WORD_LIST *call_expand_word_internal ();
static WORD_LIST *expand_string_internal ();
@@ -161,7 +162,9 @@ static WORD_LIST *word_list_split ();
static WORD_LIST *quote_list (), *dequote_list ();
static char *quote_escapes ();
static WORD_LIST *list_quote_escapes ();
-static int unquoted_substring (), unquoted_member ();
+static int unquoted_substring ();
+static char *quoted_substring __P((char *, int, int));
+static int unquoted_member ();
static int do_assignment_internal ();
static char *string_extract_verbatim (), *string_extract ();
static char *string_extract_double_quoted (), *string_extract_single_quoted ();
@@ -1710,21 +1713,23 @@ do_array_element_assignment (name, value
char *name, *value;
{
char *t;
- int ind, ni;
+ int namelen;
+ arrayind_t ind;
+ int ni;
SHELL_VAR *entry;
t = strchr (name, '[');
if (t == 0)
return ((SHELL_VAR *)NULL);
- ind = t - name;
- ni = skipsubscript (name, ind);
- if ((ALL_ELEMENT_SUB (t[1]) && t[2] == ']') || (ni <= ind + 1))
+ namelen = t - name;
+ ni = skipsubscript (name, namelen);
+ if ((ALL_ELEMENT_SUB (t[1]) && t[2] == ']') || (ni <= namelen + 1))
{
report_error ("%s: bad array subscript", name);
return ((SHELL_VAR *)NULL);
}
*t++ = '\0';
- ind = array_expand_index (t, ni - ind);
+ ind = array_expand_index (t, ni - namelen);
if (ind < 0)
{
t[-1] = '['; /* restore original name ] */
@@ -3643,13 +3648,14 @@ valid_array_reference (name)
}
/* Expand the array index beginning at S and extending LEN characters. */
-int
+arrayind_t
array_expand_index (s, len)
char *s;
int len;
{
char *exp, *t;
- int val, expok;
+ arrayind_t val;
+ int expok;
exp = xmalloc (len);
strncpy (exp, s, len - 1);
@@ -3704,7 +3710,8 @@ array_value_internal (s, quoted, allow_a
char *s;
int quoted, allow_all;
{
- int len, ind;
+ int len;
+ arrayind_t ind;
char *retval, *t, *temp;
WORD_LIST *l, *list;
SHELL_VAR *var;
@@ -3787,7 +3794,8 @@ static int
array_length_reference (s)
char *s;
{
- int ind, len;
+ arrayind_t ind;
+ int len;
char *t;
ARRAY *array;
SHELL_VAR *var;
@@ -3798,10 +3806,10 @@ array_length_reference (s)
failure. */
if ((var == 0 || array_p (var) == 0) && unbound_vars_is_error)
{
- ind = *--t;
+ char c = *--t;
*t = '\0';
report_error ("%s: unbound variable", s);
- *t++ = (char)ind;
+ *t = c;
return (-1);
}
else if (var == 0)
@@ -4199,10 +4207,12 @@ skiparith (substr, delim)
static int
verify_substring_values (value, substr, vtype, e1p, e2p)
char *value, *substr;
- int vtype, *e1p, *e2p;
+ int vtype;
+ long *e1p, *e2p;
{
char *t, *temp1, *temp2;
- int len, expok;
+ arrayind_t len;
+ int expok;
#if defined (ARRAY_VARS)
ARRAY *a;
#endif
@@ -4341,7 +4351,8 @@ parameter_brace_substring (varname, valu
char *varname, *value, *substr;
int quoted;
{
- int e1, e2, vtype, r;
+ long e1, e2;
+ int vtype, r;
char *temp, *val;
SHELL_VAR *v;
===================================================================
RCS file: variables.h,v
retrieving revision 2.5
retrieving revision 2.5.0.1
diff -pu -r2.5 -r2.5.0.1
--- variables.h 2001/02/21 16:38:19 2.5
+++ variables.h 2001/04/29 23:39:20 2.5.0.1
@@ -230,7 +230,7 @@ extern char *indirection_level_string __
extern SHELL_VAR *make_new_array_variable __P((char *));
extern SHELL_VAR *make_local_array_variable __P((char *));
extern SHELL_VAR *convert_var_to_array __P((SHELL_VAR *));
-extern SHELL_VAR *bind_array_variable __P((char *, int, char *));
+extern SHELL_VAR *bind_array_variable __P((char *, arrayind_t, char *));
extern SHELL_VAR *assign_array_from_string __P((char *, char *));
extern SHELL_VAR *assign_array_var_from_word_list __P((SHELL_VAR *, WORD_LIST
*));
extern SHELL_VAR *assign_array_var_from_string __P((SHELL_VAR *, char *));
===================================================================
RCS file: variables.c,v
retrieving revision 2.5.0.3
retrieving revision 2.5.0.4
diff -pu -r2.5.0.3 -r2.5.0.4
--- variables.c 2001/04/13 08:15:26 2.5.0.3
+++ variables.c 2001/04/29 23:39:20 2.5.0.4
@@ -972,7 +972,7 @@ null_assign (self, value)
static SHELL_VAR *
null_array_assign (self, ind, value)
SHELL_VAR *self;
- int ind;
+ arrayind_t ind;
char *value;
{
return (self);
@@ -1135,7 +1135,7 @@ get_dirstack (self)
static SHELL_VAR *
assign_dirstack (self, ind, value)
SHELL_VAR *self;
- int ind;
+ arrayind_t ind;
char *value;
{
set_dirstack_element (ind, 1, value);
@@ -1700,7 +1700,7 @@ convert_var_to_array (var)
SHELL_VAR *
bind_array_variable (name, ind, value)
char *name;
- int ind;
+ arrayind_t ind;
char *value;
{
SHELL_VAR *entry;
@@ -1758,7 +1758,7 @@ assign_array_var_from_word_list (var, li
SHELL_VAR *var;
WORD_LIST *list;
{
- register int i;
+ register arrayind_t i;
register WORD_LIST *l;
ARRAY *a;
@@ -1814,7 +1814,8 @@ assign_array_var_from_string (var, value
ARRAY *a;
WORD_LIST *list, *nlist;
char *w, *val, *nval;
- int ni, len, ind, last_ind;
+ int ni, len;
+ arrayind_t ind, last_ind;
if (value == 0)
return var;
@@ -1958,7 +1959,8 @@ unbind_array_element (var, sub)
SHELL_VAR *var;
char *sub;
{
- int len, ind;
+ int len;
+ arrayind_t ind;
ARRAY_ELEMENT *ae;
len = skipsubscript (sub, 0);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Bash 2.05 mishandles large array subscripts on 64-bit hosts,
Paul Eggert <=