Skip to content

fix(shell): one-past-the-end write in argv array when a command has MAX_CMD_ARGS tokens - #112

Merged
im-nymii merged 1 commit into
Auri-OS:developfrom
kudasaixc:hotfix/shell-argv-overflow
Jul 24, 2026
Merged

fix(shell): one-past-the-end write in argv array when a command has MAX_CMD_ARGS tokens#112
im-nymii merged 1 commit into
Auri-OS:developfrom
kudasaixc:hotfix/shell-argv-overflow

Conversation

@kudasaixc

@kudasaixc kudasaixc commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

When a command line has 16 or more space-separated tokens, shell_parse writes one pointer past the end of the args array on the stack.

shell_execute declares the array with exactly MAX_CMD_ARGS slots:

char *args[MAX_CMD_ARGS];   // 16 slots, indices 0..15
int argc = shell_parse(cmd, args);

shell_parse fills args[0..15] and then always writes the NULL sentinel at args[argc]:

while (cmd[i] != '\0' && argc < MAX_CMD_ARGS) {  // argc can reach 16
    args[argc++] = &cmd[i];
    ...
}
args[argc] = NULL;   // argc == 16 -> writes args[16], past the array

So a line of 16 words makes argc reach 16 and args[16] = NULL writes 4 bytes past the array. It's reachable from normal keyboard input, and the tree builds with -fno-stack-protector. It's undefined behaviour; whether it does anything visible depends on the stack layout (see the note below, I could not get it to actually crash on the current toolchain).

Fix is to size the array for the NULL terminator, like a normal argv:

char *args[MAX_CMD_ARGS + 1];

No behaviour change for valid input.

shell_execute declares `char *args[MAX_CMD_ARGS]` (16 slots) but
shell_parse fills args[0..15] and then writes args[argc] = NULL. With
16+ whitespace-separated tokens argc reaches 16, so the NULL is written
to args[16] -- one pointer past the end of the on-stack array,
corrupting the adjacent stack slot. This is reachable from any keyboard
input, e.g. a line of 16 words. Size the array MAX_CMD_ARGS + 1 to hold
the argv-style NULL sentinel.
@kudasaixc

kudasaixc commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Small runtime note, I built this locally with the same setup as CI (Zig 0.16.0 + NASM, the USE_ZIG=1 path) and ran it in QEMU with AURI_TEST_MODE.

With the fix, a 16-token command (echo + 15 args, so argc == 16) is handled cleanly and the shell keeps working:

root@auri-os~$ echo a a a a a a a a a a a a a a a
a a a a a a a a a a a a a a a
root@auri-os~$ uptime -s
7s

On the unfixed build the same command did not crash either. The write is always exactly one slot (argc is capped at MAX_CMD_ARGS, so it's always args[16] = NULL), and with the current GCC/Zig stack layout that slot happens to land on harmless padding.

So to be straight about it: it's a real one-past-the-end write (undefined behaviour, and the tree builds with -fno-stack-protector), worth fixing as hardening, but I couldn't get it to actually crash on the current toolchain. So it's a latent defect, not a live crash. The fix stays a safe one-liner (args[MAX_CMD_ARGS + 1]).

@kudasaixc kudasaixc changed the title fix(shell): stack overflow when a command has MAX_CMD_ARGS tokens fix(shell): one-past-the-end write in argv array when a command has MAX_CMD_ARGS tokens Jul 4, 2026
@im-nymii

Copy link
Copy Markdown
Member

LGTM

@im-nymii
im-nymii merged commit 81084a9 into Auri-OS:develop Jul 24, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants