@@ -281,26 +281,45 @@ pub enum BufferAccessError {
281281 #[ error( "Buffer range size invalid: range_size {range_size} must be multiple of 4" ) ]
282282 UnalignedRangeSize { range_size : wgt:: BufferAddress } ,
283283 #[ error( "Buffer access out of bounds: index {index} would underrun the buffer (limit: {min})" ) ]
284- OutOfBoundsUnderrun {
284+ OutOfBoundsStartOffsetUnderrun {
285285 index : wgt:: BufferAddress ,
286286 min : wgt:: BufferAddress ,
287287 } ,
288288 #[ error(
289- "Buffer access out of bounds: last index {index} would overrun the buffer (limit: {max})"
289+ "Buffer access out of bounds: start offset {index} would overrun the buffer (limit: {max})"
290290 ) ]
291- OutOfBoundsOverrun {
291+ OutOfBoundsStartOffsetOverrun {
292292 index : wgt:: BufferAddress ,
293293 max : wgt:: BufferAddress ,
294294 } ,
295- #[ error( "Buffer map range start {start} is greater than end {end}" ) ]
296- NegativeRange {
297- start : wgt:: BufferAddress ,
298- end : wgt:: BufferAddress ,
295+ #[ error(
296+ "Buffer access out of bounds: start offset {index} + size {size} would overrun the buffer (limit: {max})"
297+ ) ]
298+ OutOfBoundsEndOffsetOverrun {
299+ index : wgt:: BufferAddress ,
300+ size : wgt:: BufferAddress ,
301+ max : wgt:: BufferAddress ,
299302 } ,
300303 #[ error( "Buffer map aborted" ) ]
301304 MapAborted ,
302305 #[ error( transparent) ]
303306 InvalidResource ( #[ from] InvalidResourceError ) ,
307+ #[ error( "Map start offset ({offset}) is out-of-bounds for buffer of size {buffer_size}" ) ]
308+ MapStartOffsetOverrun {
309+ offset : wgt:: BufferAddress ,
310+ buffer_size : wgt:: BufferAddress ,
311+ } ,
312+ #[ error(
313+ "Map end offset (start at {} + size of {}) is out-of-bounds for buffer of size {}" ,
314+ offset,
315+ size,
316+ buffer_size
317+ ) ]
318+ MapEndOffsetOverrun {
319+ offset : wgt:: BufferAddress ,
320+ size : wgt:: BufferAddress ,
321+ buffer_size : wgt:: BufferAddress ,
322+ } ,
304323}
305324
306325impl WebGpuError for BufferAccessError {
@@ -318,10 +337,12 @@ impl WebGpuError for BufferAccessError {
318337 | Self :: UnalignedRange
319338 | Self :: UnalignedOffset { .. }
320339 | Self :: UnalignedRangeSize { .. }
321- | Self :: OutOfBoundsUnderrun { .. }
322- | Self :: OutOfBoundsOverrun { .. }
323- | Self :: NegativeRange { .. }
324- | Self :: MapAborted => return ErrorType :: Validation ,
340+ | Self :: OutOfBoundsStartOffsetUnderrun { .. }
341+ | Self :: OutOfBoundsStartOffsetOverrun { .. }
342+ | Self :: OutOfBoundsEndOffsetOverrun { .. }
343+ | Self :: MapAborted
344+ | Self :: MapStartOffsetOverrun { .. }
345+ | Self :: MapEndOffsetOverrun { .. } => return ErrorType :: Validation ,
325346 } ;
326347 e. webgpu_error_type ( )
327348 }
@@ -592,10 +613,30 @@ impl Buffer {
592613 return Err ( ( op, BufferAccessError :: UnalignedRangeSize { range_size } ) ) ;
593614 }
594615
595- let range = offset..( offset + range_size) ;
616+ if offset > self . size {
617+ return Err ( (
618+ op,
619+ BufferAccessError :: MapStartOffsetOverrun {
620+ offset,
621+ buffer_size : self . size ,
622+ } ,
623+ ) ) ;
624+ }
625+ // NOTE: Should never underflow because of our earlier check.
626+ if range_size > self . size - offset {
627+ return Err ( (
628+ op,
629+ BufferAccessError :: MapEndOffsetOverrun {
630+ offset,
631+ size : range_size,
632+ buffer_size : self . size ,
633+ } ,
634+ ) ) ;
635+ }
636+ let end_offset = offset + range_size;
596637
597- if !range . start . is_multiple_of ( wgt:: MAP_ALIGNMENT )
598- || !range . end . is_multiple_of ( wgt:: COPY_BUFFER_ALIGNMENT )
638+ if !offset . is_multiple_of ( wgt:: MAP_ALIGNMENT )
639+ || !end_offset . is_multiple_of ( wgt:: COPY_BUFFER_ALIGNMENT )
599640 {
600641 return Err ( ( op, BufferAccessError :: UnalignedRange ) ) ;
601642 }
@@ -609,25 +650,6 @@ impl Buffer {
609650 return Err ( ( op, e. into ( ) ) ) ;
610651 }
611652
612- if range. start > range. end {
613- return Err ( (
614- op,
615- BufferAccessError :: NegativeRange {
616- start : range. start ,
617- end : range. end ,
618- } ,
619- ) ) ;
620- }
621- if range. end > self . size {
622- return Err ( (
623- op,
624- BufferAccessError :: OutOfBoundsOverrun {
625- index : range. end ,
626- max : self . size ,
627- } ,
628- ) ) ;
629- }
630-
631653 let device = & self . device ;
632654 if let Err ( e) = device. check_is_valid ( ) {
633655 return Err ( ( op, e. into ( ) ) ) ;
@@ -650,7 +672,8 @@ impl Buffer {
650672 return Err ( ( op, BufferAccessError :: MapAlreadyPending ) ) ;
651673 }
652674 BufferMapState :: Idle => BufferMapState :: Waiting ( BufferPendingMapping {
653- range,
675+ // NOTE: Should never overflow because of our earlier check.
676+ range : offset..end_offset,
654677 op,
655678 _parent_buffer : self . clone ( ) ,
656679 } ) ,
@@ -704,11 +727,18 @@ impl Buffer {
704727 let map_state = & * self . map_state . lock ( ) ;
705728 match * map_state {
706729 BufferMapState :: Init { ref staging_buffer } => {
707- // offset (u64) can not be < 0, so no need to validate the lower bound
708- if offset + range_size > self . size {
709- return Err ( BufferAccessError :: OutOfBoundsOverrun {
710- index : offset + range_size - 1 ,
711- max : self . size ,
730+ if offset > self . size {
731+ return Err ( BufferAccessError :: MapStartOffsetOverrun {
732+ offset,
733+ buffer_size : self . size ,
734+ } ) ;
735+ }
736+ // NOTE: Should never underflow because of our earlier check.
737+ if range_size > self . size - offset {
738+ return Err ( BufferAccessError :: MapEndOffsetOverrun {
739+ offset,
740+ size : range_size,
741+ buffer_size : self . size ,
712742 } ) ;
713743 }
714744 let ptr = unsafe { staging_buffer. ptr ( ) } ;
@@ -720,15 +750,22 @@ impl Buffer {
720750 ref range,
721751 ..
722752 } => {
753+ if offset > range. end {
754+ return Err ( BufferAccessError :: OutOfBoundsStartOffsetOverrun {
755+ index : offset,
756+ max : range. end ,
757+ } ) ;
758+ }
723759 if offset < range. start {
724- return Err ( BufferAccessError :: OutOfBoundsUnderrun {
760+ return Err ( BufferAccessError :: OutOfBoundsStartOffsetUnderrun {
725761 index : offset,
726762 min : range. start ,
727763 } ) ;
728764 }
729- if offset + range_size > range. end {
730- return Err ( BufferAccessError :: OutOfBoundsOverrun {
731- index : offset + range_size - 1 ,
765+ if range_size > range. end - offset {
766+ return Err ( BufferAccessError :: OutOfBoundsEndOffsetOverrun {
767+ index : offset,
768+ size : range_size,
732769 max : range. end ,
733770 } ) ;
734771 }
0 commit comments