fix(printf): implement %n; report C-library conversion failures like bash - #674
Merged
Conversation
…bash Two format-string mismatches with bash (issue #665): - %n previously printed the literal spec and consumed no argument. It now binds the named variable to the byte count written so far in the CURRENT format pass (bash zeroes tw on every reuse of the format string). A missing or empty name is ignored; an invalid identifier reports `NAME': not a valid identifier and stops processing with status 1, still writing the accumulated output; a failed binding (readonly) reports through Shell::set without changing the status. Namerefs are followed, and -v buffers count the same way. - A conversion snprintf refuses (a field width past INT_MAX on glibc is EOVERFLOW; an unallocatable buffer is ENOMEM) previously kept processing, printed a hardcoded macOS message at the end, and threw ALL output away. bash's PF macro stops immediately, reports strerror (errno) and still writes what was accumulated -- gnash now does the same. Verified byte-identical with bash 5.3.15 on 14 %n cases (mid-format stop, format reuse, -v interplay, namerefs, readonly, array-element and other invalid names) plus width/precision/%q/%f/%(fmt)T regression cases; printf.tests scoreboard improves 393 -> 388 diff lines with the %n mismatches gone. Closes #665
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the two
bi_printfmismatches from #665.%n
Previously printed the literal spec and consumed no argument. Now, matching bash's
printf.defcase 'n':twcounter on every reuse of the format string, soprintf 'ab%n' u v w xsets each variable to 2a[0]) reportsprintf: `NAME': not a valid identifierand stops immediately with status 1, still writing the accumulated output (printf 'ab%ncd' 0printsab)Shell::setbut leaves the exit status 0, as bash does; namerefs are followedprintf -v out 'ab%n' ucounts bytes in the-vbuffer the same wayC-library conversion failures
When
snprintfrefuses a conversion (field width pastINT_MAXisEOVERFLOWon glibc; an unallocatable buffer isENOMEM), gnash kept processing, printed a hardcoded macOS-flavored message at the end, and threw all output away. bash'sPFmacro stops immediately, reportsstrerror(errno), and still writes what was accumulated — gnash now does the same. (On macOS libc the huge-width case never fails —printf '%200000000000000000000s' xprintsx/exit 0 in both shells — so this path mainly aligns Linux behavior.)Verification
Byte-identical stdout/stderr/exit vs reference bash 5.3.15 on 14
%ncases (mid-format stop, format reuse,-vinterplay, nameref, readonly, array-element and other invalid names,%5n) plus width/precision/%q/%5.2f/%(fmt)Tregression cases.printf.testsscoreboard improves 393 → 388 diff lines (the %n mismatches are gone; remaining diffs are pre-existing option-parsing,-vvalidation and%.*sstar-width gaps).smoke.testspasses.Closes #665
🤖 Generated with Claude Code