Let’s try a simple script testing the upper bound of signed long integers with various implementations of the POSIX shell:
$ chmod +x overflow.sh
$ cat overflow.sh
echo $(( 9223372036854775807 ))
echo $(( 9223372036854775808 ))
echo $(( 9223372036854775808 + 1 ))
Tested on OpenBSD 6.8.
$ ksh ./overflow.sh
9223372036854775807
-9223372036854775808
-9223372036854775807
All is well, nothing to see here.
Tested with bash 5.0.17 on Ubuntu 20.04 and bash 5.1.4 on OpenBSD 6.8.
$ bash ./overflow.sh
9223372036854775807
-9223372036854775808
-9223372036854775807
All is well, nothing to see here.
Tested with dash 0.5.11.2 on OpenBSD 6.8.
$ dash ./overflow.sh
9223372036854775807
9223372036854775807
-9223372036854775808
There is a small overflow bug here as 9223372036854775807 and 9223372036854775808 are considered equals. Oops.
Tested with zsh 5.8 on OpenBSD 6.8.
$ zsh ./overflow.sh
9223372036854775807
./overflow.sh:2: number truncated after 18 digits: 9223372036854775808
922337203685477580
./overflow.sh:3: number truncated after 18 digits: 9223372036854775808 + 1
922337203685477581
This bug is strange as 9223372036854775807 is actually 20 digits long and this fact doesn’t bother zsh that much, so both the truncation and the error message have bugs too.
Tested with mksh 58-1 on Ubuntu 20.04.
This is the MirBSD version of the Korn shell, a very interesting implementation to test as it is the default for Android.
$ mksh ./overflow.sh
-1
0
1
Surprising? The answer is easy: contrary to the POSIX specification mksh implements integers as signed int instead of signed long. Its overflow point is thus the much more closer 2147483648 instead of 9223372036854775808.
Tested with yash 2.49 on OpenBSD 6.8.
yash is a lesser known shell from Japan with a lot of very good features but the strange decision of implementing arrays with 1-based index instead of 0-based like everyone else, making it a portability nightmare.
$ yash ./overflow.sh
9223372036854775807
9.22337203685478e+18
9.22337203685478e+18
But overflows don’t kill yash :)
As I was already able to witness with kbf relying on “big” numbers in shell is not portable. If safety is needed, only assumes signed int.
Of course if you are finding yourself in a situation where this page and advice are of serious help you are probably not using the most suitable programming language.