@@ -565,6 +565,14 @@ void USBMSD::_read_next()
565565
566566void USBMSD::memoryWrite (uint8_t *buf, uint16_t size)
567567{
568+ // Max sized packets are required to be sent until the transfer is complete
569+ MBED_ASSERT (_block_size % MAX_PACKET == 0 );
570+ if ((size != MAX_PACKET) && (size != 0 )) {
571+ _stage = ERROR;
572+ endpoint_stall (_bulk_out);
573+ return ;
574+ }
575+
568576 if ((_addr + size) > _memory_size) {
569577 size = _memory_size - _addr;
570578 _stage = ERROR;
@@ -869,23 +877,25 @@ void USBMSD::memoryRead(void)
869877
870878 n = (_length > MAX_PACKET) ? MAX_PACKET : _length;
871879
872- if (( _addr + n) > _memory_size) {
873- n = _memory_size - _addr;
880+ if (_addr > ( _memory_size - n) ) {
881+ n = _addr < _memory_size ? _memory_size - _addr : 0 ;
874882 _stage = ERROR;
875883 }
876884
877- // we read an entire block
878- if (!(_addr % _block_size)) {
879- disk_read (_page, _addr / _block_size, 1 );
880- }
885+ if (n > 0 ) {
886+ // we read an entire block
887+ if (!(_addr % _block_size)) {
888+ disk_read (_page, _addr / _block_size, 1 );
889+ }
881890
882- // write data which are in RAM
883- _write_next (&_page[_addr % _block_size], MAX_PACKET);
891+ // write data which are in RAM
892+ _write_next (&_page[_addr % _block_size], MAX_PACKET);
884893
885- _addr += n;
886- _length -= n;
894+ _addr += n;
895+ _length -= n;
887896
888- _csw.DataResidue -= n;
897+ _csw.DataResidue -= n;
898+ }
889899
890900 if (!_length || (_stage != PROCESS_CBW)) {
891901 _csw.Status = (_stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED;
@@ -896,30 +906,37 @@ void USBMSD::memoryRead(void)
896906
897907bool USBMSD::infoTransfer (void )
898908{
899- uint32_t n ;
909+ uint32_t addr_block ;
900910
901911 // Logical Block Address of First Block
902- n = (_cbw.CB [2 ] << 24 ) | (_cbw.CB [3 ] << 16 ) | (_cbw.CB [4 ] << 8 ) | (_cbw.CB [5 ] << 0 );
912+ addr_block = (_cbw.CB [2 ] << 24 ) | (_cbw.CB [3 ] << 16 ) | (_cbw.CB [4 ] << 8 ) | (_cbw.CB [5 ] << 0 );
913+
914+ _addr = addr_block * _block_size;
903915
904- _addr = n * _block_size;
916+ if ((addr_block >= _block_count) || (_addr >= _memory_size)) {
917+ _csw.Status = CSW_FAILED;
918+ sendCSW ();
919+ return false ;
920+ }
905921
922+ uint32_t length_blocks = 0 ;
906923 // Number of Blocks to transfer
907924 switch (_cbw.CB [0 ]) {
908925 case READ10:
909926 case WRITE10:
910927 case VERIFY10:
911- n = (_cbw.CB [7 ] << 8 ) | (_cbw.CB [8 ] << 0 );
928+ length_blocks = (_cbw.CB [7 ] << 8 ) | (_cbw.CB [8 ] << 0 );
912929 break ;
913930
914931 case READ12:
915932 case WRITE12:
916- n = (_cbw.CB [6 ] << 24 ) | (_cbw.CB [7 ] << 16 ) | (_cbw.CB [8 ] << 8 ) | (_cbw.CB [9 ] << 0 );
933+ length_blocks = (_cbw.CB [6 ] << 24 ) | (_cbw.CB [7 ] << 16 ) | (_cbw.CB [8 ] << 8 ) | (_cbw.CB [9 ] << 0 );
917934 break ;
918935 }
919936
920- _length = n * _block_size;
937+ _length = length_blocks * _block_size;
921938
922- if (!_cbw.DataLength ) { // host requests no data
939+ if (!_cbw.DataLength || !length_blocks || (length_blocks > _block_count - addr_block) || (_length > _memory_size - _addr)) { // host requests no data or wrong length
923940 _csw.Status = CSW_FAILED;
924941 sendCSW ();
925942 return false ;
0 commit comments