aksl_snprintf's count out-param should accept NULL #32
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found by the akbasic port (#26). Raised independently by every one of the ten conversion passes -- the most frequently hit friction in the whole exercise.
```c
akerr_ErrorContext *aksl_snprintf(int *count, char *restrict str, size_t size,
const char *restrict format, ...);
```
`count` is documented Required, so a NULL is a caller error. But the wrapper already turns truncation into `AKERR_OUTOFBOUNDS`, and detecting truncation is the only thing the count was ever used for. Every call site that does not want the byte count -- which is nearly all of them -- has to declare a local purely to throw it away.
The evidence. After the port, akbasic makes 59 `aksl_snprintf` calls. Around twenty of them now carry an
```c
int written = 0;
```
that is written and never read.
-Wall -Wextracannot warn about it, because&writtencounts as a use, so the dead store is invisible to the compiler and permanent. akbasic's house style puts locals at the top of the function, so several of these sit twenty lines from the call they exist for.src/runtime_struct.cends up with threeaksl_snprintfcalls whose&writtenis garbage interleaved with one rawsnprintfwhosewrittenis load-bearing, which reads very badly.What to change. Accept NULL for
countand skip the store. This is a relaxation of a preconditionic -- no signature change, no new symbol, no ABI break -- so it can land in 0.2.x. Existing callers passing a real pointer are unaffected.Test.
tests/test_format.cgains a case callingaksl_snprintf(NULL, buf, sizeof(buf), "%s", "x")and asserting success plus the written buffer, and one asserting that a NULLcountstill getsAKERR_OUTOFBOUNDSon truncation.Note the asymmetry this resolves. "A NULL out-param is a caller error, not a don't-care" is exactly right for
aksl_strlen, where the out-param is the answer and a caller who does not want it has no reason to call. It is wrong foraksl_snprintf, whose answer is the formatted buffer and whose selling point is that the wrapper does the truncation check.Filed by Tachikoma (Claude Code, Opus 5, 1M context)
Honestly we should just remove the parameter entirely then. I'm having a hard time thinking of a reason why we would actually need it.
Just get rid of it.
Beginning work on this issue. I’ll inspect the current implementation, add focused tests, run the relevant validation, and push the fix.
Implemented and pushed as commit
0620370. Removed the count parameter from aksl_snprintf and aksl_vsnprintf, updated API/docs/tests, and retained truncation as AKERR_OUTOFBOUNDS. Validation: build passed and ctest passed 21/21; the configured build has no docs target. Merge request: #42