@@ -12,7 +12,7 @@ use std::task::{Poll, ready};
1212
1313use bytes:: Bytes ;
1414
15- use crate :: { Error , Result } ;
15+ use crate :: { Error , MAX_FRAME_SIZE , Result } ;
1616
1717use super :: { Frame , FrameConsumer , FrameProducer } ;
1818
@@ -179,13 +179,23 @@ impl GroupProducer {
179179
180180 /// Create a frame with an upfront size
181181 pub fn create_frame ( & mut self , info : Frame ) -> Result < FrameProducer > {
182+ // Reject before `produce()`: `FrameProducer::new` preallocates `size` bytes, so an oversized
183+ // frame must be caught here or it triggers the very allocation the limit exists to prevent.
184+ if info. size > MAX_FRAME_SIZE {
185+ return Err ( Error :: FrameTooLarge ) ;
186+ }
182187 let frame = info. produce ( ) ;
183188 self . append_frame ( frame. clone ( ) ) ?;
184189 Ok ( frame)
185190 }
186191
187192 /// Append a frame producer to the group.
188193 pub fn append_frame ( & mut self , frame : FrameProducer ) -> Result < ( ) > {
194+ // Backstop for direct callers (the buffer is already allocated by the time we hold a
195+ // FrameProducer); `create_frame` is the path that rejects before allocating.
196+ if frame. size > MAX_FRAME_SIZE {
197+ return Err ( Error :: FrameTooLarge ) ;
198+ }
189199 let mut state = modify ( & self . state ) ?;
190200 if state. fin {
191201 return Err ( Error :: Closed ) ;
@@ -441,6 +451,20 @@ mod test {
441451 assert_eq ! ( chunks[ 0 ] , Bytes :: from_static( b"helloworld" ) ) ;
442452 }
443453
454+ #[ test]
455+ fn append_rejects_oversized_frame ( ) {
456+ let mut producer = Group { sequence : 0 } . produce ( ) ;
457+ let err = producer. create_frame ( Frame {
458+ size : MAX_FRAME_SIZE + 1 ,
459+ } ) ;
460+ assert ! (
461+ matches!( err, Err ( Error :: FrameTooLarge ) ) ,
462+ "a frame over the limit is rejected"
463+ ) ;
464+ // A frame at the limit is still accepted.
465+ assert ! ( producer. create_frame( Frame { size: MAX_FRAME_SIZE } ) . is_ok( ) ) ;
466+ }
467+
444468 #[ test]
445469 fn get_frame_by_index ( ) {
446470 let mut producer = Group { sequence : 0 } . produce ( ) ;
0 commit comments