- update_line: use IS_COMBINING_CHAR instead of UNICODE_COMBINING_CHAR
plus WCWIDTH; it doesn't make sense on systems where wcwidth isn't
broken
+
+ 2/27
+ ----
+print_cmd.c
+ - print_case_clauses: if one of the case command pattern lists begins
+ with the word `esac' (unquoted), precede the pattern list with `(',
+ since it had to be there originally to get through the parser.
+ Report by Emanuele Torre <torreemanuele6@gmail.com>
+
+ 2/29
+ ----
+general.c,general.h
+ - string_to_rlimtype: takes a second ENDP argument, like strtol, so
+ the caller doesn't have to check that the string is all digits,
+ but can optionally check for and disallow a 0x prefix
+
+ 3/2
+ ---
+subst.c
+ - dequote_list: unset the W_QUOTED flag in the word after dequoting it
+ - parameter_brace_expand_rhs: if the word in the list returned by
+ expand_string_for_rhs has W_QUOTED set, but the string being
+ expanded was not quoted, turn on the W_QUOTED in the returned word
+ so we can potentially avoid word splitting
+ - expand_word_internal: if CTLNUL is a IFS character, don't add quoted
+ null strings to istring if we're going to be word splitting, since
+ they will be treated as word delimiters
#include "common.h"
#include "bashgetopt.h"
#include "pipesize.h"
+#include <chartypes.h>
#if !defined (errno)
extern int errno;
#if !defined (RLIMTYPE)
# define RLIMTYPE long
-# define string_to_rlimtype(s) strtol(s, (char **)NULL, 10)
+# define string_to_rlimtype(s, ep) strtol(s, ep, 10)
# define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "")
#endif
real_limit = soft_limit;
else if (STREQ (cmdarg, "unlimited"))
real_limit = RLIM_INFINITY;
- else if (all_digits (cmdarg))
+ else if (DIGIT (*cmdarg) && (cmdarg[1] == 0 || DIGIT (cmdarg[1])))
{
- limit = string_to_rlimtype (cmdarg);
+ char *endp;
+ limit = string_to_rlimtype (cmdarg, &endp);
+ if (*endp != '\0')
+ {
+ sh_invalidnum (cmdarg);
+ return (EXECUTION_FAILURE);
+ }
+
block_factor = BLOCKSIZE(limits[limind].block_factor);
real_limit = limit * block_factor;
static char *quote_escapes_internal (const char *, int);
+static char *quote_ifs (const char *);
+static WORD_LIST *list_quote_ifs (WORD_LIST *);
+
static WORD_LIST *list_quote_escapes (WORD_LIST *);
static WORD_LIST *list_dequote_escapes (WORD_LIST *);
/* This was further clarified on the austin-group list in March, 2017 and
in Posix bug 1129 */
old_nosplit = expand_no_split_dollar_star;
+ /* The check against ifs_is_null is so we don't split this time through,
+ since we will split the (possibly-quoted) results of this function. */
expand_no_split_dollar_star = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || op == '=' || ifs_is_null == 0; /* XXX - was 1 */
td.flags = W_EXPANDRHS; /* expanding RHS of ${paramOPword} */
td.flags |= W_NOSPLIT2; /* no splitting, remove "" and '' */
tlist->word->flags &= ~W_HASQUOTEDNULL;
free (tlist->word->word);
tlist->word->word = s;
+ tlist->word->flags &= ~W_QUOTED; /* no longer quoted */
}
return list;
}
return (string);
}
+/* Use CTLESC to quote IFS characters in STRING. Not used yet. */
+static char *
+quote_ifs (const char *string)
+{
+ const char *s, *send;
+ char *t, *result;
+ size_t slen;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+ send = string + slen;
+
+ t = result = (char *)xmalloc ((slen * 2) + 1);
+ s = string;
+
+ while (*s)
+ {
+ if (isifs (*s))
+ *t++ = CTLESC;
+ COPY_CHAR_P (t, s, send);
+ }
+ *t = '\0';
+
+ return (result);
+}
+
+static WORD_LIST *
+list_quote_ifs (WORD_LIST *list)
+{
+ WORD_LIST *w;
+ char *t;
+
+ for (w = list; w; w = w->next)
+ {
+ t = w->word->word;
+ w->word->word = quote_ifs (t);
+ free (t);
+ }
+ return list;
+}
+
/* Remove quoted $IFS characters from STRING. Quoted IFS characters are
added to protect them from word splitting, but we need to remove them
if no word splitting takes place. This returns newly-allocated memory,
temp = string_list (l);
if (temp && (QUOTED_NULL (temp) == 0) && (l->word->flags & W_SAWQUOTEDNULL))
w->flags |= W_SAWQUOTEDNULL; /* XXX */
+ if (temp && (l->word->flags & W_QUOTED) && quoted == 0)
+ w->flags |= W_QUOTED;
}
/* If we have a quoted null result (QUOTED_NULL(temp)) and the word is
temp = string_list_dollar_star (list, quoted, 0);
if (temp)
{
+ /* Q_HERE_DOCUMENT as well? */
temp1 = (quoted & Q_DOUBLE_QUOTES) ? quote_string (temp) : temp;
if (*temp == 0)
tflag |= W_HASQUOTEDNULL;
temp = string_list_dollar_at (list, quoted, 0);
/* Set W_SPLITSPACE to make sure the individual positional
parameters are split into separate arguments */
-#if 0
- if (quoted == 0 && (ifs_is_set == 0 || ifs_is_null))
-#else /* change with bash-5.0 */
if (quoted == 0 && ifs_is_null)
-#endif
tflag |= W_SPLITSPACE;
/* If we're not quoted but we still don't want word splitting, make
we quote the IFS characters to protect them from splitting (e.g.,
if (tword && (tword->flags & W_SAWQUOTEDNULL))
had_quoted_null = 1; /* XXX */
+ /* This loses tword->flags. If quoted == 0 but (tword->flags & W_QUOTED),
+ we need to note that somewhere. It means that the result will be
+ split, but this portion should not be. It only really matters if
+ $IFS contains $'\001', since usually quoting with CTLESC will
+ inhibit the word splitting. */
+
temp = tword ? tword->word : (char *)NULL;
dispose_word_desc (tword);
will cause word splitting. */
if (temp == 0 && quoted_state == PARTIALLY_QUOTED && quoted == 0 && (word->flags & (W_NOSPLIT|W_EXPANDRHS|W_ASSIGNRHS)) == W_EXPANDRHS)
{
+ /* Don't add a quoted null character if it would eventually be
+ used as a word delimiter when splitting. */
+ if (isifs (CTLNUL))
+ continue;
c = CTLNUL;
sindex--;
had_quoted_null = 1;
if (temp == 0 && quoted_state == PARTIALLY_QUOTED && (word->flags & (W_NOSPLIT|W_NOSPLIT2)))
continue;
+ /* Throw away a quoted null instead of adding a character that
+ would eventually be a word delimiter when splitting. */
+ if (temp == 0 && quoted_state == PARTIALLY_QUOTED && had_quoted_null && isifs(CTLNUL))
+ continue;
+
add_quoted_string:
if (temp)