I am (soon -- perhaps it will have happened before you read this for some of you) going to commit changes to /bin/sh to (finally!) get rid of internal uses of atoi() - completely.
Mostly this will have no visible effect, but there may be a few places where sh will now report a "number out of range" instead of silently truncating it to 32 bits, eg: "shift 4294967297" will now be an error, instead of the same as "shift 1" (and the same for several other builtin commands that take a numeric argument). (We already fixed a bug a while ago where ${4294967297} used to treated the same as ${1}, nothing is altering there, that will remain valid, and most likely produce an (unset) null string as its value, unless you can work out a way to actually set that many args. Note that none of this affects shell arithmetic $(( )) which continues to operate on intmax_t integral types, and is not affected at all (it has not used atoi() in a very long time, if it ever did.) Most likely the one place where a script might fall over because of this change is if it happens to have break NNNNNNNNNNNNN where N...N is a > 31 bit number, where the intent was to simply break out of every possible enclosing loop, but the programmer (script writer) was too lazy to work out how many there might be, so simply wrote something huge. (Same for "continue" of course.) That will no longer work if "huge" is too big, keep it under 2^31 and all should still function just the same. One other thing that was affected, just as shift 4294967297 is no longer an alias for "shift 1", the same is true for OPTIND=4294967297 which used to be treated the same as OPTIND=1 and do a reset on the argument list for getopts(). But as well as no longer silently truncating this way, another bug in the handling of OPTIND is being fixed (a side effect needed because of the other changes) - it will no longer be an error to assign a non-number to OPTIND. Doing so won't accomplish anything useful, but in sh, OPTIND is just a variable like any other, and it should be possible to assign anything you like to it. That will now work as it should (ie: no "number out of range" here). What is undefined (in POSIX) in this area, is calling getopts after setting OPTIND to anything other than 1. For our /bin/sh the posix undefined behaviour will be implemented to be to simply ignore the invalid setting of OPTIND. Set it to 1 and the arg list is reset, set it to anything else, and it gets set, but has no other effect. getopts will continue to set OPTIND as it is defined to do, whatever the script (or you) set it to before calling getopts. (Note "1" here is implmented as any unsigned decimal integer which has the same value as 1, so 001 etc will work as well, +1 will not.) Also, in this area, the shell is supposed to initialize OPTIND to 1 when it starts. /bin/sh did that, but allowed an OPTIND in the environment to override that. That will no longer happen, whatever the environment contains when sh starts, OPTIND will start at 1. If anyone notices any untoward effects from these changes, after they have been committed, please let me know, or file a PR. kre ps: this was inspired by seeing bug reports about another shell which could actually be made to core dump by giving it large enough integer parameters in "appropriate" commands - I am not aware of any /bin/sh bugs that drastic, but I thought it time to fix the integer parsing code once and for all.