@@ -689,15 +689,17 @@ int64_t bsv_movie_write_checkpoint(bsv_movie_t *handle, uint8_t compression, uin
689689 switch (encoding )
690690 {
691691 case REPLAY_CHECKPOINT2_ENCODING_RAW :
692- encoded_size = serial_info .size ;
692+ /* If serial_info.size > uint32 max, we have bigger problems on our hands */
693+ encoded_size = (uint32_t )serial_info .size ;
693694 encoded_data = (uint8_t * )serial_info .data ;
694695 break ;
695696#ifdef HAVE_STATESTREAM
696697 case REPLAY_CHECKPOINT2_ENCODING_STATESTREAM :
697- encoded_size = serial_info .size + serial_info .size / 2 ;
698+ /* encoded size estimate or actual encoded state size should not exceed uint32 max */
699+ encoded_size = (uint32_t )(serial_info .size + serial_info .size / 2 );
698700 encoded_data = (uint8_t * )malloc (encoded_size );
699701 owns_encoded = true;
700- encoded_size = bsv_movie_write_deduped_state (handle , (uint8_t * )serial_info .data ,
702+ encoded_size = ( uint32_t ) bsv_movie_write_deduped_state (handle , (uint8_t * )serial_info .data ,
701703 serial_info .size , encoded_data , encoded_size );
702704 break ;
703705#endif
@@ -723,23 +725,24 @@ int64_t bsv_movie_write_checkpoint(bsv_movie_t *handle, uint8_t compression, uin
723725 ret = -1 ;
724726 goto exit ;
725727 }
726- compressed_encoded_size = zlib_compressed_encoded_size ;
728+ compressed_encoded_size = ( uint32_t ) zlib_compressed_encoded_size ;
727729 break ;
728730 }
729731#endif
730732#ifdef HAVE_ZSTD
731733 case REPLAY_CHECKPOINT2_COMPRESSION_ZSTD :
732734 {
733- size_t compressed_encoded_size_big = ZSTD_compressBound (encoded_size );
734- compressed_encoded_data = (uint8_t * )calloc (compressed_encoded_size_big , sizeof (uint8_t ));
735+ size_t compressed_encoded_size = ZSTD_compressBound (encoded_size );
736+ compressed_encoded_data = (uint8_t * )calloc (compressed_encoded_size , sizeof (uint8_t ));
735737 owns_compressed_encoded = true;
736- compressed_encoded_size_big = ZSTD_compress (compressed_encoded_data , compressed_encoded_size_big , encoded_data , encoded_size , 3 );
737- if (ZSTD_isError (compressed_encoded_size_big ))
738+ compressed_encoded_size = ZSTD_compress (compressed_encoded_data , compressed_encoded_size , encoded_data , encoded_size , 3 );
739+ if (ZSTD_isError (compressed_encoded_size ))
738740 {
739741 ret = -1 ;
740742 goto exit ;
741743 }
742- compressed_encoded_size = compressed_encoded_size_big ;
744+ /* Have to cast after checking the error flags, not before */
745+ compressed_encoded_size = (uint32_t )compressed_encoded_size ;
743746 break ;
744747 }
745748#endif
@@ -749,7 +752,7 @@ int64_t bsv_movie_write_checkpoint(bsv_movie_t *handle, uint8_t compression, uin
749752 goto exit ;
750753 }
751754 /* uncompressed, unencoded size */
752- size_ = swap_if_big32 (serial_info .size );
755+ size_ = swap_if_big32 (( uint32_t ) serial_info .size );
753756 if (intfstream_write (handle -> file , & size_ , sizeof (uint32_t )) < (int64_t )sizeof (uint32_t ))
754757 {
755758 ret = -1 ;
@@ -1127,7 +1130,12 @@ bool replay_get_serialized_data(void* buffer)
11271130 buf = ((uint8_t * )buffer ) + sizeof (uint32_t );
11281131 intfstream_rewind (handle -> file );
11291132 read_amt = intfstream_read (handle -> file , buf , file_end );
1130- ((uint32_t * )buffer )[1 + REPLAY_HEADER_FRAME_COUNT_INDEX ] = swap_if_big32 (handle -> frame_counter );
1133+ if (handle -> frame_counter > UINT32_MAX ) {
1134+ RARCH_ERR ("[Replay] Frame counter too big to fit in 32 bits\n" );
1135+ return false;
1136+ }
1137+ /* Bounds checked above, this cast is safe */
1138+ ((uint32_t * )buffer )[1 + REPLAY_HEADER_FRAME_COUNT_INDEX ] = swap_if_big32 ((uint32_t )(handle -> frame_counter ));
11311139 if (read_amt != file_end )
11321140 RARCH_ERR ("[Replay] Failed to write correct number of replay bytes into state file: %d / %d.\n" ,
11331141 read_amt , file_end );
@@ -1585,7 +1593,8 @@ int64_t bsv_movie_write_deduped_state(bsv_movie_t *movie, uint8_t *state,
15851593 /* write "here is a new block" and new block to file */
15861594 rmsgpack_write_int (out_stream , BSV_IFRAME_NEW_BLOCK_TOKEN );
15871595 rmsgpack_write_int (out_stream , found_block .index );
1588- rmsgpack_write_bin (out_stream , state + block_start , block_byte_size );
1596+ /* Cast is fine, a single block can't be super big */
1597+ rmsgpack_write_bin (out_stream , state + block_start , (uint32_t )block_byte_size );
15891598 }
15901599 else
15911600 reused_blocks ++ ;
@@ -1597,7 +1606,8 @@ int64_t bsv_movie_write_deduped_state(bsv_movie_t *movie, uint8_t *state,
15971606 /* write "here is a new superblock" and new superblock to file */
15981607 rmsgpack_write_int (out_stream , BSV_IFRAME_NEW_SUPERBLOCK_TOKEN );
15991608 rmsgpack_write_int (out_stream , found_block .index );
1600- rmsgpack_write_array_header (out_stream , superblock_size );
1609+ /* Cast is fine, a single superblock can't be billions of blocks long */
1610+ rmsgpack_write_array_header (out_stream , (uint32_t )superblock_size );
16011611 for (i = 0 ; i < superblock_size ; i ++ )
16021612 rmsgpack_write_int (out_stream , superblock_buf [i ]);
16031613 }
@@ -1610,7 +1620,8 @@ int64_t bsv_movie_write_deduped_state(bsv_movie_t *movie, uint8_t *state,
16101620 /* uint32s_index_commit(movie->superblocks); */
16111621 /* write "here is the superblock seq" and superblock seq to file */
16121622 rmsgpack_write_int (out_stream , BSV_IFRAME_SUPERBLOCK_SEQ_TOKEN );
1613- rmsgpack_write_array_header (out_stream , superblock_count );
1623+ /* Cast is fine, we won't have billions of superblocks */
1624+ rmsgpack_write_array_header (out_stream , (uint32_t )superblock_count );
16141625 for (i = 0 ; i < superblock_count ; i ++ )
16151626 rmsgpack_write_int (out_stream , movie -> superblock_seq [i ]);
16161627 free (superblock_buf );
@@ -1684,7 +1695,8 @@ bool bsv_movie_read_deduped_state(bsv_movie_t *movie, uint8_t *encoded, size_t e
16841695 RARCH_ERR ("[STATESTREAM] new block index type is wrong\n" );
16851696 goto exit ;
16861697 }
1687- index = item .val .uint_ ;
1698+ /* Block indexes must be 32bit */
1699+ index = (uint32_t )item .val .uint_ ;
16881700 rmsgpack_dom_read_with (read_mem , & item , reader_state );
16891701 if (item .type != RDT_BINARY )
16901702 {
@@ -1715,7 +1727,8 @@ bool bsv_movie_read_deduped_state(bsv_movie_t *movie, uint8_t *encoded, size_t e
17151727 RARCH_ERR ("[STATESTREAM] new superblock index type is wrong\n" );
17161728 goto exit ;
17171729 }
1718- index = item .val .uint_ ;
1730+ /* Block indices are 32-bit */
1731+ index = (uint32_t )item .val .uint_ ;
17191732 if (rmsgpack_dom_read_with (read_mem , & item , reader_state ) < 0 )
17201733 {
17211734 RARCH_ERR ("[STATESTREAM] array read failed\n" );
@@ -1738,7 +1751,8 @@ bool bsv_movie_read_deduped_state(bsv_movie_t *movie, uint8_t *encoded, size_t e
17381751 {
17391752 struct rmsgpack_dom_value inner_item = item .val .array .items [i ];
17401753 /* assert(inner_item.type == RDT_INT || inner_item.type == RDT_UINT); */
1741- superblock [i ] = inner_item .val .uint_ ;
1754+ /* Superblock indices are 32-bit */
1755+ superblock [i ] = (uint32_t )inner_item .val .uint_ ;
17421756 }
17431757 if (!uint32s_index_insert_exact (movie -> superblocks , index , superblock , movie -> frame_counter ))
17441758 {
@@ -1766,7 +1780,8 @@ bool bsv_movie_read_deduped_state(bsv_movie_t *movie, uint8_t *encoded, size_t e
17661780 uint32_t * superblock ;
17671781 struct rmsgpack_dom_value inner_item = item .val .array .items [i ];
17681782 /* assert(inner_item.type == RDT_INT || inner_item.type == RDT_UINT); */
1769- uint32_t superblock_idx = inner_item .val .uint_ ;
1783+ /* Superblock indices are 32-bit */
1784+ uint32_t superblock_idx = (uint32_t )inner_item .val .uint_ ;
17701785 /* if this superblock is the same as last time, no need to scan the blocks. */
17711786 if (movie -> cur_save_valid && movie -> cur_save && superblock_idx == movie -> superblock_seq [i ])
17721787 {
0 commit comments