Line data Source code
1 : #ifndef HEADER_fd_src_waltz_tls_fd_tls_serde_h 2 : #define HEADER_fd_src_waltz_tls_fd_tls_serde_h 3 : 4 : /* fd_tls_serde.h provides branch-minimizing (de-)serializer macros for 5 : internal use. This file specifically exists for fd_tls_proto.c and 6 : should not be included elsewhere. */ 7 : 8 : /* FD_TLS_SERDE_{BEGIN,END} create and terminate a bounds checking 9 : context. Internally, creates a new do/while(0) scope. */ 10 : 11 : #include "fd_tls_proto.h" 12 408168 : #define FD_TLS_SERDE_BEGIN do { \ 13 408168 : int valid = 1; \ 14 : 15 408165 : #define FD_TLS_SERDE_END } while(0); 16 : 17 : /* FD_TLS_SERDE_LOCATE defines a local variable pointing to the would- 18 : be position of the field to be decoded, which may be out-of-bounds. 19 : Also extends the "valid" expression to include a bounds check for 20 : this field. Both the "valid" expression and this local can be fully 21 : constant-propagated if sz is constant. */ 22 : 23 : #define FD_TLS_SERDE_LOCATE( IDX, FIELD, FIELD_TYPE, FIELD_CNT ) \ 24 1044090 : ulong _field_##IDX##_laddr = wire_laddr; \ 25 1044090 : ulong const _field_##IDX##_cnt = (FIELD_CNT); \ 26 1044090 : ulong const _field_##IDX##_sz = sizeof(FIELD_TYPE)*_field_##IDX##_cnt; \ 27 1044090 : valid &= (wire_sz >= _field_##IDX##_sz); \ 28 1044090 : wire_sz -= _field_##IDX##_sz; \ 29 1044090 : wire_laddr += _field_##IDX##_sz; 30 : 31 : /* FD_TLS_SERDE_CHECK performs the bounds checks queued by prior 32 : FD_TLS_SERDE_LOCATE ops. */ 33 : 34 : #define FD_TLS_SERDE_CHECK \ 35 472071 : if( FD_UNLIKELY( !valid ) ) return -(long)FD_TLS_ALERT_DECODE_ERROR; 36 : 37 : /* FD_TLS_SERDE_DECODE generates a non-overlapping memory copy for the 38 : given field. Field should be bounds checked at this point. 39 : 40 : Note: We use __extension__ here because ISO C forbids casting a 41 : non-scalar type to itself. (as is the case with tls_u24). */ 42 : 43 : #define FD_TLS_SERDE_DECODE( IDX, FIELD, FIELD_TYPE, FIELD_CNT ) \ 44 492999 : do { \ 45 492999 : if( _field_##IDX##_sz ) \ 46 492999 : memcpy( (FIELD), (void const *)_field_##IDX##_laddr, _field_##IDX##_sz ); \ 47 492999 : FIELD_TYPE * _field_##IDX##_ptr = (FIELD); \ 48 1505031 : for( ulong i=0; i < (FIELD_CNT); i++ ) { \ 49 1012032 : *((_field_##IDX##_ptr)++) = __extension__ \ 50 1012032 : (FIELD_TYPE)fd_##FIELD_TYPE##_bswap( (FIELD)[i] ); \ 51 1012032 : } \ 52 492999 : } while(0); 53 : 54 : #define FD_TLS_SERDE_ENCODE( IDX, FIELD, FIELD_TYPE, FIELD_CNT ) \ 55 487170 : do { \ 56 487167 : uchar * dest = (uchar *)_field_##IDX##_laddr; \ 57 487167 : if( _field_##IDX##_sz ) \ 58 487167 : memcpy( dest, (FIELD), _field_##IDX##_sz ); \ 59 4777338 : for( ulong i=0; i<(FIELD_CNT); i++ ) { \ 60 4290171 : FIELD_TYPE temp; \ 61 4290171 : memcpy( &temp, dest, sizeof(FIELD_TYPE) ); \ 62 4290171 : temp = fd_##FIELD_TYPE##_bswap( temp ); \ 63 4290171 : memcpy( dest, &temp, sizeof(FIELD_TYPE) ); \ 64 4290171 : dest += sizeof(FIELD_TYPE); \ 65 4290171 : } \ 66 487167 : } while(0); 67 : 68 : /* FD_TLS_DECODE_FIELD is a convenience macro for decoding a single 69 : field with known size. */ 70 : 71 : #define FD_TLS_DECODE_FIELD( FIELD, FIELD_TYPE ) \ 72 182652 : FD_TLS_SERDE_BEGIN \ 73 182652 : FD_TLS_SERDE_LOCATE( _, FIELD, FIELD_TYPE, 1 ) \ 74 182652 : FD_TLS_SERDE_CHECK \ 75 182652 : FD_TLS_SERDE_DECODE( _, FIELD, FIELD_TYPE, 1 ) \ 76 182652 : FD_TLS_SERDE_END 77 : 78 : #define FD_TLS_ENCODE_FIELD( FIELD, FIELD_TYPE ) \ 79 : FD_TLS_SERDE_BEGIN \ 80 : FD_TLS_SERDE_LOCATE( _, FIELD, FIELD_TYPE, 1 ) \ 81 : FD_TLS_SERDE_CHECK \ 82 : FD_TLS_SERDE_ENCODE( _, FIELD, FIELD_TYPE, 1 ) \ 83 : FD_TLS_SERDE_END 84 : 85 : /* FD_TLS_DECODE_STATIC_BATCH is a convenience macro for decoding a 86 : batch of static sized fields in a new decode context. */ 87 : 88 : #define FD_TLS_DECODE_STATIC_BATCH( fields ) \ 89 146802 : FD_TLS_SERDE_BEGIN \ 90 310347 : fields( FD_TLS_SERDE_LOCATE ) \ 91 146802 : FD_TLS_SERDE_CHECK \ 92 310347 : fields( FD_TLS_SERDE_DECODE ) \ 93 146802 : FD_TLS_SERDE_END 94 : 95 : #define FD_TLS_ENCODE_STATIC_BATCH( fields ) \ 96 88551 : FD_TLS_SERDE_BEGIN \ 97 487188 : fields( FD_TLS_SERDE_LOCATE ) \ 98 88551 : FD_TLS_SERDE_CHECK \ 99 487170 : fields( FD_TLS_SERDE_ENCODE ) \ 100 78711 : FD_TLS_SERDE_END 101 : 102 : #define FD_TLS_DECODE_LIST_BEGIN( LIST_SZ_TYPE, ALIGN ) \ 103 67800 : do { \ 104 67800 : LIST_SZ_TYPE list_sz; \ 105 67800 : FD_TLS_DECODE_FIELD( &list_sz, LIST_SZ_TYPE ); \ 106 67800 : if( FD_UNLIKELY( !fd_ulong_is_aligned( list_sz, (ALIGN) ) ) ) \ 107 67800 : return -(long)FD_TLS_ALERT_DECODE_ERROR; \ 108 67800 : if( FD_UNLIKELY( list_sz > wire_sz ) ) \ 109 67800 : return -(long)FD_TLS_ALERT_DECODE_ERROR; \ 110 67800 : ulong const list_start = wire_laddr; \ 111 67797 : ulong const list_stop = list_start + list_sz; \ 112 250812 : while( wire_laddr < list_stop ) \ 113 : 114 : #define FD_TLS_DECODE_LIST_END \ 115 67704 : if( FD_UNLIKELY( wire_laddr != list_stop ) ) \ 116 67704 : return -(long)FD_TLS_ALERT_DECODE_ERROR; \ 117 67704 : } while(0); \ 118 : 119 63903 : #define FD_TLS_SKIP_FIELD( FIELD_TYPE ) (__extension__({ \ 120 63903 : int valid = 1; \ 121 63903 : FD_TLS_SERDE_LOCATE( , , FIELD_TYPE, 1 ) \ 122 63903 : FD_TLS_SERDE_CHECK \ 123 63903 : (FIELD_TYPE *)fd_type_pun( (void *)_field__laddr ); \ 124 63870 : })) 125 : 126 : #define FD_TLS_SKIP_FIELDS( FIELD_TYPE, CNT ) (__extension__({ \ 127 : int valid = 1; \ 128 : FD_TLS_SERDE_LOCATE( , , FIELD_TYPE, (CNT) ) \ 129 : FD_TLS_SERDE_CHECK \ 130 : (FIELD_TYPE *)_field__laddr; \ 131 : })) 132 : 133 7254 : #define FD_TLS_DECODE_SUB( FUNC, OUT ) do { \ 134 7254 : long res = FUNC( (OUT), (void const *)wire_laddr, wire_sz ); \ 135 7254 : if( FD_UNLIKELY( res<0L ) ) return res; \ 136 7254 : wire_laddr += (ulong)res; \ 137 7248 : wire_sz -= (ulong)res; \ 138 7248 : } while(0) 139 : 140 28086 : #define FD_TLS_ENCODE_SUB( FUNC, IN ) (__extension__({ \ 141 28086 : long res = FUNC( (IN), (void *)wire_laddr, wire_sz ); \ 142 28086 : if( FD_UNLIKELY( res<0L ) ) return res; \ 143 28086 : wire_laddr += (ulong)res; \ 144 28086 : wire_sz -= (ulong)res; \ 145 28086 : (ulong)res; \ 146 28086 : })) 147 : 148 : #endif /* HEADER_fd_src_waltz_tls_fd_tls_serde_h */