52
52
#define ENODATA 120
53
53
#endif
54
54
55
- // A more readable expression way to refer to the fact that there are 8 bytes
56
- // at the beginning of every message header.
57
- static const int32_t kMessageHeaderPrefixSize = 8 ;
58
-
59
55
#define NANOARROW_IPC_MAGIC "ARROW1"
60
56
61
57
// Internal representation of a parsed "Field" from flatbuffers. This
@@ -272,14 +268,6 @@ void ArrowIpcDecoderReset(struct ArrowIpcDecoder* decoder) {
272
268
}
273
269
}
274
270
275
- static inline uint32_t ArrowIpcReadContinuationBytes (struct ArrowBufferView * data ) {
276
- uint32_t value ;
277
- memcpy (& value , data -> data .as_uint8 , sizeof (uint32_t ));
278
- data -> data .as_uint8 += sizeof (uint32_t );
279
- data -> size_bytes -= sizeof (uint32_t );
280
- return value ;
281
- }
282
-
283
271
static inline int32_t ArrowIpcReadInt32LE (struct ArrowBufferView * data , int swap_endian ) {
284
272
int32_t value ;
285
273
memcpy (& value , data -> data .as_uint8 , sizeof (int32_t ));
@@ -984,40 +972,49 @@ static inline void ArrowIpcDecoderResetHeaderInfo(struct ArrowIpcDecoder* decode
984
972
985
973
// Returns NANOARROW_OK if data is large enough to read the first 8 bytes
986
974
// of the message header, ESPIPE if reading more data might help, or EINVAL if the content
987
- // is not valid. Advances the input ArrowBufferView by 8 bytes.
975
+ // is not valid. Advances the input ArrowBufferView by prefix_size (8 bytes or 4 bytes if
976
+ // the message is pre-0.15 and has no continuation). Sets decoder->header_size_bytes
977
+ // to the flatbuffers length plus the prefix_size.
988
978
static inline int ArrowIpcDecoderReadHeaderPrefix (struct ArrowIpcDecoder * decoder ,
989
979
struct ArrowBufferView * data_mut ,
990
- int32_t * message_size_bytes ,
980
+ int32_t * prefix_size_bytes ,
991
981
struct ArrowError * error ) {
992
982
struct ArrowIpcDecoderPrivate * private_data =
993
983
(struct ArrowIpcDecoderPrivate * )decoder -> private_data ;
994
984
995
- if (data_mut -> size_bytes < kMessageHeaderPrefixSize ) {
985
+ if (data_mut -> size_bytes < 8 ) {
996
986
ArrowErrorSet (error ,
997
987
"Expected data of at least 8 bytes but only %" PRId64 " bytes remain" ,
998
988
data_mut -> size_bytes );
999
989
return ESPIPE ;
1000
990
}
1001
991
1002
- uint32_t continuation = ArrowIpcReadContinuationBytes (data_mut );
1003
- if (continuation != 0xFFFFFFFF ) {
1004
- ArrowErrorSet (error , "Expected 0xFFFFFFFF at start of message but found 0x%08X" ,
1005
- (unsigned int )continuation );
1006
- return EINVAL ;
992
+ int swap_endian = private_data -> system_endianness == NANOARROW_IPC_ENDIANNESS_BIG ;
993
+ int32_t continuation = ArrowIpcReadInt32LE (data_mut , swap_endian );
994
+ int32_t length ;
995
+ if ((uint32_t )continuation != 0xFFFFFFFF ) {
996
+ if (continuation < 0 ) {
997
+ ArrowErrorSet (error , "Expected 0xFFFFFFFF at start of message but found 0x%08X" ,
998
+ (unsigned int )continuation );
999
+ return EINVAL ;
1000
+ }
1001
+ // Tolerate pre-0.15 encapsulated messages which only had the length prefix
1002
+ length = continuation ;
1003
+ * prefix_size_bytes = sizeof (length );
1004
+ } else {
1005
+ length = ArrowIpcReadInt32LE (data_mut , swap_endian );
1006
+ * prefix_size_bytes = sizeof (continuation ) + sizeof (length );
1007
1007
}
1008
+ decoder -> header_size_bytes = * prefix_size_bytes + length ;
1008
1009
1009
- int swap_endian = private_data -> system_endianness == NANOARROW_IPC_ENDIANNESS_BIG ;
1010
- int32_t header_body_size_bytes = ArrowIpcReadInt32LE (data_mut , swap_endian );
1011
- * message_size_bytes = header_body_size_bytes + kMessageHeaderPrefixSize ;
1012
- if (header_body_size_bytes < 0 ) {
1010
+ if (length < 0 ) {
1013
1011
ArrowErrorSet (error ,
1014
- "Expected message body size > 0 but found message body size of %" PRId32
1015
- " bytes" ,
1016
- header_body_size_bytes );
1012
+ "Expected message size > 0 but found message size of %" PRId32 " bytes" ,
1013
+ length );
1017
1014
return EINVAL ;
1018
1015
}
1019
1016
1020
- if (header_body_size_bytes == 0 ) {
1017
+ if (length == 0 ) {
1021
1018
ArrowErrorSet (error , "End of Arrow stream" );
1022
1019
return ENODATA ;
1023
1020
}
@@ -1029,8 +1026,10 @@ ArrowErrorCode ArrowIpcDecoderPeekHeader(struct ArrowIpcDecoder* decoder,
1029
1026
struct ArrowBufferView data ,
1030
1027
struct ArrowError * error ) {
1031
1028
ArrowIpcDecoderResetHeaderInfo (decoder );
1032
- NANOARROW_RETURN_NOT_OK (ArrowIpcDecoderReadHeaderPrefix (
1033
- decoder , & data , & decoder -> header_size_bytes , error ));
1029
+ int32_t prefix_size_bytes ;
1030
+ NANOARROW_RETURN_NOT_OK (
1031
+ ArrowIpcDecoderReadHeaderPrefix (decoder , & data , & prefix_size_bytes , error ));
1032
+ NANOARROW_UNUSED (prefix_size_bytes );
1034
1033
return NANOARROW_OK ;
1035
1034
}
1036
1035
@@ -1041,24 +1040,24 @@ ArrowErrorCode ArrowIpcDecoderVerifyHeader(struct ArrowIpcDecoder* decoder,
1041
1040
(struct ArrowIpcDecoderPrivate * )decoder -> private_data ;
1042
1041
1043
1042
ArrowIpcDecoderResetHeaderInfo (decoder );
1044
- NANOARROW_RETURN_NOT_OK (ArrowIpcDecoderReadHeaderPrefix (
1045
- decoder , & data , & decoder -> header_size_bytes , error ));
1043
+ int32_t prefix_size_bytes ;
1044
+ NANOARROW_RETURN_NOT_OK (
1045
+ ArrowIpcDecoderReadHeaderPrefix (decoder , & data , & prefix_size_bytes , error ));
1046
1046
1047
1047
// Check that data contains at least the entire header (return ESPIPE to signal
1048
1048
// that reading more data may help).
1049
- int64_t message_body_size = decoder -> header_size_bytes - kMessageHeaderPrefixSize ;
1050
- if (data .size_bytes < message_body_size ) {
1049
+ if (data .size_bytes < decoder -> header_size_bytes - prefix_size_bytes ) {
1051
1050
ArrowErrorSet (error ,
1052
- "Expected >= %" PRId64 " bytes of remaining data but found %" PRId64
1051
+ "Expected >= %d bytes of remaining data but found %" PRId64
1053
1052
" bytes in buffer" ,
1054
- message_body_size + kMessageHeaderPrefixSize ,
1055
- data .size_bytes + kMessageHeaderPrefixSize );
1053
+ decoder -> header_size_bytes , data .size_bytes + prefix_size_bytes );
1056
1054
return ESPIPE ;
1057
1055
}
1058
1056
1059
1057
// Run flatbuffers verification
1060
1058
enum flatcc_verify_error_no verify_error =
1061
- ns (Message_verify_as_root (data .data .as_uint8 , message_body_size );
1059
+ ns (Message_verify_as_root (data .data .as_uint8 ,
1060
+ decoder -> header_size_bytes - prefix_size_bytes );
1062
1061
if (verify_error != flatcc_verify_ok )) {
1063
1062
ArrowErrorSet (error , "Message flatbuffer verification failed (%d) %s" ,
1064
1063
(int )verify_error , flatcc_verify_error_string (verify_error ));
@@ -1163,18 +1162,17 @@ ArrowErrorCode ArrowIpcDecoderDecodeHeader(struct ArrowIpcDecoder* decoder,
1163
1162
(struct ArrowIpcDecoderPrivate * )decoder -> private_data ;
1164
1163
1165
1164
ArrowIpcDecoderResetHeaderInfo (decoder );
1166
- NANOARROW_RETURN_NOT_OK (ArrowIpcDecoderReadHeaderPrefix (
1167
- decoder , & data , & decoder -> header_size_bytes , error ));
1165
+ int32_t prefix_size_bytes ;
1166
+ NANOARROW_RETURN_NOT_OK (
1167
+ ArrowIpcDecoderReadHeaderPrefix (decoder , & data , & prefix_size_bytes , error ));
1168
1168
1169
1169
// Check that data contains at least the entire header (return ESPIPE to signal
1170
1170
// that reading more data may help).
1171
- int64_t message_body_size = decoder -> header_size_bytes - kMessageHeaderPrefixSize ;
1172
- if (data .size_bytes < message_body_size ) {
1171
+ if (data .size_bytes < decoder -> header_size_bytes - prefix_size_bytes ) {
1173
1172
ArrowErrorSet (error ,
1174
- "Expected >= %" PRId64 " bytes of remaining data but found %" PRId64
1173
+ "Expected >= %d bytes of remaining data but found %" PRId64
1175
1174
" bytes in buffer" ,
1176
- message_body_size + kMessageHeaderPrefixSize ,
1177
- data .size_bytes + kMessageHeaderPrefixSize );
1175
+ decoder -> header_size_bytes , data .size_bytes + prefix_size_bytes );
1178
1176
return ESPIPE ;
1179
1177
}
1180
1178
0 commit comments