From 70d7c6430db990b5880da40e86f9a364966e48dd Mon Sep 17 00:00:00 2001
From: Chet Ramey <chet.ramey@case.edu>
Date: Tue, 28 Sep 2021 15:13:02 -0400
Subject: [PATCH] fixes for array subscripts and values containing 0x01
 characters

Conflict:Delete modifications in changlog and test cases; sh_single_quote in arrayfunc.c modify call method
Reference:https://git.savannah.gnu.org/cgit/bash.git/commit/?id=70d7c6430db990b5880da40e86f9a364966e48dd
---
 arrayfunc.c | 47 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 38 insertions(+), 9 deletions(-)

diff --git a/arrayfunc.c b/arrayfunc.c
index b2c8ff0..3222d0b 100644
--- a/arrayfunc.c
+++ b/arrayfunc.c
@@ -523,8 +523,17 @@ expand_compound_array_assignment (var, value, flags)
      shell expansions including pathname generation and word splitting. */
   /* First we split the string on whitespace, using the shell parser
      (ksh93 seems to do this). */
+  /* XXX - this needs a rethink, maybe use split_at_delims */
   list = parse_string_to_word_list (val, 1, "array assign");
 
+  /* If the parser has quoted CTLESC and CTNLNUL with CTLESC in unquoted
+     words, we need to remove those here because the code below assumes
+     they are there because they exist in the original word. */
+  /* XXX - if we rethink parse_string_to_word_list above, change this. */
+  for (nlist = list; nlist; nlist = nlist->next)
+    if ((nlist->word->flags & W_QUOTED) == 0)
+      remove_quoted_escapes (nlist->word->word);
+
   /* Note that we defer expansion of the assignment statements for associative
      arrays here, so we don't have to scan the subscript and find the ending
      bracket twice. See the caller below. */
@@ -606,10 +615,13 @@ char *
 expand_and_quote_kvpair_word (w)
      char *w;
 {
-  char *t, *r;
+  char *r, *s, *t;
 
   t = w ? expand_assignment_string_to_string (w, 0) : 0;
-  r = sh_single_quote (t ? t : "");
+  s = (t && strchr (t, CTLESC)) ? quote_escapes (t) : t;
+  r = sh_single_quote (s ? s : "");
+  if (s != t)
+    free (s);
   free (t);
   return r;
 }
@@ -895,7 +907,10 @@ quote_compound_array_word (w, type)
 
   wlen = strlen (w);
   w[ind] = '\0';
-  sub = sh_single_quote (w+1);
+  t = (strchr (w+1, CTLESC)) ? quote_escapes (w+1) : w+1;
+  sub = sh_single_quote (t);
+  if (t != w+1)
+   free (t);
   w[ind] = RBRACK;
 
   nword = xmalloc (wlen * 4 + 5);	/* wlen*4 is max single quoted length */
@@ -908,7 +923,10 @@ quote_compound_array_word (w, type)
   if (w[ind] == '+')
     nword[i++] = w[ind++];
   nword[i++] = w[ind++];
-  value = sh_single_quote (w + ind);
+  t = (strchr (w+ind, CTLESC)) ? quote_escapes (w+ind) : w+ind;
+  value = sh_single_quote (t);
+  if (t != w+ind)
+   free (t);
   strcpy (nword + i, value);
 
   return nword;
@@ -926,7 +944,7 @@ expand_and_quote_assoc_word (w, type)
      char *w;
      int type;
 {
-  char *nword, *key, *value, *t;
+  char *nword, *key, *value, *s, *t;
   int ind, wlen, i;
 
   if (w[0] != LBRACK)
@@ -937,8 +955,11 @@ expand_and_quote_assoc_word (w, type)
 
   w[ind] = '\0';
   t = expand_assignment_string_to_string (w+1, 0);
+  s = (t && strchr (t, CTLESC)) ? quote_escapes (t) : t;
+  key = sh_single_quote (s ? s : "");
+  if (s != t)
+    free (s);
   w[ind] = RBRACK;
-  key = sh_single_quote (t ? t : "");
   free (t);
 
   wlen = STRLEN (key);
@@ -953,7 +974,10 @@ expand_and_quote_assoc_word (w, type)
   nword[i++] = w[ind++];
 
   t = expand_assignment_string_to_string (w+ind, 0);
-  value = sh_single_quote (t ? t : "");
+  s = (t && strchr (t, CTLESC)) ? quote_escapes (t) : t;
+  value = sh_single_quote (s ? s : "");
+  if (s != t)
+    free (s);
   free (t);
   nword = xrealloc (nword, wlen + 5 + STRLEN (value));
   strcpy (nword + i, value);
@@ -973,7 +997,7 @@ quote_compound_array_list (list, type)
      WORD_LIST *list;
      int type;
 {
-  char *t;
+  char *s, *t;
   WORD_LIST *l;
 
   for (l = list; l; l = l->next)
@@ -981,7 +1005,12 @@ quote_compound_array_list (list, type)
       if (l->word == 0 || l->word->word == 0)
 	continue;	/* should not happen, but just in case... */
       if ((l->word->flags & W_ASSIGNMENT) == 0)
-	t = sh_single_quote (l->word->word);
+	{
+	  s = (strchr (l->word->word, CTLESC)) ? quote_escapes (l->word->word) : l->word->word;
+	  t = sh_single_quote (s);
+	  if (s != l->word->word)
+	    free (s);
+	}
       else 
 	t = quote_compound_array_word (l->word->word, type);
       free (l->word->word);
-- 
2.33.0

