about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorian Klink <flokli@flokli.de>2023-11-27T14·36+0200
committerclbot <clbot@tvl.fyi>2023-11-27T15·12+0000
commitb7de931cc6edd78b6c59ed97bf4485ae90c3de06 (patch)
treea635d71147fd39060dc03d64216a382a976e4ad4
parentdfaaf41cefe004eeb35f362cee3ba145bf0b9d35 (diff)
fix(nix-compat/narinfo): don't panic trying to parse signatures r/7074
BASE64.decode_mut panics if we're passing data that has the wrong size.
Do the size check first and error out there.

Also update the error, and talk about b64-encoded sizes.

Change-Id: I290f80a37d48526a30bf1df9d1d9fe34865008eb
Reviewed-on: https://cl.tvl.fyi/c/depot/+/10146
Tested-by: BuildkiteCI
Reviewed-by: edef <edef@edef.eu>
Autosubmit: flokli <flokli@flokli.de>
-rw-r--r--tvix/nix-compat/src/narinfo/signature.rs19
1 files changed, 13 insertions, 6 deletions
diff --git a/tvix/nix-compat/src/narinfo/signature.rs b/tvix/nix-compat/src/narinfo/signature.rs
index 26e062a09e..53e75c5873 100644
--- a/tvix/nix-compat/src/narinfo/signature.rs
+++ b/tvix/nix-compat/src/narinfo/signature.rs
@@ -20,13 +20,15 @@ impl<'a> Signature<'a> {
             .split_once(':')
             .ok_or(SignatureError::MissingSeparator)?;
 
-        let mut buf = [0; SIGNATURE_LENGTH + 2];
+        if bytes64.len() != BASE64.encode_len(SIGNATURE_LENGTH) {
+            return Err(SignatureError::InvalidSignatureLen(bytes64.len()));
+        }
+
         let mut bytes = [0; SIGNATURE_LENGTH];
+        let mut buf = [0; SIGNATURE_LENGTH + 2];
         match BASE64.decode_mut(bytes64.as_bytes(), &mut buf) {
-            Ok(SIGNATURE_LENGTH) => {
-                bytes.copy_from_slice(&buf[..SIGNATURE_LENGTH]);
-            }
-            Ok(n) => return Err(SignatureError::InvalidSignatureLen(n)),
+            Ok(SIGNATURE_LENGTH) => bytes.copy_from_slice(&buf[..SIGNATURE_LENGTH]),
+            Ok(_) => unreachable!(),
             // keeping DecodePartial gets annoying lifetime-wise
             Err(_) => return Err(SignatureError::DecodeError(input.to_string())),
         }
@@ -54,7 +56,7 @@ impl<'a> Signature<'a> {
 pub enum SignatureError {
     #[error("Missing separator")]
     MissingSeparator,
-    #[error("Invalid signature len: {0}")]
+    #[error("Invalid signature len: (expected {} b64-encoded, got {}", BASE64.encode_len(SIGNATURE_LENGTH), .0)]
     InvalidSignatureLen(usize),
     #[error("Unable to base64-decode signature: {0}")]
     DecodeError(String),
@@ -111,4 +113,9 @@ mod test {
         let sig = Signature::parse(sig_str).expect("must parse");
         assert_eq!(expect_valid, sig.verify(fp.as_bytes(), verifying_key));
     }
+
+    #[test_case("cache.nixos.org-1:o1DTsjCz0PofLJ216P2RBuSulI8BAb6zHxWE4N+tzlcELk5Uk/GO2SCxWTRN5wJutLZZ+cHTMdWqOHF8"; "wrong_length")]
+    fn parse_fail(input: &'static str) {
+        Signature::parse(input).expect_err("must fail");
+    }
 }