Repository navigation
main: refuse to write the output into the input file - #428
woahwhattheheck wants to merge 8 commits into
Conversation
"scrypt enc secret.txt secret.txt" opens secret.txt for reading, reads a passphrase, then opens the same path with fopen(..., "wb"), which truncates it. scryptenc_file() then reads from the now-empty file, gets EOF on the first fread(), writes a valid 128-byte scrypt file containing an encryption of no data, and returns SCRYPT_OK; scrypt exits 0. The file the user asked to encrypt is gone, with no error and nothing to indicate that anything went wrong. "scrypt dec f f" destroys the ciphertext the same way, and both are also reachable with the input on stdin, e.g. "scrypt enc - f < f". Compare the open input file and the output path with fstat() and stat() before opening the output, and exit with an error if they are the same regular file. Devices are excluded: opening /dev/null for writing discards nothing. The check runs before the passphrase is read, so the user is not asked to type a passphrase for a command which cannot succeed. Add tests/12-same-file.sh, and document the restriction in scrypt.1.
The previous commit was uploaded through the GitHub API by a helper which dropped the final newline of every text file it sent. Rewrite those files with their trailing newline intact; no other change.
Add the authored static-alias and independent-file regression coverage to the existing test scenario. Preserve the application implementation and existing upstream submission.
|
Head |
|
Maintainer review / bounty-classification request for #428 (fixes first-reporter report #427). The reported behavior is destructive: |
The existing same-file guard only runs for a named output path. Append-redirected standard output can therefore write back into the input, for both enc and dec and with a named input or stdin. Compare the open stdout descriptor when no output path is supplied. Reuse the existing regular/block-device identity policy, retain named-output race protection, and keep character devices such as /dev/null valid. Extend the maintained same-file scenario with four bounded stdout cases and document the limit that a shell may already have truncated a file before scrypt starts. Actual CLI before/after: https://github.com/woahwhattheheck/scrypt/actions/runs/37202941771/job/111438168445 Standard Ubuntu 24.04.5, GCC 13.3.0, -std=c99 -O2 -Wall -Wextra; compile parent and candidate. Parent 14db0e0 exits 0 and changes the input in all four cases: enc 768 -> 1664 bytes, dec 896 -> 1664 bytes. Candidate exits 1 with the same-file diagnostic and preserves every byte in all four. Independent stdout encryption/decryption roundtrip, named-output alias, named /dev/null, and stdin/stdout /dev/null controls pass. Test script shell syntax passes. No complete suite or platform matrix run. Executed source 342abef and test 72d49e3 are identical to this commit. The isolated validation workflow/driver remain on validation/scrypt-stdout-alias-20261004 at 120326d and are not included here.
Fixes #427.
scrypt enc secret.txt secret.txtpreviously opened the output withfopen(..., "wb")before reading the input, silently replacing the source with a 128-byte encryption of empty data.scrypt dec f fcould destroy the ciphertext similarly, and stdin aliases are also reachable (scrypt enc - f < f). This PR supports the original first-reporter bug-bounty submission in #427 by @woahwhattheheck; that claimant and request for sponsor classification/payment remain unchanged.Current implementation
same_file()checks the already-open input before asking for a passphrase. It compares against either the named output or the already-open standard output. Regular-file aliases are identified by device/inode; block-device aliases by their underlying device. Character devices such as/dev/nullremain permitted.open_output()opens a named output withoutO_TRUNC, compares the actual open descriptors, and only then truncates a distinct regular output. This binds the destructive check to the opened object rather than trusting the earlier pathname check, closing the path-swap seam.errnowhen closing an unsuccessful output descriptor. An obvious same-file failure occurs before prompting.scrypt.1documents the restriction and its limit: the program cannot undo truncation already performed by the invoking shell.Executed acceptance — October 9, 2026
The unchanged contribution head
ff39f6231fb12fc7171492d2b063b960b4bb2664built with Autotools and GCC 13.3.0 (-std=c99 -O2) on Ubuntu 24.04. Its existing same-file scenario passed through the project runner:autoreconf -fi ./configure CFLAGS='-std=c99 -O2' make -j2 N=12 USE_VALGRIND=0 VERBOSE=1 sh tests/test_scrypt.sh ./scryptSuccessful exact-head acceptance run.
The existing scenario covers ordinary same-file encryption/decryption, hard links, symlink aliases, stdin,
..path spelling, stdout aliases, input preservation, different-file output, and a FIFO-gated pathname swap after the early check. The workflow checks that the production/test source remains unchanged. It lives on an isolated acceptance branch and adds no CI-only files to this upstream PR.The first acceptance job ran the scenario successfully but was marked failed by an overly strict log matcher: verbose progress split the success message across lines. The linked corrected job uses the runner's exit status and is green. No production or regression-source changes were made for either run. This receipt is for the focused Linux scenario, not a full-suite, Valgrind or cross-platform result; sponsor acceptance and payment are separate.
Test numbering
The scenario is numbered
12to avoidtests/11-info.shfrom #426. The adjacentEXTRA_DISTentries may need reconciliation depending on merge order.Original-reporter claim and follow-through
The original reporter and PR author is @woahwhattheheck. This corrective contribution is submitted in support of the existing bug-bounty report and claim in #427. I request sponsor review, the applicable bounty classification and any eligible payment to the original claimant, and will address feedback on this PR. Original contributor credit and earlier compensation requests remain intact; no award or received payment is assumed.