about summary refs log tree commit diff
path: root/tvix
diff options
context:
space:
mode:
authorFlorian Klink <flokli@flokli.de>2023-01-17T12·31+0100
committerflokli <flokli@flokli.de>2023-01-18T17·13+0000
commit9822fa387ae8d8053eaba1b30c3fc5870ba701b8 (patch)
tree43d93feadbeeabce7f3377076bd69e4db7765f0b /tvix
parent083e24bbb1a216b43bfa4fa2e509a1ee6a88ad46 (diff)
feat(tvix/derivation): more checks for output hashes and encoding r/5701
Change-Id: Idebad60c3bf9daf94d04a36bb73ac0dd767f9e79
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7856
Reviewed-by: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
Diffstat (limited to 'tvix')
-rw-r--r--tvix/Cargo.lock1
-rw-r--r--tvix/Cargo.nix4
-rw-r--r--tvix/derivation/Cargo.toml1
-rw-r--r--tvix/derivation/src/errors.rs6
-rw-r--r--tvix/derivation/src/output.rs23
5 files changed, 33 insertions, 2 deletions
diff --git a/tvix/Cargo.lock b/tvix/Cargo.lock
index 523264b32f84..acf516900fd6 100644
--- a/tvix/Cargo.lock
+++ b/tvix/Cargo.lock
@@ -2318,6 +2318,7 @@ name = "tvix-derivation"
 version = "0.1.0"
 dependencies = [
  "anyhow",
+ "data-encoding",
  "glob",
  "serde",
  "serde_json",
diff --git a/tvix/Cargo.nix b/tvix/Cargo.nix
index ca3165c1afab..cb86a7fe5ba7 100644
--- a/tvix/Cargo.nix
+++ b/tvix/Cargo.nix
@@ -6880,6 +6880,10 @@ rec {
             packageId = "anyhow";
           }
           {
+            name = "data-encoding";
+            packageId = "data-encoding";
+          }
+          {
             name = "glob";
             packageId = "glob";
           }
diff --git a/tvix/derivation/Cargo.toml b/tvix/derivation/Cargo.toml
index 12afcf92c1e8..ff54a0848abe 100644
--- a/tvix/derivation/Cargo.toml
+++ b/tvix/derivation/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 
 [dependencies]
 anyhow = "1.0.68"
+data-encoding = "2.3.3"
 glob = "0.3.0"
 serde = { version = "1.0", features = ["derive"] }
 sha2 = "0.10.6"
diff --git a/tvix/derivation/src/errors.rs b/tvix/derivation/src/errors.rs
index 75b101efddae..6942967e1d23 100644
--- a/tvix/derivation/src/errors.rs
+++ b/tvix/derivation/src/errors.rs
@@ -47,4 +47,10 @@ pub enum DerivationError {
 pub enum OutputError {
     #[error("Invalid ouput path {0}: {1}")]
     InvalidOutputPath(String, ParseStorePathError),
+    #[error("Invalid hash encoding: {0}")]
+    InvalidHashEncoding(String, data_encoding::DecodeError),
+    #[error("Invalid hash algo: {0}")]
+    InvalidHashAlgo(String),
+    #[error("Invalid Digest size {0} for algo {1}")]
+    InvalidDigestSizeForAlgo(usize, String),
 }
diff --git a/tvix/derivation/src/output.rs b/tvix/derivation/src/output.rs
index 369efca031f3..36a480d5a0d7 100644
--- a/tvix/derivation/src/output.rs
+++ b/tvix/derivation/src/output.rs
@@ -1,5 +1,5 @@
 use serde::{Deserialize, Serialize};
-use tvix_store::store_path::StorePath;
+use tvix_store::{nixbase32::NIXBASE32, store_path::StorePath};
 
 use crate::OutputError;
 
@@ -25,7 +25,26 @@ impl Output {
     }
 
     pub fn validate(&self, validate_output_paths: bool) -> Result<(), OutputError> {
-        // TODO: add validation for hash, hashAlgo
+        if let Some(hash) = &self.hash {
+            // try to decode digest
+            let result = NIXBASE32.decode(&hash.digest.as_bytes());
+            match result {
+                Err(e) => return Err(OutputError::InvalidHashEncoding(hash.digest.clone(), e)),
+                Ok(digest) => {
+                    if hash.algo != "sha1" && hash.algo != "sha256" {
+                        return Err(OutputError::InvalidHashAlgo(hash.algo.to_string()));
+                    }
+                    if (hash.algo == "sha1" && digest.len() != 20)
+                        || (hash.algo == "sha256" && digest.len() != 32)
+                    {
+                        return Err(OutputError::InvalidDigestSizeForAlgo(
+                            digest.len(),
+                            hash.algo.to_string(),
+                        ));
+                    }
+                }
+            };
+        }
         if validate_output_paths {
             if let Err(e) = StorePath::from_absolute_path(&self.path) {
                 return Err(OutputError::InvalidOutputPath(self.path.to_string(), e));