diff --git a/sys/kern/imgact_shell.c b/sys/kern/imgact_shell.c --- a/sys/kern/imgact_shell.c +++ b/sys/kern/imgact_shell.c @@ -123,10 +123,25 @@ bcopy(imgp->args->begin_argv + length, imgp->args->begin_argv + offset, imgp->args->endp - (imgp->args->begin_argv + length)); - offset -= length; /* calculate actual adjustment */ - imgp->args->begin_envv += offset; - imgp->args->endp += offset; - imgp->args->space -= offset; + /* + * Calculate the actual pointer/space adjustment without relying on + * size_t modular wrap when offset < length (which happens whenever + * argv[0] is longer than the interpreter tokens + fname). Handle + * the grow (offset >= length) and shrink (offset < length) cases + * explicitly so the intent is obvious and unsigned underflow cannot + * confuse readers or static analyzers. + */ + if (offset >= length) { + size_t grow = offset - length; + imgp->args->begin_envv += grow; + imgp->args->endp += grow; + imgp->args->space -= (int)grow; + } else { + size_t shrink = length - offset; + imgp->args->begin_envv -= shrink; + imgp->args->endp -= shrink; + imgp->args->space += (int)shrink; + } /* decr argc remove old argv[0], incr argc for fname add, net 0 */ /*