@@ -174,6 +174,14 @@ pub fn decode_record(buf: &[u8]) -> Result<ApplyJournalRecord> {
174174 let action_count = u32:: from_le_bytes ( b4) as usize ;
175175 off += 4 ;
176176
177+ // Every action consumes at least one kind byte plus a 16-byte segment id.
178+ // Reject hostile counts before they can drive a giant allocation.
179+ if action_count > buf. len ( ) . saturating_sub ( off) / 17 {
180+ return Err ( PagedbError :: corruption (
181+ crate :: errors:: CorruptionDetail :: HeaderUnverifiable ,
182+ ) ) ;
183+ }
184+
177185 let mut actions = Vec :: with_capacity ( action_count) ;
178186 for _ in 0 ..action_count {
179187 if off >= buf. len ( ) {
@@ -215,6 +223,12 @@ pub fn decode_record(buf: &[u8]) -> Result<ApplyJournalRecord> {
215223 }
216224 }
217225
226+ if off != buf. len ( ) {
227+ return Err ( PagedbError :: corruption (
228+ crate :: errors:: CorruptionDetail :: HeaderUnverifiable ,
229+ ) ) ;
230+ }
231+
218232 Ok ( ApplyJournalRecord {
219233 target_commit_id,
220234 actions,
@@ -401,6 +415,25 @@ mod tests {
401415 assert_eq ! ( decoded. actions. len( ) , 1 ) ;
402416 }
403417
418+ #[ test]
419+ fn decode_record_rejects_trailing_bytes_inside_record ( ) {
420+ let mut record = encode_record ( & promotes ( 1 ) ) ;
421+ record. push ( 0xAA ) ;
422+
423+ let err = decode_record ( & record) . expect_err ( "trailing record bytes must be corruption" ) ;
424+ assert ! ( matches!( err, PagedbError :: Corruption ( _) ) ) ;
425+ }
426+
427+ #[ test]
428+ fn decode_record_rejects_impossible_action_count_before_allocation ( ) {
429+ let mut record = Vec :: new ( ) ;
430+ record. extend_from_slice ( & 42u64 . to_le_bytes ( ) ) ;
431+ record. extend_from_slice ( & u32:: MAX . to_le_bytes ( ) ) ;
432+
433+ let err = decode_record ( & record) . expect_err ( "impossible action count must be corruption" ) ;
434+ assert ! ( matches!( err, PagedbError :: Corruption ( _) ) ) ;
435+ }
436+
404437 async fn mk_pager ( ) -> crate :: pager:: Pager < crate :: vfs:: memory:: MemVfs > {
405438 let mk = crate :: crypto:: kdf:: derive_mk ( & [ 1u8 ; 32 ] , & [ 0u8 ; 16 ] , 0 ) . unwrap ( ) ;
406439 let cfg = crate :: pager:: PagerConfig {
0 commit comments