From 24868e519289d5d1862dff1d63eb25d1eb5fdba1 Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Sat, 2 Mar 2024 19:24:43 +0900 Subject: [PATCH] gpg_signing: handle early termination of gpg command in verify path Also fixes missing wait() on I/O error. We have the same problem in several places. I'll fix them in another batch. --- lib/src/gpg_signing.rs | 12 +++++++++--- lib/tests/test_gpg.rs | 10 +++++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/src/gpg_signing.rs b/lib/src/gpg_signing.rs index cdc012292..ea4c85404 100644 --- a/lib/src/gpg_signing.rs +++ b/lib/src/gpg_signing.rs @@ -18,7 +18,7 @@ use std::ffi::OsString; use std::fmt::Debug; use std::io::Write; use std::process::{Command, ExitStatus, Stdio}; -use std::str; +use std::{io, str}; use thiserror::Error; @@ -82,9 +82,15 @@ fn run_sign_command(command: &mut Command, input: &[u8]) -> Result, GpgE fn run_verify_command(command: &mut Command, input: &[u8]) -> Result, GpgError> { let process = command.stderr(Stdio::null()).spawn()?; - process.stdin.as_ref().unwrap().write_all(input)?; + let write_result = process.stdin.as_ref().unwrap().write_all(input); let output = process.wait_with_output()?; - Ok(output.stdout) + match write_result { + Ok(()) => Ok(output.stdout), + // If the signature format is invalid, gpg will terminate early. Writing + // more input data will fail in that case. + Err(err) if err.kind() == io::ErrorKind::BrokenPipe => Ok(vec![]), + Err(err) => Err(err.into()), + } } #[derive(Debug)] diff --git a/lib/tests/test_gpg.rs b/lib/tests/test_gpg.rs index 1dd0e5b10..c15a70e4a 100644 --- a/lib/tests/test_gpg.rs +++ b/lib/tests/test_gpg.rs @@ -200,8 +200,16 @@ fn invalid_signature() { super duper invalid -----END PGP SIGNATURE-----"; + + // Small data: gpg command will exit late. assert_matches!( - backend.verify(b"hello world", signature), + backend.verify(b"a", signature), + Err(SignError::InvalidSignatureFormat) + ); + + // Large data: gpg command will exit early because the signature is invalid. + assert_matches!( + backend.verify(&b"a".repeat(100 * 1024), signature), Err(SignError::InvalidSignatureFormat) ); }