diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index ce4e4b68..0997f559 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -8407,3 +8407,52 @@ doc/{bash.1,bashref.texi} - BASH_COMPAT: overhauled the text, refers to Shell Compatibility Mode section + 5/27 + ---- +variables.c,/lib/sh/random.c + - moved functions that manage 16-bit and 32-bit random values to + lib/sh/random.c + +alias.c + - add_alias: don't bother checking null alias values for ending in + space or tab + +braces.c,include/typemax.h + - move sh_imaxabs and overflow and underflow detection to typemax.h + so the expression evaluation code can use it in the future + + 5/28 + ---- +lib/readline/kill.c + - _rl_bracketed_read_mbstring: make sure to fill in mb[0] even if + the locale says MB_CUR_MAX == 1 in case a caller uses it. Partial + fix for bug reported by Phi Debian + +lib/readline/vi_mode.c + - _rl_vi_change_char: make sure _rl_vi_last_replacement gets filled in + in the case where MB_CUR_MAX == 1. Rest of fix for bug reported by + Phi Debian + - rl_vi_change_char: same fix for _rl_vi_last_replacement + + 5/29 + ---- +lib/malloc/malloc.c + - __P -> PARAMS + - union mhead: now 16 bytes to force 16-byte alignment; extra 8 bytes + at the end of struct minfo to use for guard bytes. Enabled if + pointers are 64 bits (SIZEOF_CHAR_P == 8) + - if we have 64-bit pointers, prepopulate the 64-byte bin first instead + of the 32-byte bin (pointers and WORD_DESCs still fit into 32 bytes, + but WORD_LISTs are now 36 bytes with malloc overhead). We can still + split 64-byte blocks to satisfy 32-byte requests + - internal_malloc: fill in the new 8 mh_magic8 bytes with MAGIC1 guard + bytes + - internal_malloc: print a warning message if the returned pointer is + not aligned according to MALIGN_MASK + - internal_free: detect underflow by checking that mh_magic8 is full + of MAGIC1 bytes + - internal_realloc: detect underflow by checking that mh_magic8 is full + of MAGIC1 bytes + +lib/malloc/stats.c + - _print_malloc_stats: slight adjustment for better column alignment diff --git a/MANIFEST b/MANIFEST index b1213ae1..9f2e58d8 100644 --- a/MANIFEST +++ b/MANIFEST @@ -420,6 +420,7 @@ lib/sh/netopen.c f lib/sh/oslib.c f lib/sh/pathcanon.c f lib/sh/pathphys.c f +lib/sh/random.c f lib/sh/rename.c f lib/sh/setlinebuf.c f lib/sh/shmatch.c f diff --git a/Makefile.in b/Makefile.in index 886783b9..f9e99fba 100644 --- a/Makefile.in +++ b/Makefile.in @@ -231,7 +231,7 @@ SHLIB_SOURCE = ${SH_LIBSRC}/clktck.c ${SH_LIBSRC}/getcwd.c \ ${SH_LIBSRC}/input_avail.c ${SH_LIBSRC}/mbscasecmp.c \ ${SH_LIBSRC}/fnxform.c ${SH_LIBSRC}/unicode.c \ ${SH_LIBSRC}/wcswidth.c ${SH_LIBSRC}/wcsnwidth.c \ - ${SH_LIBSRC}/shmbchar.c ${SH_LIBSRC}/utf8.c + ${SH_LIBSRC}/shmbchar.c ${SH_LIBSRC}/utf8.c ${SH_LIBSRC}/random.c SHLIB_LIB = -lsh SHLIB_LIBNAME = libsh.a diff --git a/alias.c b/alias.c index 74ae8700..70138c85 100644 --- a/alias.c +++ b/alias.c @@ -127,9 +127,12 @@ add_alias (name, value) free (temp->value); temp->value = savestring (value); temp->flags &= ~AL_EXPANDNEXT; - n = value[strlen (value) - 1]; - if (n == ' ' || n == '\t') - temp->flags |= AL_EXPANDNEXT; + if (value[0]) + { + n = value[strlen (value) - 1]; + if (n == ' ' || n == '\t') + temp->flags |= AL_EXPANDNEXT; + } } else { @@ -138,9 +141,12 @@ add_alias (name, value) temp->value = savestring (value); temp->flags = 0; - n = value[strlen (value) - 1]; - if (n == ' ' || n == '\t') - temp->flags |= AL_EXPANDNEXT; + if (value[0]) + { + n = value[strlen (value) - 1]; + if (n == ' ' || n == '\t') + temp->flags |= AL_EXPANDNEXT; + } elt = hash_insert (savestring (name), aliases, HASH_NOSRCH); elt->data = temp; diff --git a/braces.c b/braces.c index 82c17403..8d0c7709 100644 --- a/braces.c +++ b/braces.c @@ -356,25 +356,6 @@ expand_amble (text, tlen, flags) #define ST_CHAR 2 #define ST_ZINT 3 -#ifndef sh_imaxabs -# define sh_imaxabs(x) (((x) >= 0) ? (x) : -(x)) -#endif - -/* Handle signed arithmetic overflow and underflow. Have to do it this way - to avoid compilers optimizing out simpler overflow checks. */ - -/* Make sure that a+b does not exceed MAXV or is smaller than MINV (if b < 0). - Assumes that b > 0 if a > 0 and b < 0 if a < 0 */ -#define ADDOVERFLOW(a,b,minv,maxv) \ - ((((a) > 0) && ((b) > ((maxv) - (a)))) || \ - (((a) < 0) && ((b) < ((minv) - (a))))) - -/* Make sure that a-b is not smaller than MINV or exceeds MAXV (if b < 0). - Assumes that b > 0 if a > 0 and b < 0 if a < 0 */ -#define SUBOVERFLOW(a,b,minv,maxv) \ - ((((b) > 0) && ((a) < ((minv) + (b)))) || \ - (((b) < 0) && ((a) > ((maxv) + (b))))) - static char ** mkseq (start, end, incr, type, width) intmax_t start, end, incr; diff --git a/doc/bash.1 b/doc/bash.1 index 696351bd..defe1e38 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -5206,8 +5206,9 @@ start it, or using a substring that appears in its command line. For example, .B %ce refers to a stopped -.B ce -job. If a prefix matches more than one job, +job whose command name begins with +.BR ce . +If a prefix matches more than one job, .B bash reports an error. Using .BR %?ce , diff --git a/doc/bashref.texi b/doc/bashref.texi index 2f2b6bdd..9741eee8 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -8257,7 +8257,8 @@ previous job with a @samp{-}. A job may also be referred to using a prefix of the name used to start it, or using a substring that appears in its command line. For example, @samp{%ce} refers -to a stopped @code{ce} job. Using @samp{%?ce}, on the +to a stopped job whose command name begins with @samp{ce}. +Using @samp{%?ce}, on the other hand, refers to any job containing the string @samp{ce} in its command line. If the prefix or substring matches more than one job, Bash reports an error. diff --git a/doc/shell-compat b/doc/shell-compat deleted file mode 100644 index c79aee17..00000000 --- a/doc/shell-compat +++ /dev/null @@ -1,158 +0,0 @@ -@node Shell Compatibility Mode -@section Shell Compatibility Mode -@cindex Compatibility Level -@cindex Compatibility Mode - -Bash-4.0 introduced the concept of a `shell compatibility level', specified -as a set of options to the shopt builtin -(@code{compat31}, -@code{compat32}, -@code{compat40}, -@code{compat41}, -and so on). -There is only one current -compatibility level -- each option is mutually exclusive. -The compatibility level is intended to allow users to select behavior -from previous versions that is incompatible with newer versions -while they migrate scripts to use current features and -behavior. It's intended to be a temporary solution. - -This section does not mention behavior that is standard for a particular -version (e.g., setting @code{compat32} means that quoting the rhs of the regexp -matching operator quotes special regexp characters in the word, which is -default behavior in bash-3.2 and above). - -If a user enables, say, @code{compat32}, it may affect the behavior of other -compatibility levels up to and including the current compatibility level. -The idea is that each compatibility level controls behavior that changed -in that version of Bash, but that granularity may not be sufficient for -all uses, and as a result users should employ compatibility levels carefully. -Read the documentation for a particular feature to find out the -current behavior. - -Bash-4.3 introduced a new shell variable: @env{BASH_COMPAT}. -The value assigned -to this variable (a decimal version number like 4.2, or an integer -corresponding to the @code{compat}@var{NN} option, like 42) determines the -compatibility level. - -Starting with bash-4.4, Bash has begun deprecating older compatibility -levels. -Eventually, the options will be removed in favor of @env{BASH_COMPAT}. - -Bash-5.0 is the final version for which there will be an individual shopt -option for the previous version. Users should use @env{BASH_COMPAT} -on bash-5.0 and later versions. - -The following table describes the behavior changes controlled by each -compatibility level setting. -The @code{compat}@var{NN} tag is used as shorthand for setting the -compatibility level -to @var{NN} using one of the following mechanisms. -For versions prior to bash-5.0, the compatibility level may be set using -the corresponding @code{compat}@var{NN} shopt option. -For bash-4.3 and later versions, the @env{BASH_COMPAT} variable is preferred, -and it is required for bash-5.1 and later versions. - -@table @code -@item compat31 -@itemize @bullet -@item -quoting the rhs of the @code{[[} command's regexp matching operator (=~) -has no special effect -@end itemize - -@item compat32 -@itemize @bullet -@item -interrupting a command list such as "a ; b ; c" causes the execution -of the next command in the list (in bash-4.0 and later versions, -the shell acts as if it received the interrupt, so -interrupting one command in a list aborts the execution of the -entire list) -@end itemize - -@item compat40 -@itemize @bullet -@item -the @samp{<} and @samp{>} operators to the @code{[[} command do not -consider the current locale when comparing strings; they use ASCII -ordering. -Bash versions prior to bash-4.1 use ASCII collation and strcmp(3); -bash-4.1 and later use the current locale's collation sequence and -strcoll(3). -@end itemize - -@item compat41 -@itemize @bullet -@item -in posix mode, @code{time} may be followed by options and still be -recognized as a reserved word (this is @sc{posix} interpretation 267) -@item -in posix mode, the parser requires that an even number of single -quotes occur in the @var{word} portion of a double-quoted $@{@dots{}@} -parameter expansion and treats them specially, so that characters within -the single quotes are considered quoted -(this is @sc{posix} interpretation 221) -@end itemize - -@item compat42 -@itemize @bullet -@item -the replacement string in double-quoted pattern substitution is not -run through quote removal, as it is in versions after bash-4.2 -@item -in posix mode, single quotes are considered special when expanding -the @var{word} portion of a double-quoted a $@{@dots{}@} parameter expansion -and can be used to quote a closing brace or other special character -(this is part of @sc{posix} interpretation 221); -in later versions, single quotes -are not special within double-quoted word expansions -@end itemize - -@item compat43 -@itemize @bullet -@item -the shell does not print a warning message if an attempt is made to -use a quoted compound assignment as an argument to declare -(declare -a foo='(1 2)'). Later versions warn that this usage is -deprecated -@item -word expansion errors are considered non-fatal errors that cause the -current command to fail, even in posix mode -(the default behavior is to make them fatal errors that cause the shell -to exit) -@item -when executing a shell function, the loop state (while/until/etc.) -is not reset, so @code{break} or @code{continue} in that function will break -or continue loops in the calling context. Bash-4.4 and later reset -the loop state to prevent this -@end itemize - -@item compat44 -@itemize @bullet -@item -the shell sets up the values used by @env{BASH_ARGV} and @env{BASH_ARGC} -so they can expand to the shell's positional parameters even if extended -debug mode is not enabled -@item -a subshell inherits loops from its parent context, so @code{break} -or @code{continue} will cause the subshell to exit. -Bash-5.0 and later reset the loop state to prevent the exit -@item -variable assignments preceding builtins like @code{export} and @code{readonly} -that set attributes continue to affect variables with the same -name in the calling environment even if the shell is not in posix -mode -@end itemize - -@item compat50 (set using BASH_COMPAT) -@itemize @bullet -@item -Bash-5.1 changed the way @code{$RANDOM} is generated to introduce slightly -more randomness. If the shell compatibility level is set to 50 or -lower, it reverts to the method from bash-5.0 and previous versions, -so seeding the random number generator by assigning a value to -@env{RANDOM} wll produce the same sequence as in bash-5.0 -@end itemize -@end table diff --git a/doc/shell-compat.t b/doc/shell-compat.t deleted file mode 100644 index d4d1b9c4..00000000 --- a/doc/shell-compat.t +++ /dev/null @@ -1,169 +0,0 @@ -.SH Shell Compatibility Mode -Bash-4.0 introduced the concept of a `shell compatibility level', specified -as a set of options to the shopt builtin -.BR compat31 , -.BR compat32 , -.BR compat40 , -.BR compat41 , -and so on). -There is only one current -compatibility level -- each option is mutually exclusive. -The compatibility level is intended to allow users to select behavior -from previous versions that is incompatible with newer versions -while they migrate scripts to use current features and -behavior. It's intended to be a temporary solution. -.PP -This section does not mention behavior that is standard for a particular -version (e.g., setting \fBcompat32\fP means that quoting the rhs of the regexp -matching operator quotes special regexp characters in the word, which is -default behavior in bash-3.2 and above). -.PP -If a user enables, say, \fBcompat32\fP, it may affect the behavior of other -compatibility levels up to and including the current compatibility level. -The idea is that each compatibility level controls behavior that changed -in that version of \fBbash\fP, -but that behavior may have been present in earlier versions. -For instance, the change to use locale-based comparisons with the \fB[[\fP -command came in bash-4.1, and earlier versions used ASCII-based comparisons, -so enabling \fBcompat32\fP will enable ASCII-based comparisons as well. -That granularity may not be sufficient for -all uses, and as a result users should employ compatibility levels carefully. -Read the documentation for a particular feature to find out the -current behavior. -.PP -Bash-4.3 introduced a new shell variable: -.SM -.BR BASH_COMPAT . -The value assigned -to this variable (a decimal version number like 4.2, or an integer -corresponding to the \fBcompat\fP\fINN\fP option, like 42) determines the -compatibility level. -.PP -Starting with bash-4.4, Bash has begun deprecating older compatibility -levels. -Eventually, the options will be removed in favor of -.SM -.BR BASH_COMPAT . -.PP -Bash-5.0 is the final version for which there will be an individual shopt -option for the previous version. Users should use -.SM -.B BASH_COMPAT -on bash-5.0 and later versions. -.PP -The following table describes the behavior changes controlled by each -compatibility level setting. -The \fBcompat\fP\fINN\fP tag is used as shorthand for setting the -compatibility level -to \fINN\fP using one of the following mechanisms. -For versions prior to bash-5.0, the compatibility level may be set using -the corresponding \fBcompat\fP\fINN\fP shopt option. -For bash-4.3 and later versions, the -.SM -.B BASH_COMPAT -variable is preferred, -and it is required for bash-5.1 and later versions. -.PP - -.TP -\fBcompat31\fP -.IP \(bu -quoting the rhs of the \fB[[\fP command's regexp matching operator (=~) -has no special effect - -.TP -\fBcompat32\fP -.IP \(bu -interrupting a command list such as "a ; b ; c" causes the execution -of the next command in the list (in bash-4.0 and later versions, -the shell acts as if it received the interrupt, so -interrupting one command in a list aborts the execution of the -entire list) - -.TP -\fBcompat40\fP -.IP \(bu -the \fB<\fP and \fB>\fP operators to the \fB[[\fP command do not -consider the current locale when comparing strings; they use ASCII -ordering. -Bash versions prior to bash-4.1 use ASCII collation and -.IR strcmp (3); -bash-4.1 and later use the current locale's collation sequence and -.IR strcoll (3). - -.TP -\fBcompat41\fP -.IP \(bu -in \fIposix\fP mode, \fBtime\fP may be followed by options and still be -recognized as a reserved word (this is POSIX interpretation 267) -.IP \(bu -in \fIposix\fP mode, the parser requires that an even number of single -quotes occur in the \fIword\fP portion of a double-quoted -parameter expansion and treats them specially, so that characters within -the single quotes are considered quoted -(this is POSIX interpretation 221) - -.TP -\fBcompat42\fP -.IP \(bu -the replacement string in double-quoted pattern substitution does not -undergo quote removal, as it does in versions after bash-4.2 -.IP \(bu -in posix mode, single quotes are considered special when expanding -the \fIword\fP portion of a double-quoted parameter expansion -and can be used to quote a closing brace or other special character -(this is part of POSIX interpretation 221); -in later versions, single quotes -are not special within double-quoted word expansions - -.TP -\fBcompat43\fP -the shell does not print a warning message if an attempt is made to -use a quoted compound assignment as an argument to declare -(declare -a foo='(1 2)'). Later versions warn that this usage is -deprecated -.IP \(bu -word expansion errors are considered non-fatal errors that cause the -current command to fail, even in posix mode -(the default behavior is to make them fatal errors that cause the shell -to exit) -.IP \(bu -when executing a shell function, the loop state (while/until/etc.) -is not reset, so \fBbreak\fP or \fBcontinue\fP in that function will break -or continue loops in the calling context. Bash-4.4 and later reset -the loop state to prevent this - -.TP -\fBcompat44\fP -.IP \(bu -the shell sets up the values used by -.SM -.B BASH_ARGV -and -.SM -.B BASH_ARGC -so they can expand to the shell's positional parameters even if extended -debug mode is not enabled -.IP \(bu -a subshell inherits loops from its parent context, so \fBbreak\fP -or \fBcontinue\fP will cause the subshell to exit. -Bash-5.0 and later reset the loop state to prevent the exit -.IP \(bu -variable assignments preceding builtins like \fBexport\fP and \fBreadonly\fP -that set attributes continue to affect variables with the same -name in the calling environment even if the shell is not in posix -mode - -.TP -\fBcompat50\fP -.IP \(bu -Bash-5.1 changed the way -.SM -.B $RANDOM -is generated to introduce slightly -more randomness. If the shell compatibility level is set to 50 or -lower, it reverts to the method from bash-5.0 and previous versions, -so seeding the random number generator by assigning a value to -.SM -.B RANDOM -will produce the same sequence as in bash-5.0 diff --git a/expr.c b/expr.c index 66c04afd..bbff95e9 100644 --- a/expr.c +++ b/expr.c @@ -549,6 +549,7 @@ expassign () switch (op) { case MUL: + /* Handle INTMAX_MIN and INTMAX_MAX * -1 specially here? */ lvalue *= value; break; case DIV: diff --git a/externs.h b/externs.h index 6c9a0163..3d7716c6 100644 --- a/externs.h +++ b/externs.h @@ -1,7 +1,7 @@ /* externs.h -- extern function declarations which do not appear in their own header file. */ -/* Copyright (C) 1993-2010 Free Software Foundation, Inc. +/* Copyright (C) 1993-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -308,6 +308,13 @@ extern char *sh_canonpath PARAMS((char *, int)); extern char *sh_physpath PARAMS((char *, int)); extern char *sh_realpath PARAMS((const char *, char *)); +/* declarations for functions defined in lib/sh/random.c */ +extern int brand PARAMS((void)); +extern void sbrand PARAMS((unsigned long)); /* set bash random number generator. */ +extern void seedrand PARAMS((void)); /* seed generator randomly */ +extern void seedrand32 PARAMS((void)); +extern u_bits32_t get_urandom32 PARAMS((void)); + /* declarations for functions defined in lib/sh/setlinebuf.c */ #ifdef NEED_SH_SETLINEBUF_DECL extern int sh_setlinebuf PARAMS((FILE *)); diff --git a/include/typemax.h b/include/typemax.h index 0f696388..9853d567 100644 --- a/include/typemax.h +++ b/include/typemax.h @@ -109,4 +109,23 @@ static const unsigned long long int maxquad = ULLONG_MAX; # define SIZE_MAX 65535 /* POSIX minimum max */ #endif +#ifndef sh_imaxabs +# define sh_imaxabs(x) (((x) >= 0) ? (x) : -(x)) +#endif + +/* Handle signed arithmetic overflow and underflow. Have to do it this way + to avoid compilers optimizing out simpler overflow checks. */ + +/* Make sure that a+b does not exceed MAXV or is smaller than MINV (if b < 0). + Assumes that b > 0 if a > 0 and b < 0 if a < 0 */ +#define ADDOVERFLOW(a,b,minv,maxv) \ + ((((a) > 0) && ((b) > ((maxv) - (a)))) || \ + (((a) < 0) && ((b) < ((minv) - (a))))) + +/* Make sure that a-b is not smaller than MINV or exceeds MAXV (if b < 0). + Assumes that b > 0 if a > 0 and b < 0 if a < 0 */ +#define SUBOVERFLOW(a,b,minv,maxv) \ + ((((b) > 0) && ((a) < ((minv) + (b)))) || \ + (((b) < 0) && ((a) > ((maxv) + (b))))) + #endif /* _SH_TYPEMAX_H */ diff --git a/lib/malloc/malloc.c b/lib/malloc/malloc.c index ae9a5557..b3196366 100644 --- a/lib/malloc/malloc.c +++ b/lib/malloc/malloc.c @@ -1,6 +1,6 @@ /* malloc.c - dynamic memory allocation for bash. */ -/* Copyright (C) 1985-2005 Free Software Foundation, Inc. +/* Copyright (C) 1985-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne-Again SHell. @@ -25,6 +25,8 @@ * * Nov 1983, Mike@BRL, Added support for 4.1C/4.2 BSD. * + * [VERY] old explanation: + * * This is a very fast storage allocator. It allocates blocks of a small * number of different sizes, and keeps free lists of each size. Blocks * that don't exactly fit are passed up to the next larger size. In this @@ -138,22 +140,35 @@ enough room in the block for the new size. Range checking is always done. */ union mhead { +#if SIZEOF_CHAR_P == 8 + bits64_t mh_align[2]; /* 16 */ +#else bits64_t mh_align; /* 8 */ +#endif struct { char mi_alloc; /* ISALLOC or ISFREE */ /* 1 */ char mi_index; /* index in nextf[] */ /* 1 */ /* Remainder are valid only when block is allocated */ u_bits16_t mi_magic2; /* should be == MAGIC2 */ /* 2 */ u_bits32_t mi_nbytes; /* # of bytes allocated */ /* 4 */ +#if SIZEOF_CHAR_P == 8 + char mi_magic8[8]; /* MAGIC1 guard bytes */ /* 8 */ +#endif } minfo; }; #define mh_alloc minfo.mi_alloc #define mh_index minfo.mi_index #define mh_nbytes minfo.mi_nbytes #define mh_magic2 minfo.mi_magic2 +#define mh_magic8 minfo.mi_magic8 #define MOVERHEAD sizeof(union mhead) + +#if SIZEOF_CHAR_P == 8 +#define MALIGN_MASK 15 +#else #define MALIGN_MASK 7 /* one less than desired alignment */ +#endif typedef union _malloc_guard { char s[4]; @@ -167,6 +182,8 @@ typedef union _malloc_guard { to describe the overhead for when the block is in use, and we do not want the free-list pointer to count in that. */ +/* If SIZEOF_CHAR_P == 8, this goes into the mh_magic8 buffer at the end of + the rest of the struct. This may need adjusting. */ #define CHAIN(a) \ (*(union mhead **) (sizeof (char *) + (char *) (a))) @@ -174,13 +191,14 @@ typedef union _malloc_guard { and end of each allocated block, and make sure they are undisturbed whenever a free or a realloc occurs. */ -/* Written in the 2 bytes before the block's real space (-4 bytes) */ +/* Written in the bytes before the block's real space (-SIZEOF_CHAR_P bytes) */ +#define MAGIC1 0x55 #define MAGIC2 0x5555 #define MSLOP 4 /* 4 bytes extra for u_bits32_t size */ /* How many bytes are actually allocated for a request of size N -- - rounded up to nearest multiple of 8 after accounting for malloc - overhead. */ + rounded up to nearest multiple of 2*SIZEOF_CHAR_P after accounting for + malloc overhead. */ #define ALLOCATED_BYTES(n) \ (((n) + MOVERHEAD + MSLOP + MALIGN_MASK) & ~MALIGN_MASK) @@ -277,24 +295,24 @@ extern int errno; #endif /* Declarations for internal functions */ -static PTR_T internal_malloc __P((size_t, const char *, int, int)); -static PTR_T internal_realloc __P((PTR_T, size_t, const char *, int, int)); -static void internal_free __P((PTR_T, const char *, int, int)); -static PTR_T internal_memalign __P((size_t, size_t, const char *, int, int)); +static PTR_T internal_malloc PARAMS((size_t, const char *, int, int)); +static PTR_T internal_realloc PARAMS((PTR_T, size_t, const char *, int, int)); +static void internal_free PARAMS((PTR_T, const char *, int, int)); +static PTR_T internal_memalign PARAMS((size_t, size_t, const char *, int, int)); #ifndef NO_CALLOC -static PTR_T internal_calloc __P((size_t, size_t, const char *, int, int)); -static void internal_cfree __P((PTR_T, const char *, int, int)); +static PTR_T internal_calloc PARAMS((size_t, size_t, const char *, int, int)); +static void internal_cfree PARAMS((PTR_T, const char *, int, int)); #endif #ifndef NO_VALLOC -static PTR_T internal_valloc __P((size_t, const char *, int, int)); +static PTR_T internal_valloc PARAMS((size_t, const char *, int, int)); #endif #if defined (botch) extern void botch (); #else -static void botch __P((const char *, const char *, int)); +static void botch PARAMS((const char *, const char *, int)); #endif -static void xbotch __P((PTR_T, int, const char *, const char *, int)); +static void xbotch PARAMS((PTR_T, int, const char *, const char *, int)); #if !HAVE_DECL_SBRK extern char *sbrk (); @@ -302,7 +320,7 @@ extern char *sbrk (); #ifdef SHELL extern int interrupt_immediately, running_trap; -extern int signal_is_trapped __P((int)); +extern int signal_is_trapped PARAMS((int)); #endif #ifdef MALLOC_STATS @@ -321,8 +339,8 @@ int malloc_mmap_threshold = MMAP_THRESHOLD; char _malloc_trace_buckets[NBUCKETS]; /* These should really go into a header file. */ -extern void mtrace_alloc __P((const char *, PTR_T, size_t, const char *, int)); -extern void mtrace_free __P((PTR_T, int, const char *, int)); +extern void mtrace_alloc PARAMS((const char *, PTR_T, size_t, const char *, int)); +extern void mtrace_free PARAMS((PTR_T, int, const char *, int)); #endif #if !defined (botch) @@ -693,7 +711,7 @@ morecore (nu) memtop += sbrk_amt; - /* shouldn't happen, but just in case -- require 8-byte alignment */ + /* shouldn't happen, but just in case -- require 8- or 16-byte alignment */ if ((long)mp & MALIGN_MASK) { mp = (union mhead *) (((long)mp + MALIGN_MASK) & ~MALIGN_MASK); @@ -723,8 +741,13 @@ malloc_debug_dummy () write (1, "malloc_debug_dummy\n", 19); } +#if SIZEOF_CHAR_P == 8 +#define PREPOP_BIN 3 +#define PREPOP_SIZE 64 +#else #define PREPOP_BIN 2 #define PREPOP_SIZE 32 +#endif static int pagealign () @@ -760,8 +783,8 @@ pagealign () memtop += sbrk_needed; /* Take the memory which would otherwise be wasted and populate the most - popular bin (2 == 32 bytes) with it. Add whatever we need to curbrk - to make things 32-byte aligned, compute how many 32-byte chunks we're + popular bin (3 == 64 bytes) with it. Add whatever we need to curbrk + to make things 64-byte aligned, compute how many 64-byte chunks we're going to get, and set up the bin. */ curbrk += sbrk_needed & (PREPOP_SIZE - 1); sbrk_needed -= sbrk_needed & (PREPOP_SIZE - 1); @@ -822,7 +845,7 @@ internal_malloc (n, file, line, flags) /* get a block */ if (nbytes <= binsize(nunits)) break; - /* Silently reject too-large requests. */ + /* Silently reject too-large requests. XXX - can increase this if HAVE_MMAP */ if (nunits >= NBUCKETS) return ((PTR_T) NULL); @@ -863,6 +886,11 @@ internal_malloc (n, file, line, flags) /* get a block */ p->mh_magic2 = MAGIC2; p->mh_nbytes = n; +#if SIZEOF_CHAR_P == 8 + /* Begin guard */ + MALLOC_MEMSET ((char *)p->mh_magic8, MAGIC1, 8); +#endif + /* End guard */ mg.i = n; z = mg.s; @@ -897,6 +925,14 @@ internal_malloc (n, file, line, flags) /* get a block */ _malloc_ckwatch (p + 1, file, line, W_ALLOC, n); #endif +#if defined (MALLOC_DEBUG) + z = (char *) (p + 1); + /* Check alignment of returned pointer */ + if ((unsigned long)z & MALIGN_MASK) + fprintf (stderr, "malloc: %s:%d: warning: request for %ld bytes not aligned on %d byte boundary\r\n", + file ? file : _("unknown"), line, p->mh_nbytes, MALIGN_MASK+1); +#endif + return (PTR_T) (p + 1); } @@ -956,6 +992,15 @@ internal_free (mem, file, line, flags) if (IN_BUCKET(nbytes, nunits) == 0) xbotch (mem, ERR_UNDERFLOW, _("free: underflow detected; mh_nbytes out of range"), file, line); +#if SIZEOF_CHAR_P == 8 + { + int i; + for (i = 0, z = p->mh_magic8; i < 8; i++) + if (*z++ != MAGIC1) + xbotch (mem, ERR_UNDERFLOW, + _("free: underflow detected; magic8 corrupted"), file, line); + } +#endif ap += p->mh_nbytes; z = mg.s; @@ -1087,6 +1132,16 @@ internal_realloc (mem, n, file, line, flags) if (IN_BUCKET(nbytes, nunits) == 0) xbotch (mem, ERR_UNDERFLOW, _("realloc: underflow detected; mh_nbytes out of range"), file, line); +#if SIZEOF_CHAR_P == 8 + { + int i; + for (i = 0, z = p->mh_magic8; i < 8; i++) + if (*z++ != MAGIC1) + xbotch (mem, ERR_UNDERFLOW, + _("realloc: underflow detected; magic8 corrupted"), file, line); + + } +#endif m = (char *)mem + (tocopy = p->mh_nbytes); z = mg.s; diff --git a/lib/malloc/stats.c b/lib/malloc/stats.c index 05247970..13696dca 100644 --- a/lib/malloc/stats.c +++ b/lib/malloc/stats.c @@ -110,7 +110,7 @@ _print_malloc_stats (s, fp) if (i == malloc_mmap_threshold+1) fprintf (fp, "--------\n"); if (v.nmal > 0) - fprintf (fp, "%8lu\t%4d\t%6d\t%5d\t%8d\t%8d %5d %8d\n", (unsigned long)v.blocksize, v.nfree, v.nused, v.nmal, v.nmorecore, v.nlesscore, v.nsplit, v.ncoalesce); + fprintf (fp, "%8lu\t%4d\t%6d\t%5d%8d\t%8d %5d %8d\n", (unsigned long)v.blocksize, v.nfree, v.nused, v.nmal, v.nmorecore, v.nlesscore, v.nsplit, v.ncoalesce); totfree += v.nfree * v.blocksize; totused += v.nused * v.blocksize; } diff --git a/lib/readline/kill.c b/lib/readline/kill.c index 5366445e..285e32df 100644 --- a/lib/readline/kill.c +++ b/lib/readline/kill.c @@ -820,7 +820,10 @@ _rl_bracketed_read_mbstring (char *mb, int mlen) #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) c = _rl_read_mbstring (c, mb, mlen); + else #endif + mb[0] = c; + mb[mlen] = '\0'; /* just in case */ return c; } diff --git a/lib/readline/vi_mode.c b/lib/readline/vi_mode.c index 035fb644..47af84b7 100644 --- a/lib/readline/vi_mode.c +++ b/lib/readline/vi_mode.c @@ -2014,10 +2014,11 @@ _rl_vi_callback_change_char (_rl_callback_generic_arg *data) c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); #if defined (HANDLE_MULTIBYTE) - strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX); -#else - _rl_vi_last_replacement[0] = c; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX); + else #endif + _rl_vi_last_replacement[0] = c; _rl_vi_last_replacement[MB_LEN_MAX] = '\0'; /* XXX */ if (c < 0) @@ -2054,10 +2055,11 @@ rl_vi_change_char (int count, int key) { c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); #ifdef HANDLE_MULTIBYTE - strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX); -#else - _rl_vi_last_replacement[0] = c; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX); + else #endif + _rl_vi_last_replacement[0] = c; _rl_vi_last_replacement[MB_LEN_MAX] = '\0'; /* just in case */ } diff --git a/lib/sh/Makefile.in b/lib/sh/Makefile.in index fade8c9b..9b1c2770 100644 --- a/lib/sh/Makefile.in +++ b/lib/sh/Makefile.in @@ -2,7 +2,7 @@ # Makefile for the Bash library # # -# Copyright (C) 1998-2010 Free Software Foundation, Inc. +# Copyright (C) 1998-2020 Free Software Foundation, Inc. # 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 @@ -93,7 +93,7 @@ CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \ wcsdup.c fpurge.c zgetline.c mbscmp.c uconvert.c ufuncs.c \ casemod.c dprintf.c input_avail.c mbscasecmp.c fnxform.c \ strchrnul.c unicode.c wcswidth.c wcsnwidth.c shmbchar.c strdup.c \ - utf8.c + utf8.c random.c # The header files for this library. HSOURCES = @@ -108,7 +108,7 @@ OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.o \ fmtullong.o fmtumax.o zcatfd.o zmapfd.o winsize.o wcsdup.o \ fpurge.o zgetline.o mbscmp.o uconvert.o ufuncs.o casemod.o \ input_avail.o mbscasecmp.o fnxform.o unicode.o shmbchar.o \ - utf8.o wcsnwidth.o ${LIBOBJS} + utf8.o random.o wcsnwidth.o ${LIBOBJS} SUPPORT = Makefile @@ -170,6 +170,7 @@ netopen.o: netopen.c oslib.o: oslib.c pathcanon.o: pathcanon.c pathphys.o: pathphys.c +random.o: random.c rename.o: rename.c setlinebuf.o: setlinebuf.c shmatch.o: shmatch.c @@ -248,6 +249,7 @@ netopen.o: ${BUILD_DIR}/config.h oslib.o: ${BUILD_DIR}/config.h pathcanon.o: ${BUILD_DIR}/config.h pathphys.o: ${BUILD_DIR}/config.h +random.o: ${BUILD_DIR}/config.h rename.o: ${BUILD_DIR}/config.h setlinebuf.o: ${BUILD_DIR}/config.h shmatch.o: ${BUILD_DIR}/config.h @@ -380,6 +382,10 @@ pathphys.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h pathphys.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h #pathphys.o: ${BUILD_DIR}/version.h +random.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h +random.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h +random.o: ${BASHINCDIR}/filecntl.h + rename.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h rename.o: ${BASHINCDIR}/posixstat.h diff --git a/lib/sh/random.c b/lib/sh/random.c new file mode 100644 index 00000000..1eaa71aa --- /dev/null +++ b/lib/sh/random.c @@ -0,0 +1,240 @@ +/* random.c -- Functions for managing 16-bit and 32-bit random numbers. */ + +/* Copyright (C) 2020 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash 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. + + Bash 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 Bash. If not, see . +*/ + +#include "config.h" + +#include "bashtypes.h" + +#if defined (HAVE_SYS_RANDOM_H) +# include +#endif + +#if defined (HAVE_UNISTD_H) +# include +#endif +#include "filecntl.h" + +#include +#include "bashansi.h" + +#include "shell.h" + +extern time_t shell_start_time; + +extern int last_random_value; + +static u_bits32_t intrand32 PARAMS((u_bits32_t)); +static u_bits32_t genseed PARAMS((void)); + +static u_bits32_t brand32 PARAMS((void)); +static void sbrand32 PARAMS((u_bits32_t)); +static void perturb_rand32 PARAMS((void)); + +/* The random number seed. You can change this by setting RANDOM. */ +static u_bits32_t rseed = 1; + +/* Returns a 32-bit pseudo-random number. */ +static u_bits32_t +intrand32 (last) + u_bits32_t last; +{ + /* Minimal Standard generator from + "Random number generators: good ones are hard to find", + Park and Miller, Communications of the ACM, vol. 31, no. 10, + October 1988, p. 1195. Filtered through FreeBSD. + + x(n+1) = 16807 * x(n) mod (m). + + We split up the calculations to avoid overflow. + + h = last / q; l = x - h * q; t = a * l - h * r + m = 2147483647, a = 16807, q = 127773, r = 2836 + + There are lots of other combinations of constants to use; look at + https://www.gnu.org/software/gsl/manual/html_node/Other-random-number-generators.html#Other-random-number-generators */ + + bits32_t h, l, t; + u_bits32_t ret; + + /* Can't seed with 0. */ + ret = (last == 0) ? 123459876 : last; + h = ret / 127773; + l = ret - (127773 * h); + t = 16807 * l - 2836 * h; + ret = (t < 0) ? t + 0x7fffffff : t; + + return (ret); +} + +static u_bits32_t +genseed () +{ + struct timeval tv; + u_bits32_t iv; + + gettimeofday (&tv, NULL); + iv = (u_bits32_t)seedrand; /* let the compiler truncate */ + iv = tv.tv_sec ^ tv.tv_usec ^ getpid () ^ getppid () ^ current_user.uid ^ iv; + return (iv); +} + +#define BASH_RAND_MAX 32767 /* 0x7fff - 16 bits */ + +/* Returns a pseudo-random number between 0 and 32767. */ +int +brand () +{ + unsigned int ret; + + rseed = intrand32 (rseed); + if (shell_compatibility_level > 50) + ret = (rseed >> 16) ^ (rseed & 65535); + else + ret = rseed; + return (ret & BASH_RAND_MAX); +} + +/* Set the random number generator seed to SEED. */ +void +sbrand (seed) + unsigned long seed; +{ + rseed = seed; + last_random_value = 0; +} + +void +seedrand () +{ + u_bits32_t iv; + + iv = genseed (); + sbrand (iv); +} + +static u_bits32_t rseed32 = 1073741823; +static int last_rand32; + +static int urandfd = -1; + +#define BASH_RAND32_MAX 0x7fffffff /* 32 bits */ + +/* Returns a 32-bit pseudo-random number between 0 and 4294967295. */ +static u_bits32_t +brand32 () +{ + u_bits32_t ret; + + rseed32 = intrand32 (rseed32); + return (rseed32 & BASH_RAND32_MAX); +} + +static void +sbrand32 (seed) + u_bits32_t seed; +{ + last_rand32 = rseed32 = seed; +} + +void +seedrand32 () +{ + u_bits32_t iv; + + iv = genseed (); + sbrand32 (iv); +} + +static void +perturb_rand32 () +{ + rseed32 ^= genseed (); +} + +/* Force another attempt to open /dev/urandom on the next call to get_urandom32 */ +void +urandom_close () +{ + if (urandfd >= 0) + close (urandfd); + urandfd = -1; +} + +#if !defined (HAVE_GETRANDOM) +/* Imperfect emulation of getrandom(2). */ +#ifndef GRND_NONBLOCK +# define GRND_NONBLOCK 1 +# define GRND_RANDOM 2 +#endif + +static ssize_t +getrandom (buf, len, flags) + void *buf; + size_t len; + unsigned int flags; +{ + int oflags; + ssize_t r; + static int urand_unavail = 0; + +#if HAVE_GETENTROPY + r = getentropy (buf, len); + return (r == 0) ? len : -1; +#endif + + if (urandfd == -1 && urand_unavail == 0) + { + oflags = O_RDONLY; + if (flags & GRND_NONBLOCK) + oflags |= O_NONBLOCK; + urandfd = open ("/dev/urandom", oflags, 0); + if (urandfd >= 0) + SET_CLOSE_ON_EXEC (urandfd); + else + { + urand_unavail = 1; + return -1; + } + } + if (urandfd >= 0 && (r = read (urandfd, buf, len)) == len) + return (r); + return -1; +} +#endif + +u_bits32_t +get_urandom32 () +{ + u_bits32_t ret; + + if (getrandom ((void *)&ret, sizeof (ret), GRND_NONBLOCK) == sizeof (ret)) + return (last_rand32 = ret); + +#if defined (HAVE_ARC4RANDOM) + ret = arc4random (); +#else + if (subshell_environment) + perturb_rand32 (); + do + ret = brand32 (); + while (ret == last_rand32); +#endif + return (last_rand32 = ret); +} diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 0b063810..c8bef8dd 100755 --- a/tests/RUN-ONE-TEST +++ b/tests/RUN-ONE-TEST @@ -1,4 +1,4 @@ -BUILD_DIR=/usr/local/build/chet/bash/bash-current +BUILD_DIR=/usr/local/build/bash/bash-current THIS_SH=$BUILD_DIR/bash PATH=$PATH:$BUILD_DIR diff --git a/tests/arith5.sub b/tests/arith5.sub index 26ae600b..7d5c7799 100644 --- a/tests/arith5.sub +++ b/tests/arith5.sub @@ -11,6 +11,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # +# a lot of this is technically undefined behavior due to signed 64-bit +# integer overflow, but we're testing exception handling here + intmax_max=$((2**63 - 1)) intmax_min1=$((2**63)) intmax_min2=$((-2**63)) diff --git a/tests/history.right b/tests/history.right index 2c40731c..74eb91bc 100644 --- a/tests/history.right +++ b/tests/history.right @@ -140,9 +140,9 @@ three one two three -5.0 +5.1 echo ${BASH_VERSION%\.*} -5.0 +5.1 echo ${BASH_VERSION%\.*} a b diff --git a/tests/new-exp.right b/tests/new-exp.right index 7083303d..d584ccd3 100644 --- a/tests/new-exp.right +++ b/tests/new-exp.right @@ -624,7 +624,7 @@ c Sub = 0 2 4 8 <'ab cd'> <'4'> <'ab cd'> <> -argv[1] = +argv[1] = < > <' \t\n'> diff --git a/variables.c b/variables.c index d529a319..4fcdaea0 100644 --- a/variables.c +++ b/variables.c @@ -32,10 +32,6 @@ # endif /* !__QNXNTO__ */ #endif /* __QNX__ */ -#if defined (HAVE_SYS_RANDOM_H) -# include -#endif - #if defined (HAVE_UNISTD_H) # include #endif @@ -206,19 +202,6 @@ static SHELL_VAR *assign_seconds PARAMS((SHELL_VAR *, char *, arrayind_t, char * static SHELL_VAR *get_seconds PARAMS((SHELL_VAR *)); static SHELL_VAR *init_seconds_var PARAMS((void)); -static u_bits32_t intrand32 PARAMS((u_bits32_t)); -static u_bits32_t genseed PARAMS((void)); - -static int brand PARAMS((void)); -static void sbrand PARAMS((unsigned long)); /* set bash random number generator. */ -static void seedrand PARAMS((void)); /* seed generator randomly */ - -static u_bits32_t brand32 PARAMS((void)); -static void sbrand32 PARAMS((u_bits32_t)); -static void seedrand32 PARAMS((void)); -static void perturb_rand32 PARAMS((void)); -static u_bits32_t get_urandom32 PARAMS((void)); - static SHELL_VAR *assign_random PARAMS((SHELL_VAR *, char *, arrayind_t, char *)); static SHELL_VAR *get_random PARAMS((SHELL_VAR *)); @@ -1348,201 +1331,12 @@ init_seconds_var () INIT_DYNAMIC_VAR ("SECONDS", (v ? value_cell (v) : (char *)NULL), get_seconds, assign_seconds); return v; } - -/* The random number seed. You can change this by setting RANDOM. */ -static u_bits32_t rseed = 1; -static int last_random_value; + +/* Functions for $RANDOM and $SRANDOM */ + +int last_random_value; static int seeded_subshell = 0; -/* Returns a 32-bit pseudo-random number. */ -static u_bits32_t -intrand32 (last) - u_bits32_t last; -{ - /* Minimal Standard generator from - "Random number generators: good ones are hard to find", - Park and Miller, Communications of the ACM, vol. 31, no. 10, - October 1988, p. 1195. filtered through FreeBSD. - - x(n+1) = 16807 * x(n) mod (2**31 - 1). - - We split up the calculations to avoid overflow. - - h = last / q; l = x - h * q; t = a * l - h * r - m = 2147483647, a = 16807, q = 127773, r = 2836 - - There are lots of other combinations of constants to use; look at - https://www.gnu.org/software/gsl/manual/html_node/Other-random-number-generators.html#Other-random-number-generators */ - - bits32_t h, l, t; - u_bits32_t ret; - - /* Can't seed with 0. */ - ret = (last == 0) ? 123459876 : last; - h = ret / 127773; - l = ret - (127773 * h); - t = 16807 * l - 2836 * h; - ret = (t < 0) ? t + 0x7fffffff : t; - - return (ret); -} - -static u_bits32_t -genseed () -{ - struct timeval tv; - u_bits32_t iv; - - gettimeofday (&tv, NULL); - iv = (u_bits32_t)seedrand; /* let the compiler truncate */ - iv = tv.tv_sec ^ tv.tv_usec ^ getpid () ^ getppid () ^ current_user.uid ^ iv; - return (iv); -} - -#define BASH_RAND_MAX 32767 /* 0x7fff - 16 bits */ - -/* Returns a pseudo-random number between 0 and 32767. */ -static int -brand () -{ - unsigned int ret; - - rseed = intrand32 (rseed); - if (shell_compatibility_level > 50) - ret = (rseed >> 16) ^ (rseed & 65535); - else - ret = rseed; - return (ret & BASH_RAND_MAX); -} - -/* Set the random number generator seed to SEED. */ -static void -sbrand (seed) - unsigned long seed; -{ - rseed = seed; - last_random_value = 0; -} - -static void -seedrand () -{ - u_bits32_t iv; - - iv = genseed (); - sbrand (iv); -} - -static u_bits32_t rseed32 = 1073741823; -static int last_rand32; - -static int urandfd = -1; - -#define BASH_RAND32_MAX 0x7fffffff /* 32 bits */ - -/* Returns a 32-bit pseudo-random number between 0 and 4294967295. */ -static u_bits32_t -brand32 () -{ - u_bits32_t ret; - - rseed32 = intrand32 (rseed32); - return (rseed32 & BASH_RAND32_MAX); -} - -static void -sbrand32 (seed) - u_bits32_t seed; -{ - last_rand32 = rseed32 = seed; -} - -static void -seedrand32 () -{ - u_bits32_t iv; - - iv = genseed (); - sbrand32 (iv); -} - -static void -perturb_rand32 () -{ - rseed32 ^= genseed (); -} - -/* Force another attempt to open /dev/urandom on the next call to get_urandom32 */ -void -urandom_close () -{ - if (urandfd >= 0) - close (urandfd); - urandfd = -1; -} - -#if !defined (HAVE_GETRANDOM) -/* Imperfect emulation of getrandom(2). */ -#ifndef GRND_NONBLOCK -# define GRND_NONBLOCK 1 -# define GRND_RANDOM 2 -#endif - -static ssize_t -getrandom (buf, len, flags) - void *buf; - size_t len; - unsigned int flags; -{ - int oflags; - ssize_t r; - static int urand_unavail = 0; - -#if HAVE_GETENTROPY - r = getentropy (buf, len); - return (r == 0) ? len : -1; -#endif - - if (urandfd == -1 && urand_unavail == 0) - { - oflags = O_RDONLY; - if (flags & GRND_NONBLOCK) - oflags |= O_NONBLOCK; - urandfd = open ("/dev/urandom", oflags, 0); - if (urandfd >= 0) - SET_CLOSE_ON_EXEC (urandfd); - else - { - urand_unavail = 1; - return -1; - } - } - if (urandfd >= 0 && (r = read (urandfd, buf, len)) == len) - return (r); - return -1; -} -#endif - -static u_bits32_t -get_urandom32 () -{ - u_bits32_t ret; - - if (getrandom ((void *)&ret, sizeof (ret), GRND_NONBLOCK) == sizeof (ret)) - return (last_rand32 = ret); - -#if defined (HAVE_ARC4RANDOM) - ret = arc4random (); -#else - if (subshell_environment) - perturb_rand32 (); - do - ret = brand32 (); - while (ret == last_rand32); -#endif - return (last_rand32 = ret); -} - static SHELL_VAR * assign_random (self, value, unused, key) SHELL_VAR *self;