new pattern substitution replacement feature; fix for problem with unset builtin and associative arrays

This commit is contained in:
Chet Ramey
2021-10-08 08:21:16 -04:00
parent f188aa6a01
commit f74291e6d1
8 changed files with 82 additions and 23 deletions
+45
View File
@@ -2183,3 +2183,48 @@ doc/{bash.1,bashref.texi}
now specifies the expansions that the replacement string undergoes
- pattern substitution: documented new behavior of unquoted & in the
replacement string
10/4
----
shell.c
- include <malloc/shmalloc.h> if we're debugging malloc (MALLOC_DEBUG)
so we can get an extern declaration of trace_malloc_stats
10/5
----
subst.c
- expand_subscript_string: allocate new memory for td.word, copying
STRING, in case it gets freed on error by expand_word_internal.
Report and fix from Koichi Murase <myoga.murase@gmail.com>
lib/malloc/malloc.c
- malloc_usable_size: return the allocated size instead of the chunk
size, since writing over the bounds checking will cause fatal errors.
Reported by Julien Moutinho <julm+bash@sourcephile.fr>, fix from
Dominique Martinet <asmadeus@codewreck.org>
arrayfunc.c
- unbind_array_elememnt: pass (flags&VA_NOEXPAND) to skipsubscript(),
instead of unconditionally passing 1 if we're operating on an
associative array. This is consistent with how valid_array_reference
determines the length of the subscript.
Report and fix from Koichi Murase <myoga.murase@gmail.com>
10/6
----
subst.c
- skip_to_delim: add a new value for FLAGS. If FLAGS&2, we assume that
START is one character after the opening OPEN. If not, we assume that
START is at OPEN, and needs to be incremented past it. Part of fix
from Koichi Murase <myoga.murase@gmail.com>
arrayfunc.c
- unbind_array_element: make sure to pass FLAGS to skipsubscript with
bit 2 set, since we are passed a SUB index that's one past the
opening bracket. Rest of fix from
Koichi Murase <myoga.murase@gmail.com>
- array_variable_name: make sure we pass (FLAGS&1) to skipsubscript, so
we don't inadvertently pass a value with bit 2 set, which would
cause an off-by-one error in subscript parsing
+3
View File
@@ -619,6 +619,9 @@ lint:
asan:
${MAKE} ${MFLAGS} ADDON_CFLAGS='${ASAN_XCFLAGS}' ADDON_LDFLAGS='${ASAN_XLDFLAGS}' .made
valgrind:
${MAKE} ${MFLAGS} ADDON_CFLAGS='-DDISABLE_MALLOC_WRAPPERS' ADDON_LDFLAGS= .made
# cheating
gcov:
${MAKE} ${MFLAGS} CFLAGS=-g ADDON_CFLAGS='${GCOV_XCFLAGS}' ADDON_LDFLAGS='${GCOV_XLDFLAGS}' .made
+5 -1
View File
@@ -1074,7 +1074,11 @@ unbind_array_element (var, sub, flags)
if (var && assoc_p (var) && (flags&VA_ONEWORD))
len = strlen (sub) - 1;
else
#if 0
len = skipsubscript (sub, 0, (flags&VA_NOEXPAND) || (var && assoc_p(var))); /* XXX */
#else
len = skipsubscript (sub, 0, (flags&VA_NOEXPAND) | 2); /* XXX */
#endif
if (sub[len] != ']' || len == 0)
{
builtin_error ("%s[%s: %s", var->name, sub, _(bash_badsub_errmsg));
@@ -1330,7 +1334,7 @@ array_variable_name (s, flags, subp, lenp)
return ((char *)NULL);
}
ind = t - s;
ni = skipsubscript (s, ind, flags); /* XXX - was 0 not flags */
ni = skipsubscript (s, ind, flags&1); /* XXX - was 0 not flags */
if (ni <= ind + 1 || s[ni] != ']')
{
err_badarraysub (s);
+1 -2
View File
@@ -4235,8 +4235,7 @@ fix_assignment_words (words)
#if defined (ARRAY_VARS)
/* Set W_ARRAYREF on words that are valid array references to a builtin that
accepts them. This is intended to eventually comnletely take the place of
assoc_expand_once. */
accepts them. This is intended to completely replace assoc_expand_once. */
static void
fix_arrayref_words (words)
WORD_LIST *words;
+7 -9
View File
@@ -1344,27 +1344,25 @@ malloc_usable_size (mem)
{
register union mhead *p;
register char *ap;
register int maxbytes;
if ((ap = (char *)mem) == 0)
return 0;
/* Find the true start of the memory block to discover which bin */
p = (union mhead *) ap - 1;
if (p->mh_alloc == ISMEMALIGN)
{
ap -= p->mh_nbytes;
p = (union mhead *) ap - 1;
}
/* XXX - should we return 0 if ISFREE? */
maxbytes = binsize(p->mh_index);
/* So the usable size is the maximum number of bytes in the bin less the
malloc overhead */
maxbytes -= MOVERHEAD + MSLOP;
return (maxbytes);
/* return 0 if ISFREE */
if (p->mh_alloc == ISFREE)
return 0;
/* Since we use bounds checking, the usable size is the last requested size. */
return (p->mh_nbytes);
}
#if !defined (NO_VALLOC)
+2
View File
@@ -72,6 +72,8 @@ extern int get_tty_state PARAMS((void));
#if defined (USING_BASH_MALLOC) && defined (DEBUG) && !defined (DISABLE_MALLOC_WRAPPERS)
# include <malloc/shmalloc.h>
#elif defined (MALLOC_DEBUG) && defined (USING_BASH_MALLOC)
# include <malloc/shmalloc.h>
#endif
#if defined (HISTORY)
+18 -10
View File
@@ -1737,12 +1737,14 @@ unquote_bang (string)
#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = oldjmp; return (x); } while (0)
/* This function assumes s[i] == open; returns with s[ret] == close; used to
parse array subscripts. FLAGS & 1 means to not attempt to skip over
matched pairs of quotes or backquotes, or skip word expansions; it is
intended to be used after expansion has been performed and during final
assignment parsing (see arrayfunc.c:assign_compound_array_list()) or
during execution by a builtin which has already undergone word expansion. */
/* When FLAGS & 2 == 0, this function assumes STRING[I] == OPEN; when
FLAGS & 2 != 0, it assumes STRING[I] points to one character past OPEN;
returns with STRING[RET] == close; used to parse array subscripts.
FLAGS & 1 means not to attempt to skip over matched pairs of quotes or
backquotes, or skip word expansions; it is intended to be used after
expansion has been performed and during final assignment parsing (see
arrayfunc.c:assign_compound_array_list()) or during execution by a builtin
which has already undergone word expansion. */
static int
skip_matched_pair (string, start, open, close, flags)
const char *string;
@@ -1757,7 +1759,10 @@ skip_matched_pair (string, start, open, close, flags)
oldjmp = no_longjmp_on_fatal_error;
no_longjmp_on_fatal_error = 1;
i = start + 1; /* skip over leading bracket */
/* Move to the first character after a leading OPEN. If FLAGS&2, we assume
that START already points to that character. If not, we need to skip over
it here. */
i = (flags & 2) ? start : start + 1;
count = 1;
pass_next = backq = 0;
ss = (char *)string;
@@ -1838,9 +1843,11 @@ skip_matched_pair (string, start, open, close, flags)
}
#if defined (ARRAY_VARS)
/* Flags has 1 as a reserved value, since skip_matched_pair uses it for
/* FLAGS has 1 as a reserved value, since skip_matched_pair uses it for
skipping over quoted strings and taking the first instance of the
closing character. */
closing character. FLAGS & 2 means that STRING[START] points one
character past the open bracket; FLAGS & 2 == 0 means that STRING[START]
points to the open bracket. skip_matched_pair knows how to deal with this. */
int
skipsubscript (string, start, flags)
const char *string;
@@ -10246,7 +10253,7 @@ expand_subscript_string (string, quoted)
ret = (char *)NULL;
td.flags = W_NOPROCSUB|W_NOTILDE|W_NOSPLIT2; /* XXX - W_NOCOMSUB? */
td.word = string;
td.word = savestring (string); /* in case it's freed on error */
expand_no_split_dollar_star = 1;
tlist = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
@@ -10264,6 +10271,7 @@ expand_subscript_string (string, quoted)
dispose_words (tlist);
}
free (td.word);
return (ret);
}
+1 -1
View File
@@ -1,4 +1,4 @@
BUILD_DIR=/usr/local/build/bash/bash-current
BUILD_DIR=/usr/local/build/chet/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR