typed-rust: bytevector-copy slice primitive + AES-GCM nonce lifetime fix
ober
87120f0c7184f9e4d4a680fe7222efa794e8fe0c
--- a/lib/jerboa/typed/checker.ss +++ b/lib/jerboa/typed/checker.ss @@ -376,6 +376,11 @@ (cons 'bytevector-append (make-typed-call-sig (list 'Bytes 'Bytes) 'Bytes '() 'bytevector-append '())) + ;; (bytevector-copy bv start end) -> the slice bv[start..end] as a fresh + ;; owned buffer (R7RS 3-arg form); splits framed buffers in byte parsers. + (cons 'bytevector-copy + (make-typed-call-sig (list 'Bytes 'Nat 'Nat) 'Bytes '() + 'bytevector-copy '())) ;; an Int as its 8-byte little-endian i64 encoding (Rust i64::to_le_bytes). (cons 'integer->le-bytes (make-typed-call-sig (list 'Int) 'Bytes '() --- a/lib/jerboa/typed/rust.ss +++ b/lib/jerboa/typed/rust.ss @@ -1435,8 +1435,11 @@ "{ use aes_gcm::aead::{Aead, KeyInit, Payload}; " "let __c = aes_gcm::Aes256Gcm::new_from_slice(" (bytes-slice (car args)) ").expect(\"AES-256-GCM key is 32 bytes\"); " - "let __n = aes_gcm::Nonce::from_slice(" (bytes-slice (cadr args)) - "); __c.encrypt(__n, Payload { msg: " (bytes-slice (caddr args)) + ;; bind the nonce to an owned local: Nonce::from_slice borrows it and the + ;; borrow must outlive the encrypt() call (a temporary would drop early). + "let __nonce = (" (emit-expression (cadr args)) "); " + "let __n = aes_gcm::Nonce::from_slice(&__nonce[..]); " + "__c.encrypt(__n, Payload { msg: " (bytes-slice (caddr args)) ", aad: " (bytes-slice (cadddr args)) " }).expect(\"AES-256-GCM encryption within size limits\") }")) @@ -1451,8 +1454,10 @@ "{ use aes_gcm::aead::{Aead, KeyInit, Payload}; " "let __c = aes_gcm::Aes256Gcm::new_from_slice(" (bytes-slice (car args)) ").expect(\"AES-256-GCM key is 32 bytes\"); " - "let __n = aes_gcm::Nonce::from_slice(" (bytes-slice (cadr args)) - "); match __c.decrypt(__n, Payload { msg: " (bytes-slice (caddr args)) + ;; bind the nonce to an owned local so its borrow outlives decrypt(). + "let __nonce = (" (emit-expression (cadr args)) "); " + "let __n = aes_gcm::Nonce::from_slice(&__nonce[..]); " + "match __c.decrypt(__n, Payload { msg: " (bytes-slice (caddr args)) ", aad: " (bytes-slice (cadddr args)) " }) { Ok(__pt) => Some(__pt), Err(_) => None } }")) @@ -1479,6 +1484,17 @@ (bytes-slice (cadr args)) "); __v }")) + ;; (bytevector-copy bv start end) -> bv[start..end] as a fresh owned buffer. + ;; Nat indices widen to usize like bytevector-u8-ref; an out-of-range slice + ;; panics and is caught by the C-ABI wrapper (caller validates lengths). + (def (emit-bytevector-copy args) + (unless (= (length args) 3) + (error 'typed-rust "bytevector-copy expects bv, start and end operands" args)) + (string-append + "(" (emit-expression (car args)) + "[(" (emit-expression (cadr args)) ") as usize..(" + (emit-expression (caddr args)) ") as usize].to_vec())")) + ;; (integer->le-bytes n) -> the 8-byte little-endian i64 encoding, matching ;; Rust's i64::to_le_bytes (secmon serializes timestamps this way). (def (emit-integer->le-bytes args) @@ -1724,6 +1740,7 @@ [(string->utf8) (emit-string->utf8 args)] [(utf8->string) (emit-utf8->string args)] [(bytevector-append) (emit-bytevector-append args)] + [(bytevector-copy) (emit-bytevector-copy args)] [(integer->le-bytes) (emit-integer->le-bytes args)] [(make-bytevector) (emit-make-bytevector args)] [(exact->inexact) (emit-to-float args)]