rapace_core/
validation.rs1use crate::{
4 DescriptorLimits, INLINE_PAYLOAD_SIZE, INLINE_PAYLOAD_SLOT, MsgDescHot, ValidationError,
5};
6
7pub fn validate_descriptor(
16 desc: &MsgDescHot,
17 limits: &DescriptorLimits,
18) -> Result<(), ValidationError> {
19 if desc.payload_len > limits.max_payload_len {
21 return Err(ValidationError::PayloadTooLarge {
22 len: desc.payload_len,
23 max: limits.max_payload_len,
24 });
25 }
26
27 if desc.channel_id > limits.max_channels {
29 return Err(ValidationError::ChannelOutOfBounds {
30 channel: desc.channel_id,
31 max: limits.max_channels,
32 });
33 }
34
35 if desc.payload_slot == INLINE_PAYLOAD_SLOT {
36 if desc.payload_len > INLINE_PAYLOAD_SIZE as u32 {
38 return Err(ValidationError::InlinePayloadTooLarge {
39 len: desc.payload_len,
40 max: INLINE_PAYLOAD_SIZE as u32,
41 });
42 }
43 if desc.payload_generation != 0 || desc.payload_offset != 0 {
45 return Err(ValidationError::InvalidInlineDescriptor);
46 }
47 } else if limits.slot_count > 0 {
48 if desc.payload_slot >= limits.slot_count {
50 return Err(ValidationError::SlotOutOfBounds {
51 slot: desc.payload_slot,
52 max: limits.slot_count,
53 });
54 }
55
56 let end = desc.payload_offset.saturating_add(desc.payload_len);
57 if end > limits.slot_size {
58 return Err(ValidationError::PayloadOutOfBounds {
59 offset: desc.payload_offset,
60 len: desc.payload_len,
61 slot_size: limits.slot_size,
62 });
63 }
64 }
65
66 Ok(())
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 fn make_desc() -> MsgDescHot {
74 MsgDescHot::new()
75 }
76
77 #[test]
78 fn test_valid_inline_payload() {
79 let mut desc = make_desc();
80 desc.payload_len = 10;
81 desc.inline_payload[..10].fill(0xAB);
82
83 let limits = DescriptorLimits::default();
84 assert!(validate_descriptor(&desc, &limits).is_ok());
85 }
86
87 #[test]
88 fn test_inline_payload_too_large() {
89 let mut desc = make_desc();
90 desc.payload_len = 30; let limits = DescriptorLimits::default();
93 let err = validate_descriptor(&desc, &limits).unwrap_err();
94 assert!(matches!(err, ValidationError::InlinePayloadTooLarge { .. }));
95 }
96
97 #[test]
98 fn test_invalid_inline_descriptor() {
99 let mut desc = make_desc();
100 desc.payload_len = 10;
101 desc.payload_generation = 1; let limits = DescriptorLimits::default();
104 let err = validate_descriptor(&desc, &limits).unwrap_err();
105 assert!(matches!(err, ValidationError::InvalidInlineDescriptor));
106 }
107
108 #[test]
109 fn test_payload_too_large() {
110 let mut desc = make_desc();
111 desc.payload_slot = 0;
112 desc.payload_len = 2 * 1024 * 1024; let limits = DescriptorLimits::with_slots(16, 4096);
115 let err = validate_descriptor(&desc, &limits).unwrap_err();
116 assert!(matches!(err, ValidationError::PayloadTooLarge { .. }));
117 }
118
119 #[test]
120 fn test_slot_out_of_bounds() {
121 let mut desc = make_desc();
122 desc.payload_slot = 100;
123 desc.payload_len = 100;
124
125 let limits = DescriptorLimits::with_slots(16, 4096);
126 let err = validate_descriptor(&desc, &limits).unwrap_err();
127 assert!(matches!(err, ValidationError::SlotOutOfBounds { .. }));
128 }
129
130 #[test]
131 fn test_payload_out_of_bounds() {
132 let mut desc = make_desc();
133 desc.payload_slot = 0;
134 desc.payload_offset = 4000;
135 desc.payload_len = 200; let limits = DescriptorLimits::with_slots(16, 4096);
138 let err = validate_descriptor(&desc, &limits).unwrap_err();
139 assert!(matches!(err, ValidationError::PayloadOutOfBounds { .. }));
140 }
141
142 #[test]
143 fn test_channel_out_of_bounds() {
144 let mut desc = make_desc();
145 desc.channel_id = 2000;
146
147 let limits = DescriptorLimits::default();
148 let err = validate_descriptor(&desc, &limits).unwrap_err();
149 assert!(matches!(err, ValidationError::ChannelOutOfBounds { .. }));
150 }
151
152 #[test]
153 fn test_valid_slot_payload() {
154 let mut desc = make_desc();
155 desc.payload_slot = 5;
156 desc.payload_generation = 42;
157 desc.payload_offset = 100;
158 desc.payload_len = 500;
159
160 let limits = DescriptorLimits::with_slots(16, 4096);
161 assert!(validate_descriptor(&desc, &limits).is_ok());
162 }
163}