[gnupg] gpgv --output FILE leaves FILE.part (regression in 2.5.21)

KOSHIKAWA Kenichi reishoku at reishoku.net
Wed Nov 4 01:00:38 CET 2026


Hello,
 
I could not open a task on dev.gnupg.org, so I am reporting this here.
 
Since 2.5.21, "gpgv --output FILE" exits with 0 and reports a good
signature, but FILE is never created.  The data is left in FILE.part.
"gpg --verify --output FILE" is not affected.
 
  Affected:  2.5.21 to 2.5.24, and master as of 5b001e5ccd62
  Good:      2.5.20, 2.4.x (checked 2.4.4 and 2.4.7)
  Systems:   Linux x86_64 (Ubuntu 24.04, built from git)
             macOS 27.0.1 arm64 (2.5.24 from Homebrew)
 
Recipe (any gpg 2.x can create the key and the signature):
 
  mkdir -m 700 home
  gpg --homedir home --batch --pinentry-mode loopback --passphrase '' \
      --quick-gen-key 'Test <test at example.org>' ed25519 sign never
  printf 'Hello\n' > data.txt
  gpg --homedir home --batch --clearsign -o signed.asc data.txt
  gpg --homedir home --batch --export > trusted.gpg
  gpgv --homedir home --keyring ./trusted.gpg --output out signed.asc
  ls out*
 
  Expected: out
  Actual:   out.part
 
Output of the gpgv steps with 2.5.24, built from the gnupg-2.5.24 tag
on Linux x86_64 (the key and signature were made with gpg 2.4.4):
 
  $ gpgv --version | head -n 1
  gpgv (GnuPG) 2.5.24
  $ gpgv --homedir home --keyring ./trusted.gpg --output out signed.asc
  gpgv: Signature made Tue Nov  3 16:12:01 2026 UTC
  gpgv:                using EDDSA key 200E09EBB8AD23B976698A94C71F7B4433288887
  gpgv: Good signature from "Test <test at example.org>"
  $ echo $?
  0
  $ ls out*
  out.part
 
With master (2.5.25-beta34) the result is the same.  With 2.5.20,
"ls out*" shows "out", and its content is the signed text.
 
git bisect between gnupg-2.5.20 and gnupg-2.5.24 gives
 
  ab2e64e4b490 gpg: Defer renaming at exit, so that it can remove
               on failure.  (T7873)
 
as the first bad commit.  With it, pfg_close_file only registers the
rename, and gnupg_commit_partial_file is called from g10_exit in
g10/gpg.c.  gpgv has its own g10_exit in g10/gpgv.c, which does not
call it, so the .part file is never renamed.  The later changes for
T8399 and 31339d07 only touch the gpg side.
 
Exit code when FILE cannot be created (FILE is an existing
directory):
 
  2.4.4, 2.5.20             2  "error creating 'out'"
  a9c9435c (2.5.21-beta15)  2  "renaming 'out.part' ... failed"
  2.5.24, master            0  (FILE.part is left, as above)
 
In g10/gpg.c, gnupg_commit_partial_file is called after the exit code
is computed, so the log_error from a failed rename is not counted.
"gpg --verify --output FILE" on master prints "renaming 'out.part' to
'out' failed" and exits with 0 in the same case.  This looks like the
same problem on the gpg side.
 
When FILE already exists, gpgv 2.5.21 and later keep its old content
and still exit with 0 and GOODSIG.  A caller that passes a file
created with mktemp, or that reuses an output path, may then read old
data as verified.  I leave it to you whether this needs more than a
normal bug fix.
 
The test suite did not catch this, because tests/openpgp/gpgv.scm
does not use --output.
 
I can test a fix on Linux and macOS.
 
I used an AI assistant (Anthropic's Claude) for the bisect and the
analysis, and to help write this report.  I have checked the results
above myself.
 
Thanks,
Kenichi

-- 
KOSHIKAWA Kenichi
reishoku at reishoku.net
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 265 bytes
Desc: not available
URL: <https://lists.gnupg.org/pipermail/gnupg-devel/attachments/20261104/a1f5c182/attachment-0001.sig>


More information about the Gnupg-devel mailing list