LCOV - code coverage report
Current view: top level - discof/restore/utils - fd_zstd_frame.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 95 0.0 %
Date: 2026-10-22 18:10:43 Functions: 0 1 0.0 %

          Line data    Source code
       1             : #include "fd_zstd_frame.h"
       2             : 
       3             : #include "../../../util/bits/fd_bits.h"
       4             : #include "../../../util/log/fd_log.h"
       5             : 
       6             : #define ZSTD_STATIC_LINKING_ONLY
       7             : #include <zstd.h>
       8             : 
       9             : /* Different states of the ZSTD frame parser state machine */
      10           0 : #define FD_ZSTD_FRAME_STATE_HEADER       (0U)
      11           0 : #define FD_ZSTD_FRAME_STATE_BLOCK_HEADER (1U)
      12           0 : #define FD_ZSTD_FRAME_STATE_PAYLOAD      (2U)
      13           0 : #define FD_ZSTD_FRAME_STATE_SKIPPABLE    (3U)
      14           0 : #define FD_ZSTD_FRAME_STATE_END          (4U)
      15           0 : #define FD_ZSTD_FRAME_STATE_ERR          (5U)
      16             : 
      17             : /* Different block types
      18             :    https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#blocks */
      19             : #define FD_ZSTD_FRAME_BLOCK_TYPE_RAW        (0U)
      20           0 : #define FD_ZSTD_FRAME_BLOCK_TYPE_RLE        (1U)
      21             : #define FD_ZSTD_FRAME_BLOCK_TYPE_COMPRESSED (2U)
      22             : #define FD_ZSTD_FRAME_BLOCK_TYPE_RESERVED   (3U)
      23             : 
      24           0 : #define FAIL_IF( c, frame, consumed, off ) do { \
      25           0 :   if( FD_UNLIKELY( c ) ) {                      \
      26           0 :     (frame)->state = FD_ZSTD_FRAME_STATE_ERR;   \
      27           0 :     *(consumed)    = (off);                     \
      28           0 :     return FD_ZSTD_FRAME_ERR;                   \
      29           0 :   }                                             \
      30           0 : } while( 0 )
      31             : 
      32             : int
      33             : fd_zstd_frame_advance( fd_zstd_frame_t * frame,
      34             :                        void const *      data,
      35             :                        ulong             data_sz,
      36           0 :                        ulong *           consumed ) {
      37           0 :   uchar const * bytes = (uchar const *)data;
      38           0 :   ulong off = 0UL;
      39             : 
      40           0 :   for(;;) {
      41           0 :     switch( frame->state ) {
      42           0 :       case FD_ZSTD_FRAME_STATE_HEADER: {
      43           0 :         ZSTD_frameHeader header[1];
      44             : 
      45           0 :         for(;;) {
      46           0 :           ulong rc = ZSTD_getFrameHeader( header, frame->header, frame->header_sz );
      47           0 :           FAIL_IF( ZSTD_isError( rc ), frame, consumed, off );
      48             : 
      49           0 :           if( !rc ) break;
      50             : 
      51             :           /* Library invariants for rc > 0 */
      52           0 :           FD_TEST( rc<=FD_ZSTD_FRAME_HEADER_MAX );
      53           0 :           FD_TEST( frame->header_sz<rc );
      54             : 
      55           0 :           if( off==data_sz ) {
      56           0 :             *consumed = off;
      57           0 :             return FD_ZSTD_FRAME_MORE;
      58           0 :           }
      59             : 
      60           0 :           ulong need    = rc-frame->header_sz;
      61           0 :           ulong copy_sz = fd_ulong_min( need, data_sz-off );
      62             : 
      63           0 :           fd_memcpy( frame->header+frame->header_sz, bytes+off, copy_sz );
      64           0 :           frame->header_sz += (uchar)copy_sz;
      65           0 :           off              += copy_sz;
      66           0 :         }
      67             : 
      68           0 :         if( header->frameType==ZSTD_skippableFrame ) {
      69           0 :           frame->bytes_remaining = (ulong)header->frameContentSize;
      70           0 :           frame->state           = FD_ZSTD_FRAME_STATE_SKIPPABLE;
      71           0 :         } else {
      72           0 :           frame->block_sz_max = header->blockSizeMax;
      73           0 :           frame->checksum_sz  = header->checksumFlag ? 4U : 0U;
      74           0 :           frame->state        = FD_ZSTD_FRAME_STATE_BLOCK_HEADER;
      75           0 :         }
      76           0 :         continue;
      77           0 :       }
      78             : 
      79           0 :       case FD_ZSTD_FRAME_STATE_BLOCK_HEADER: {
      80           0 :         ulong need    = FD_ZSTD_FRAME_BLOCK_HEADER_SZ-frame->block_header_sz;
      81           0 :         ulong copy_sz = fd_ulong_min( need, data_sz-off );
      82             : 
      83           0 :         fd_memcpy( frame->block_header+frame->block_header_sz, bytes+off, copy_sz );
      84           0 :         frame->block_header_sz += (uchar)copy_sz;
      85           0 :         off                    += copy_sz;
      86             : 
      87           0 :         if( FD_UNLIKELY( copy_sz<need ) ) {
      88           0 :           *consumed = data_sz;
      89           0 :           return FD_ZSTD_FRAME_MORE;
      90           0 :         }
      91             : 
      92           0 :         uint block_header = fd_uint_load_3( frame->block_header );
      93           0 :         uint last_block   = block_header & 1U;      /* bit 0 */
      94           0 :         uint block_type   = (block_header>>1) & 3U; /* bits 1-2 */
      95           0 :         uint block_sz     = block_header>>3;        /* bits 3-23 */
      96             : 
      97           0 :         FAIL_IF( block_type==FD_ZSTD_FRAME_BLOCK_TYPE_RESERVED || block_sz>frame->block_sz_max, frame, consumed, off );
      98             : 
      99           0 :         frame->block_header_sz = 0U;
     100           0 :         frame->last_block      = (uchar)last_block;
     101           0 :         frame->bytes_remaining = block_type==FD_ZSTD_FRAME_BLOCK_TYPE_RLE ? 1UL : (ulong)block_sz;
     102           0 :         frame->state           = FD_ZSTD_FRAME_STATE_PAYLOAD;
     103             : 
     104           0 :         if( last_block ) frame->bytes_remaining += frame->checksum_sz;
     105             : 
     106           0 :         continue;
     107           0 :       }
     108             : 
     109           0 :       case FD_ZSTD_FRAME_STATE_PAYLOAD:
     110           0 :       case FD_ZSTD_FRAME_STATE_SKIPPABLE: {
     111           0 :         ulong skip = fd_ulong_min( frame->bytes_remaining, data_sz-off );
     112           0 :         frame->bytes_remaining -= skip;
     113           0 :         off                    += skip;
     114             : 
     115           0 :         if( frame->bytes_remaining ) {
     116           0 :           *consumed = data_sz;
     117           0 :           return FD_ZSTD_FRAME_MORE;
     118           0 :         }
     119             : 
     120           0 :         if( frame->state==FD_ZSTD_FRAME_STATE_PAYLOAD && !frame->last_block ) {
     121           0 :           frame->state = FD_ZSTD_FRAME_STATE_BLOCK_HEADER;
     122           0 :           continue;
     123           0 :         }
     124             : 
     125           0 :         frame->state = FD_ZSTD_FRAME_STATE_END;
     126           0 :         *consumed    = off;
     127           0 :         return FD_ZSTD_FRAME_END;
     128           0 :       }
     129             : 
     130           0 :       case FD_ZSTD_FRAME_STATE_END:
     131           0 :         *consumed = 0UL;
     132           0 :         return FD_ZSTD_FRAME_END;
     133             : 
     134           0 :       default:
     135           0 :         *consumed = 0UL;
     136           0 :         return FD_ZSTD_FRAME_ERR;
     137           0 :     }
     138           0 :   }
     139           0 : }

Generated by: LCOV version 1.14