mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 07:43:07 +02:00
allow locale's decimal point as radix character when parsing fixed-point decimal into seconds and fractional seconds; handle case of shell script file descriptor being made non-blocking; fix smalkl memory leak in programmable completion of shell option names; fix for patsub_replacement behavior when BASH_COMPAT = 42 and the replacement string is quoted; fix for readine when changing show-mode-in-prompt variable
This commit is contained in:
@@ -164,12 +164,14 @@ examples/loadables/accept
|
||||
examples/loadables/asort
|
||||
examples/loadables/basename
|
||||
examples/loadables/cat
|
||||
examples/loadables/chmod
|
||||
examples/loadables/csv
|
||||
examples/loadables/cut
|
||||
examples/loadables/dirname
|
||||
examples/loadables/dsv
|
||||
examples/loadables/fdflags
|
||||
examples/loadables/finfo
|
||||
examples/loadables/fltexpr
|
||||
examples/loadables/getconf
|
||||
examples/loadables/head
|
||||
examples/loadables/hello
|
||||
|
||||
@@ -12327,3 +12327,49 @@ builtins/printf.def
|
||||
discussed in thread starting with
|
||||
https://lists.gnu.org/archive/html/bug-bash/2025-02/msg00151.html
|
||||
|
||||
12/5
|
||||
----
|
||||
lib/sh/uconvert.c
|
||||
- uconvert: allow locale's decimal point character to serve as radix
|
||||
character when parsing fixed-point number into seconds and
|
||||
microseconds
|
||||
|
||||
12/8
|
||||
----
|
||||
input.c
|
||||
- b_fill_buffer: handle unlikely case of file descriptor being made
|
||||
non-blocking by retrying read on EAGAIN/EWOULDBLOCK
|
||||
Report and patch from Keno Fischer <keno@juliahub.com>
|
||||
|
||||
12/10
|
||||
-----
|
||||
builtins/shopt.def
|
||||
- get_shopt_options: don't allocate memory for each member of the
|
||||
option name array, since programmable completion doesn't free the
|
||||
list members
|
||||
From https://savannah.gnu.org/patch/?10551
|
||||
|
||||
12/12
|
||||
-----
|
||||
subst.c
|
||||
- expand_string_for_patsub42: new function, uses code from bash-4.2 to
|
||||
expand the pattern replacement string if patsub_replacement is not
|
||||
set; calls expand_string_for_patsub with the same value for QUOTING
|
||||
to quote patsub_replacement strings appropriately if it is set.
|
||||
This means that double-quoting the pattern substitution has the
|
||||
effect of quoting any `&' in the replacement string, which is iffy
|
||||
but closer to what bash-4.2 did
|
||||
- parameter_brace_patsub: call expand_string_for_patsub42 if the
|
||||
shell compatibility level is <= 42
|
||||
- quote_string_for_repl: if the shell compatibility level is <= 42
|
||||
and the replacement string is quoted, quote backslashes that quote
|
||||
`&' or `\' so strcreplace() preserves them
|
||||
Fixes most patsub_replacement compatibility issues with bash-4.2
|
||||
most recently raised by <a.elata@icloud.com>
|
||||
|
||||
12/16
|
||||
-----
|
||||
lib/readline/bind.c
|
||||
- show-mode-in-prompt: add V_SPECIAL flag so hack_special_boolean_var()
|
||||
gets called and _rl_reset_prompt will be called when it's changed
|
||||
Report and fix from Martin D Kealey <martin@kurahaupo.gen.nz>
|
||||
|
||||
@@ -1391,6 +1391,7 @@ tests/new-exp13.sub f
|
||||
tests/new-exp14.sub f
|
||||
tests/new-exp15.sub f
|
||||
tests/new-exp16.sub f
|
||||
tests/new-exp17.sub f
|
||||
tests/new-exp.right f
|
||||
tests/nquote.tests f
|
||||
tests/nquote.right f
|
||||
|
||||
+1
-1
@@ -777,7 +777,7 @@ get_shopt_options (void)
|
||||
n = sizeof (shopt_vars) / sizeof (shopt_vars[0]);
|
||||
ret = strvec_create (n + 1);
|
||||
for (i = 0; shopt_vars[i].name; i++)
|
||||
ret[i] = savestring (shopt_vars[i].name);
|
||||
ret[i] = shopt_vars[i].name;
|
||||
ret[i] = (char *)NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* error.h -- External declarations of functions appearing in error.c. */
|
||||
|
||||
/* Copyright (C) 1993-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2025 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -30,7 +30,7 @@ extern char *get_name_for_error (void);
|
||||
extern void file_error (const char *);
|
||||
|
||||
/* Report a programmer's error, and abort. Pass REASON, and ARG1 ... ARG5. */
|
||||
extern void programming_error (const char *, ...) __attribute__((__format__ (printf, 1, 2))) __attribute__((__noreturn__));;
|
||||
extern void programming_error (const char *, ...) __attribute__((__format__ (printf, 1, 2))) __attribute__((__noreturn__));
|
||||
|
||||
/* General error reporting. Pass FORMAT and ARG1 ... ARG5. */
|
||||
extern void report_error (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
|
||||
|
||||
@@ -510,33 +510,53 @@ b_fill_buffer (BUFFERED_STREAM *bp)
|
||||
if (bp->b_flag & B_ERROR) /* try making read errors `sticky' */
|
||||
return EOF;
|
||||
|
||||
/* In an environment where text and binary files are treated differently,
|
||||
compensate for lseek() on text files returning an offset different from
|
||||
the count of characters read() returns. Text-mode streams have to be
|
||||
treated as unbuffered. */
|
||||
if ((bp->b_flag & (B_TEXT | B_UNBUFF)) == B_TEXT)
|
||||
while (1) /* loop to handle non-blocking fds */
|
||||
{
|
||||
o = lseek (bp->b_fd, 0, SEEK_CUR);
|
||||
nr = zread (bp->b_fd, bp->b_buffer, bp->b_size);
|
||||
if (nr > 0 && nr < lseek (bp->b_fd, 0, SEEK_CUR) - o)
|
||||
/* In an environment where text and binary files are treated differently,
|
||||
compensate for lseek() on text files returning an offset different from
|
||||
the count of characters read() returns. Text-mode streams have to be
|
||||
treated as unbuffered. */
|
||||
if ((bp->b_flag & (B_TEXT | B_UNBUFF)) == B_TEXT)
|
||||
{
|
||||
lseek (bp->b_fd, o, SEEK_SET);
|
||||
bp->b_flag |= B_UNBUFF;
|
||||
bp->b_size = 1;
|
||||
o = lseek (bp->b_fd, 0, SEEK_CUR);
|
||||
nr = zread (bp->b_fd, bp->b_buffer, bp->b_size);
|
||||
if (nr > 0 && nr < lseek (bp->b_fd, 0, SEEK_CUR) - o)
|
||||
{
|
||||
lseek (bp->b_fd, o, SEEK_SET);
|
||||
bp->b_flag |= B_UNBUFF;
|
||||
bp->b_size = 1;
|
||||
nr = zread (bp->b_fd, bp->b_buffer, bp->b_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
nr = zread (bp->b_fd, bp->b_buffer, bp->b_size);
|
||||
if (nr <= 0)
|
||||
{
|
||||
else
|
||||
nr = zread (bp->b_fd, bp->b_buffer, bp->b_size);
|
||||
|
||||
if (nr > 0)
|
||||
break;
|
||||
|
||||
bp->b_used = bp->b_inputp = 0;
|
||||
bp->b_buffer[0] = 0;
|
||||
|
||||
if (nr == 0)
|
||||
bp->b_flag |= B_EOF;
|
||||
{
|
||||
bp->b_flag |= B_EOF;
|
||||
return (EOF);
|
||||
}
|
||||
else if (errno == X_EAGAIN || errno == X_EWOULDBLOCK)
|
||||
{
|
||||
if (sh_unset_nodelay_mode (bp->b_fd) < 0)
|
||||
{
|
||||
sys_error (_("cannot reset nodelay mode for fd %d"), bp->b_fd);
|
||||
bp->b_flag |= B_ERROR;
|
||||
return (EOF);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
bp->b_flag |= B_ERROR;
|
||||
return (EOF);
|
||||
{
|
||||
bp->b_flag |= B_ERROR;
|
||||
return (EOF);
|
||||
}
|
||||
}
|
||||
|
||||
bp->b_used = nr;
|
||||
|
||||
+1
-1
@@ -1906,7 +1906,7 @@ static const struct {
|
||||
{ "search-ignore-case", &_rl_search_case_fold, 0 },
|
||||
{ "show-all-if-ambiguous", &_rl_complete_show_all, 0 },
|
||||
{ "show-all-if-unmodified", &_rl_complete_show_unmodified, 0 },
|
||||
{ "show-mode-in-prompt", &_rl_show_mode_in_prompt, 0 },
|
||||
{ "show-mode-in-prompt", &_rl_show_mode_in_prompt, V_SPECIAL },
|
||||
{ "skip-completed-text", &_rl_skip_completed_text, 0 },
|
||||
#if defined (VISIBLE_STATS)
|
||||
{ "visible-stats", &rl_visible_stats, 0 },
|
||||
|
||||
+12
-4
@@ -1,7 +1,7 @@
|
||||
/* uconvert - convert string representations of decimal numbers into whole
|
||||
number/fractional value pairs. */
|
||||
|
||||
/* Copyright (C) 2008,2009,2020,2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2008,2009,2020-2025 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -29,13 +29,21 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <bashintl.h>
|
||||
#include <stdc.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include "chartypes.h"
|
||||
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
|
||||
#define DECIMAL '.' /* XXX - should use locale */
|
||||
#ifndef locale_decpoint
|
||||
extern int locale_decpoint (void);
|
||||
#endif
|
||||
|
||||
#define DECIMAL '.'
|
||||
#define ISRADIX(c) ((c) == DECIMAL || (c) == locale_decpoint())
|
||||
|
||||
#define RETURN(x) \
|
||||
do { \
|
||||
@@ -76,7 +84,7 @@ uconvert(const char *s, long *ip, long *up, char **ep)
|
||||
|
||||
for ( ; p && *p; p++)
|
||||
{
|
||||
if (*p == DECIMAL) /* decimal point */
|
||||
if (ISRADIX (*p)) /* radix character */
|
||||
break;
|
||||
if (DIGIT(*p) == 0)
|
||||
RETURN(0);
|
||||
@@ -86,7 +94,7 @@ uconvert(const char *s, long *ip, long *up, char **ep)
|
||||
if (p == 0 || *p == 0) /* callers ensure p can never be 0; this is to shut up clang */
|
||||
RETURN(1);
|
||||
|
||||
if (*p == DECIMAL)
|
||||
if (ISRADIX (*p))
|
||||
p++;
|
||||
|
||||
/* Look for up to six digits past a decimal point. */
|
||||
|
||||
@@ -353,6 +353,7 @@ static int shouldexp_replacement (const char *);
|
||||
static char *pos_params_pat_subst (char *, char *, char *, int);
|
||||
|
||||
static char *expand_string_for_patsub (char *, int);
|
||||
static char *expand_string_for_patsub42 (char *, int); /* BASH_COMPAT=42 version */
|
||||
static char *parameter_brace_patsub (char *, char *, array_eltstate_t *, char *, int, int, int);
|
||||
|
||||
static char *pos_params_casemod (char *, char *, int, int);
|
||||
@@ -3917,7 +3918,7 @@ expand_assignment_string_to_string (char *string, int quoted)
|
||||
or a backslash into a backslash. The output of this function must eventually
|
||||
be processed by strcreplace(). */
|
||||
static char *
|
||||
quote_string_for_repl (const char *string, int flags)
|
||||
quote_string_for_repl (const char *string, int quoted)
|
||||
{
|
||||
size_t slen;
|
||||
char *result, *t;
|
||||
@@ -3951,12 +3952,24 @@ quote_string_for_repl (const char *string, int flags)
|
||||
{
|
||||
/* This function's result has to be processed by strcreplace() */
|
||||
if (*s == CTLESC && (s[1] == '&' || s[1] == '\\'))
|
||||
{
|
||||
*t++ = '\\';
|
||||
s++;
|
||||
*t++ = *s++;
|
||||
continue;
|
||||
}
|
||||
{
|
||||
*t++ = '\\';
|
||||
s++;
|
||||
*t++ = *s++;
|
||||
continue;
|
||||
}
|
||||
/* Bash-4.2 and earlier don't perform quote removal on double-quoted
|
||||
pattern substitutions. */
|
||||
if (shell_compatibility_level <= 42 &&
|
||||
(quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) &&
|
||||
*s == '\\' && (s[1] == '&' || s[1] == '\\'))
|
||||
{
|
||||
*t++ = '\\'; *t++ = '\\';
|
||||
*t++ = '\\';
|
||||
s++;
|
||||
*t++ = *s++;
|
||||
continue;
|
||||
}
|
||||
/* Dequote it */
|
||||
if (*s == CTLESC)
|
||||
{
|
||||
@@ -4006,6 +4019,28 @@ expand_string_for_patsub (char *string, int quoted)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static char *
|
||||
expand_string_for_patsub42 (char *string, int quoted)
|
||||
{
|
||||
char *ret, *t;
|
||||
|
||||
if (string == 0 || *string == '\0')
|
||||
return (char *)NULL;
|
||||
|
||||
/* This is the bash-4.2 code from parameter_brace_patsub(). */
|
||||
if (patsub_replacement == 0)
|
||||
{
|
||||
if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0)
|
||||
ret = expand_string_if_necessary (string, quoted, expand_string_unsplit);
|
||||
else
|
||||
ret = expand_string_to_string_internal (string, quoted, expand_string_unsplit);
|
||||
}
|
||||
else
|
||||
ret = expand_string_for_patsub (string, quoted);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
char *
|
||||
expand_arith_string (char *string, int quoted)
|
||||
{
|
||||
@@ -9501,11 +9536,8 @@ parameter_brace_patsub (char *varname, char *value, array_eltstate_t *estatep,
|
||||
rep = expand_string_if_necessary (rep, quoted & ~(Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT), expand_string_unsplit);
|
||||
else if (shell_compatibility_level > 42 && patsub_replacement)
|
||||
rep = expand_string_for_patsub (rep, quoted & ~(Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT));
|
||||
/* This is the bash-4.2 code. */
|
||||
else if ((mflags & MATCH_QUOTED) == 0)
|
||||
rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
|
||||
else
|
||||
rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
|
||||
rep = expand_string_for_patsub42 (rep, quoted);
|
||||
|
||||
/* Check whether or not to replace `&' in the replacement string after
|
||||
expanding it, since we want to treat backslashes quoting the `&'
|
||||
|
||||
@@ -823,4 +823,29 @@ two
|
||||
&two
|
||||
otwone
|
||||
&twone
|
||||
new-exp17.sub
|
||||
unquoted word expansion with quoted pattern and replacement
|
||||
4.2: 4.2, a < b
|
||||
5.3: 4.2, a < b
|
||||
5.3: 5.2, a < b
|
||||
double-quoted word expansion with quoted pattern and replacement
|
||||
4.2: 4.2, a '<' b
|
||||
5.3: 4.2, a '<' b
|
||||
5.3: 5.2, a < b
|
||||
unquoted word expansion with unquoted pattern and replacement
|
||||
4.2: 4.2, a < b
|
||||
5.3: 4.2, a <lt; b
|
||||
5.3: 5.2, a <lt; b
|
||||
double-quoted word expansion with unquoted pattern and replacement
|
||||
4.2: 4.2, a < b
|
||||
5.3: 4.2, a < b
|
||||
5.3: 5.2, a <lt; b
|
||||
unquoted word expansion with backslash-quoted &
|
||||
4.2: 4.2, a < b
|
||||
5.3: 4.2, a < b
|
||||
5.3: 5.2, a < b
|
||||
double-quoted word expansion with backslash-quoted &
|
||||
4.2: 4.2, a \< b
|
||||
5.3: 4.2, a \< b
|
||||
5.3: 5.2, a < b
|
||||
./new-exp.tests: line 1: ABXD: parameter unset
|
||||
|
||||
@@ -668,6 +668,7 @@ test_runsub ./new-exp15.sub
|
||||
|
||||
# pattern substitution with `&' (quoted and unquoted) in the replacement string
|
||||
test_runsub ./new-exp16.sub
|
||||
test_runsub ./new-exp17.sub # test bash-4.2 compat
|
||||
|
||||
expect $0: 'ABXD: parameter unset'
|
||||
${THIS_SH} -c 'recho ${ABXD:?"parameter unset"}' $0
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# address issues with patsub_replacement, quoting `&', and BASH_COMPAT <= 42
|
||||
|
||||
# unquoted pattern substitutions with unquoted pattern and replacement strings
|
||||
# will still perform matching and replacement even if BASH_COMPAT == 42
|
||||
|
||||
s="a < b"
|
||||
|
||||
echo unquoted word expansion with quoted pattern and replacement
|
||||
echo '4.2: 4.2, a < b'
|
||||
for ver in 4.2 5.2; do
|
||||
BASH_COMPAT=$ver # ignored for bash version less than 5.0
|
||||
t=${s//'<'/'<'}
|
||||
echo "${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}: $BASH_COMPAT, $t"
|
||||
done
|
||||
|
||||
echo double-quoted word expansion with quoted pattern and replacement
|
||||
echo "4.2: 4.2, a '<' b"
|
||||
for ver in 4.2 5.2; do
|
||||
BASH_COMPAT=$ver # ignored for bash version less than 5.0
|
||||
t="${s//'<'/'<'}"
|
||||
echo "${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}: $BASH_COMPAT, $t"
|
||||
done
|
||||
|
||||
echo unquoted word expansion with unquoted pattern and replacement
|
||||
echo '4.2: 4.2, a < b'
|
||||
for ver in 4.2 5.2; do
|
||||
BASH_COMPAT=$ver # ignored for bash version less than 5.0
|
||||
t=${s//</<}
|
||||
echo "${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}: $BASH_COMPAT, $t"
|
||||
done
|
||||
|
||||
# XXX - this is iffy but difficult to distinguish internally
|
||||
echo double-quoted word expansion with unquoted pattern and replacement
|
||||
echo '4.2: 4.2, a < b'
|
||||
for ver in 4.2 5.2; do
|
||||
BASH_COMPAT=$ver # ignored for bash version less than 5.0
|
||||
t="${s//</<}"
|
||||
echo "${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}: $BASH_COMPAT, $t"
|
||||
done
|
||||
|
||||
echo unquoted word expansion with backslash-quoted '&'
|
||||
echo '4.2: 4.2, a < b'
|
||||
for ver in 4.2 5.2; do
|
||||
BASH_COMPAT=$ver # ignored for bash version less than 5.0
|
||||
t=${s//</\<}
|
||||
echo "${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}: $BASH_COMPAT, $t"
|
||||
done
|
||||
|
||||
echo double-quoted word expansion with backslash-quoted '&'
|
||||
echo '4.2: 4.2, a \< b'
|
||||
for ver in 4.2 5.2; do
|
||||
BASH_COMPAT=$ver # ignored for bash version less than 5.0
|
||||
t="${s//</\<}"
|
||||
echo "${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}: $BASH_COMPAT, $t"
|
||||
done
|
||||
Reference in New Issue
Block a user