summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKerin Millar <kfm@plushkava.net>2024-08-07 18:45:02 +0100
committerSam James <sam@gentoo.org>2024-08-11 11:10:57 +0100
commit2500778920f533c56fa55798ec8d381276ae84d1 (patch)
treeb7596fe43d711ecc1f3aa0a5f1fd245964c17d6f /functions.sh
parenttest-functions: check numerical bounds with awk in test_srandom() (diff)
downloadgentoo-functions-2500778920f533c56fa55798ec8d381276ae84d1.tar.gz
gentoo-functions-2500778920f533c56fa55798ec8d381276ae84d1.tar.bz2
gentoo-functions-2500778920f533c56fa55798ec8d381276ae84d1.zip
Have srandom() employ an upper bound of 2^31-1
In the case of some shells - mksh, at least - the maximum value of an integer is 2147483647. Such is a consequence of implementing integers as signed int rather than signed long, even though doing so contravenes the specification. Reduce the output range of srandom() so as to be between 0 and 2147483647, rather than 0 and 4294967295. A change of this scope would normally justify incrementing GENFUN_API_LEVEL but I shall not do so on this occasion. My rationale is that >=gentoo-functions-1.7 has not yet had enough exposure for srandom() to be in use by other projects. Additionally, have test-functions test srandom() 10 times instead of 5. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
Diffstat (limited to 'functions.sh')
-rw-r--r--functions.sh42
1 files changed, 37 insertions, 5 deletions
diff --git a/functions.sh b/functions.sh
index b591acb..1c55b3d 100644
--- a/functions.sh
+++ b/functions.sh
@@ -463,7 +463,10 @@ quote_args()
}
#
-# Generates a random uint32 with the assistance of the kernel CSPRNG.
+# Generates a random number between 0 and 2147483647 (2^31-1) with the
+# assistance of the kernel CSPRNG. Upon success, the number shall be printed to
+# the standard output along with a trailing <newline>. Otherwise, the return
+# value shall be greater than 0.
#
srandom()
{
@@ -471,14 +474,43 @@ srandom()
if [ "${BASH_VERSINFO:-0}" -ge 5 ]; then
srandom()
{
- printf '%d\n' "${SRANDOM}"
+ printf '%d\n' "$(( SRANDOM >> 1 ))"
+ }
+ elif [ -c /dev/urandom ] && [ "$(( 1 << 31 == -2147483648 ))" -eq 1 ]; then
+ # The shell implements integers as signed int rather than signed
+ # long, contrary to the specification. Therefore, bit shifting
+ # cannot be a viable strategy. Instead, use awk to generate a
+ # number that is immediately within range.
+ srandom()
+ {
+ local hex
+
+ hex=$(
+ LC_ALL=
+ LC_CTYPE=C
+ od -vAn -N256 -tx1 /dev/urandom | awk '
+ {
+ gsub(/[[:space:]]/, "")
+ hex = hex $0
+ }
+ END {
+ if (match(hex, /[0-7][[:xdigit:]]{7}/)) {
+ print substr(hex, RSTART, RLENGTH)
+ } else {
+ exit 1
+ }
+ }
+ '
+ ) &&
+ printf '%d\n' "0x${hex}"
}
elif [ -c /dev/urandom ]; then
srandom()
{
- printf '%d\n' "0x$(
- LC_ALL=C od -vAn -N4 -tx1 /dev/urandom | tr -d '[:space:]'
- )"
+ local hex
+
+ hex=$(LC_ALL=C od -vAn -N4 -tx1 /dev/urandom | tr -d '[:space:]')
+ [ "${hex}" ] && printf '%d\n' "$(( 0x${hex} >> 1 ))"
}
else
warn "srandom: /dev/urandom doesn't exist as a character device"