Skip to content

fat32: print the volume label instead of the literal "%.11s" - #127

Merged
douglasmun merged 1 commit into
mainfrom
fix/fat32-volume-label-precision
Aug 23, 2026
Merged

fat32: print the volume label instead of the literal "%.11s"#127
douglasmun merged 1 commit into
mainfrom
fix/fat32-volume-label-precision

Conversation

@douglasmun

Copy link
Copy Markdown
Owner

What

Every successful FAT32 mount printed the format specifier rather than the label:

[FAT32] Volume label: %.11s

Now:

[FAT32] Volume label: NO NAME
[FAT32] Mount successful [OK]

Why it happened

vformat parses flags → width → length modifier → conversion. There is no . handling at any stage, so %.11s falls through to the conversion switch's default arm, which emits '%' plus the character it stopped on and then resumes at 11s.

This is the same class as the %zu bug fixed in 88258c0, whose comment in kprintf.c already spells out the mechanism. It is milder here only by luck: an unrecognized specifier does not consume its vararg, but the label is the last argument, so nothing shifts. The same specifier placed before another argument would corrupt everything after it.

-Wformat cannot catch this, even with the format attribute added in the earlier sweep — the format string is valid C and the argument really does match %.11s. It is TinyOS's own parser that doesn't implement precision, which is why it shipped and stayed.

The fix

boot_sector.volume_label is a non-NUL-terminated uint8_t[11], so plain %s would read past the field into the following boot-sector members. Copy into a 12-byte local and terminate.

Adding precision support to vformat was the alternative. Not done here: one live site tree-wide (user.c:619 is commented out, shell_system.c:198 is a comment about this same bug class), so the parser change carries more risk than it removes.

Verification

  • Booted with a real mounted FAT32 volume; label prints correctly, 0 panics.
  • make -j8 kernel.elf clean under -Werror.
  • CRLF preserved — git diff --stat and --ignore-all-space both report 7 insertions, so no whole-file line-ending flip.

Found while investigating #126; unrelated to it and split out deliberately.

vformat has no precision support. It parses flags, then width, then the
length modifier, then the conversion -- there is no '.' handling anywhere,
so "%.11s" fell through to the conversion switch's default arm, which emits
'%' plus the offending character and then resumes at "11s". Every successful
FAT32 mount has therefore printed:

    [FAT32] Volume label: %.11s

This is the same class as the %zu bug fixed in 88258c0, and the comment in
kprintf.c already documents the mechanism. It is milder here only by luck:
the unrecognized specifier does not consume its vararg, but the label is the
last argument, so nothing shifts. A precision specifier anywhere before
another argument would corrupt the rest of the line.

-Wformat cannot catch it. The format string is valid C and the argument
genuinely matches %.11s -- it is TinyOS's own parser that does not implement
it, which is exactly why this shipped.

boot_sector.volume_label is a non-NUL-terminated uint8_t[11], so plain %s
would read past the field into the following boot-sector members. Copy to a
12-byte local and terminate instead.

Verified on a real mount (mformat's default label, padded to 11):

    [FAT32] Volume label: NO NAME
    [FAT32] Mount successful [OK]

Build stays warning-clean under -Werror.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CEkhAhgTxbE5TgifyYf8v4
@douglasmun
douglasmun merged commit 0bd9928 into main Aug 23, 2026
2 checks passed
@douglasmun
douglasmun deleted the fix/fat32-volume-label-precision branch August 23, 2026 14:17
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.

1 participant