Cap native input buffer length

ober

b6cb83c6d8f0aa29928090a1a61649063408abbc

diff --git a/pgp-native/src/age_mod.rs b/pgp-native/src/age_mod.rs
index efe66cc..70e8fdf 100644
--- a/pgp-native/src/age_mod.rs
+++ b/pgp-native/src/age_mod.rs
@@ -36,8 +36,9 @@ pub fn encrypt(plaintext: &[u8], recipients_str: &str) -> Result<Vec<u8>, i32> {
 
     let mut out: Vec<u8> = Vec::new();
     {
-        let armored = age::armor::ArmoredWriter::wrap_output(&mut out, age::armor::Format::AsciiArmor)
-            .map_err(|_| JPGP_E_ENCRYPT)?;
+        let armored =
+            age::armor::ArmoredWriter::wrap_output(&mut out, age::armor::Format::AsciiArmor)
+                .map_err(|_| JPGP_E_ENCRYPT)?;
         let mut writer = encryptor.wrap_output(armored).map_err(|_| JPGP_E_ENCRYPT)?;
         writer.write_all(plaintext).map_err(|_| JPGP_E_ENCRYPT)?;
         let armored = writer.finish().map_err(|_| JPGP_E_ENCRYPT)?;
@@ -49,9 +50,7 @@ pub fn encrypt(plaintext: &[u8], recipients_str: &str) -> Result<Vec<u8>, i32> {
 /// Decrypt an age-armored ciphertext using a single X25519 identity
 /// supplied as an `AGE-SECRET-KEY-1...` string.
 pub fn decrypt(ciphertext: &[u8], identity_str: &str) -> Result<Vec<u8>, i32> {
-    let id: age::x25519::Identity = identity_str
-        .parse()
-        .map_err(|_| JPGP_E_PARSE_KEY)?;
+    let id: age::x25519::Identity = identity_str.parse().map_err(|_| JPGP_E_PARSE_KEY)?;
 
     let armored = age::armor::ArmoredReader::new(ciphertext);
     let decryptor = age::Decryptor::new(armored).map_err(|_| JPGP_E_DECRYPT)?;
@@ -66,6 +65,8 @@ pub fn decrypt(ciphertext: &[u8], identity_str: &str) -> Result<Vec<u8>, i32> {
     };
 
     let mut plaintext = Vec::new();
-    reader.read_to_end(&mut plaintext).map_err(|_| JPGP_E_DECRYPT)?;
+    reader
+        .read_to_end(&mut plaintext)
+        .map_err(|_| JPGP_E_DECRYPT)?;
     Ok(plaintext)
 }
diff --git a/pgp-native/src/lib.rs b/pgp-native/src/lib.rs
index f85bd4a..f283f31 100644
--- a/pgp-native/src/lib.rs
+++ b/pgp-native/src/lib.rs
@@ -10,8 +10,8 @@
 mod age_mod;
 mod error;
 mod pass_mod;
-mod pgp_mod;
 mod pgp_io;
+mod pgp_mod;
 mod sig_mod;
 mod util;
 
@@ -363,11 +363,7 @@ pub unsafe extern "C" fn jpgp_pgp_verify(
 
 /// SHA-256 of `input` written to `out` (must be 32 bytes).
 #[no_mangle]
-pub unsafe extern "C" fn jpgp_sha256(
-    input: *const u8,
-    input_len: u32,
-    out: *mut u8,
-) -> i32 {
+pub unsafe extern "C" fn jpgp_sha256(input: *const u8, input_len: u32, out: *mut u8) -> i32 {
     guard(|| {
         if out.is_null() {
             return JPGP_E_INVALID_INPUT;
diff --git a/pgp-native/src/pass_mod.rs b/pgp-native/src/pass_mod.rs
index bccb548..f2b838b 100644
--- a/pgp-native/src/pass_mod.rs
+++ b/pgp-native/src/pass_mod.rs
@@ -13,8 +13,9 @@ pub fn encrypt(plaintext: &[u8], passphrase: &str) -> Result<Vec<u8>, i32> {
 
     let mut out: Vec<u8> = Vec::new();
     {
-        let armored = age::armor::ArmoredWriter::wrap_output(&mut out, age::armor::Format::AsciiArmor)
-            .map_err(|_| JPGP_E_ENCRYPT)?;
+        let armored =
+            age::armor::ArmoredWriter::wrap_output(&mut out, age::armor::Format::AsciiArmor)
+                .map_err(|_| JPGP_E_ENCRYPT)?;
         let mut writer = encryptor.wrap_output(armored).map_err(|_| JPGP_E_ENCRYPT)?;
         writer.write_all(plaintext).map_err(|_| JPGP_E_ENCRYPT)?;
         let armored = writer.finish().map_err(|_| JPGP_E_ENCRYPT)?;
@@ -36,6 +37,8 @@ pub fn decrypt(ciphertext: &[u8], passphrase: &str) -> Result<Vec<u8>, i32> {
     };
 
     let mut plaintext = Vec::new();
-    reader.read_to_end(&mut plaintext).map_err(|_| JPGP_E_DECRYPT)?;
+    reader
+        .read_to_end(&mut plaintext)
+        .map_err(|_| JPGP_E_DECRYPT)?;
     Ok(plaintext)
 }
diff --git a/pgp-native/src/pgp_io.rs b/pgp-native/src/pgp_io.rs
index fdc4df4..9d601e4 100644
--- a/pgp-native/src/pgp_io.rs
+++ b/pgp-native/src/pgp_io.rs
@@ -22,8 +22,7 @@ pub fn decrypt(secret_armor: &str, passphrase: &str, ciphertext: &[u8]) -> Resul
         .map_err(|_| JPGP_E_PARSE_KEY)?;
     skey.verify().map_err(|_| JPGP_E_PARSE_KEY)?;
 
-    let (msg, _) =
-        Message::from_armor_single(ciphertext).map_err(|_| JPGP_E_PARSE_KEY)?;
+    let (msg, _) = Message::from_armor_single(ciphertext).map_err(|_| JPGP_E_PARSE_KEY)?;
 
     let pass = passphrase.to_owned();
     let (decrypted, _ids) = msg
diff --git a/pgp-native/src/pgp_mod.rs b/pgp-native/src/pgp_mod.rs
index ac5da5e..87f4e27 100644
--- a/pgp-native/src/pgp_mod.rs
+++ b/pgp-native/src/pgp_mod.rs
@@ -18,10 +18,7 @@ pub fn encrypt(pubkey_armor: &str, plaintext: &[u8]) -> Result<String, i32> {
     let lit = Message::new_literal_bytes("msg.bin", plaintext);
     let mut rng = thread_rng();
 
-    let enc_subkey = pkey
-        .public_subkeys
-        .iter()
-        .find(|sk| sk.is_encryption_key());
+    let enc_subkey = pkey.public_subkeys.iter().find(|sk| sk.is_encryption_key());
 
     let encrypted = if let Some(sub) = enc_subkey {
         lit.encrypt_to_keys_seipdv1(&mut rng, SymmetricKeyAlgorithm::AES256, &[sub])
diff --git a/pgp-native/src/util.rs b/pgp-native/src/util.rs
index b85d4e0..5fa4f1f 100644
--- a/pgp-native/src/util.rs
+++ b/pgp-native/src/util.rs
@@ -4,6 +4,8 @@
 use crate::error::*;
 use std::slice;
 
+pub const MAX_INPUT_LEN: u32 = 64 * 1024 * 1024;
+
 /// Write `src` into the caller-provided buffer.
 ///
 /// - Writes `src.len()` to `*out_len` always (even when `out` is null).
@@ -39,6 +41,9 @@ pub unsafe fn write_out(src: &[u8], out: *mut u8, out_len_in: u32, out_len: *mut
 /// # Safety
 /// `ptr` (if non-null) must be readable for `len` bytes.
 pub unsafe fn slice_from(ptr: *const u8, len: u32) -> Option<&'static [u8]> {
+    if len > MAX_INPUT_LEN {
+        return None;
+    }
     if ptr.is_null() {
         if len == 0 {
             return Some(&[]);