bug-bash
[Top][All Lists]
Advanced

[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);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]