This fixes two bugs: 1. The example 'mkdir' builtin, examples/loadables/mkdir.c, has a broken '-m' option that doesn't accept sticky/setuid/setgid.
$ ./bash -c '(cd examples/loadables && make mkdir) && enable -f examples/loadables/mkdir mkdir && mkdir -m2775 foo' ['make' output skipped] ./bash: line 2: mkdir: invalid file mode: 2775 2. The 'umask' builtin doesn't accept modes > 0777. $ ./bash -c 'umask 7777' ./bash: line 0: umask: 7777: octal number out of range While POSIX says the effect of specifying sticky/setuid/setgid bits is unspecified[*], the 'umask' builtin should still accept these bits, as it does in every other shell. It is also not consistent as bash will happily inherit an umask of 7777 from another process. For example: $ ksh -c 'umask 7777; bash -c "umask"' 7777 This is on MacOS and the BSDs; Linux seems to clear the first 8 bits at the kernel level, so '0777' is output. That is a Linux-specific constraint, though, and bash should still not accept through one route what it rejects through another. Patch: diff --git a/builtins/common.c b/builtins/common.c index a5f2584..0752f0d 100644 --- a/builtins/common.c +++ b/builtins/common.c @@ -537,7 +537,7 @@ read_octal (string) { digits++; result = (result * 8) + (*string++ - '0'); - if (result > 0777) + if (result > 07777) return -1; } By the way, why does that function repeatedly check the bounds for every digit? Wouldn't this be more efficient: diff --git a/builtins/common.c b/builtins/common.c index a5f2584..6f1273f 100644 --- a/builtins/common.c +++ b/builtins/common.c @@ -537,11 +537,9 @@ read_octal (string) { digits++; result = (result * 8) + (*string++ - '0'); - if (result > 0777) - return -1; } - if (digits == 0 || *string) + if (digits == 0 || *string || result > 07777) result = -1; return (result); Note: parse.y also uses read_octal() for $PS1, but it enforces a three-character limit, so it's inherently limited to octal 777 and the bounds check change in read_octal() doesn't affect it. I cannot find any other uses of read_octal(). Thanks, - M.