@@ -68,35 +68,47 @@ static struct remote_header_v0 *
6868localized_remote_header (pcmk__remote_t * remote )
6969{
7070 struct remote_header_v0 * header = NULL ;
71- uint32_t endian_swapped = 0 ;
7271
7372 if ((remote == NULL ) || (remote -> buffer == NULL )
7473 || (remote -> buffer_offset < sizeof (struct remote_header_v0 ))) {
74+
75+ // Caller error or we haven't received the full header yet
7576 return NULL ;
7677 }
7778
7879 header = (struct remote_header_v0 * ) remote -> buffer ;
79- if (header -> endian == ENDIAN_LOCAL ) {
80- return header ;
81- }
82-
83- endian_swapped = GUINT32_SWAP_LE_BE (header -> endian );
84- CRM_CHECK (endian_swapped == ENDIAN_LOCAL ,
85- crm_err ("Invalid message detected (endian mismatch): local magic "
86- "number %" PRIx32 " matches neither the header's magic "
87- "number %" PRIx32 " nor the byte-swapped form %" PRIx32 ,
88- ENDIAN_LOCAL , header -> endian , endian_swapped );
89- return NULL );
90-
91- header -> endian = endian_swapped ;
92- header -> version = GUINT32_SWAP_LE_BE (header -> version );
93- header -> id = GUINT64_SWAP_LE_BE (header -> id );
94- header -> flags = GUINT64_SWAP_LE_BE (header -> flags );
95- header -> size_total = GUINT32_SWAP_LE_BE (header -> size_total );
96- header -> payload_offset = GUINT32_SWAP_LE_BE (header -> payload_offset );
97- header -> payload_compressed = GUINT32_SWAP_LE_BE (header -> payload_compressed );
98- header -> payload_uncompressed =
99- GUINT32_SWAP_LE_BE (header -> payload_uncompressed );
80+ if (header -> endian != ENDIAN_LOCAL ) {
81+ uint32_t endian_swapped = GUINT32_SWAP_LE_BE (header -> endian );
82+
83+ CRM_CHECK (endian_swapped == ENDIAN_LOCAL ,
84+ crm_err ("Invalid message detected (endian mismatch): local "
85+ "magic number %" PRIx32 " matches neither the "
86+ "header's magic number %" PRIx32 " nor the "
87+ "byte-swapped form %" PRIx32 ,
88+ ENDIAN_LOCAL , header -> endian , endian_swapped );
89+ return NULL );
90+
91+ header -> endian = endian_swapped ;
92+ header -> version = GUINT32_SWAP_LE_BE (header -> version );
93+ header -> id = GUINT64_SWAP_LE_BE (header -> id );
94+ header -> flags = GUINT64_SWAP_LE_BE (header -> flags );
95+ header -> size_total = GUINT32_SWAP_LE_BE (header -> size_total );
96+ header -> payload_offset = GUINT32_SWAP_LE_BE (header -> payload_offset );
97+ header -> payload_compressed =
98+ GUINT32_SWAP_LE_BE (header -> payload_compressed );
99+ header -> payload_uncompressed =
100+ GUINT32_SWAP_LE_BE (header -> payload_uncompressed );
101+ }
102+
103+ // Sanity checks
104+ if (header -> payload_offset != sizeof (struct remote_header_v0 )) {
105+ return NULL ;
106+ }
107+ if ((header -> payload_offset
108+ + header -> payload_compressed
109+ + header -> payload_uncompressed ) != header -> size_total ) {
110+ return NULL ;
111+ }
100112
101113 return header ;
102114}
@@ -268,6 +280,8 @@ xmlNode *
268280pcmk__remote_message_xml (pcmk__remote_t * remote )
269281{
270282 xmlNode * xml = NULL ;
283+ size_t data_size = 0 ;
284+ const char * payload = NULL ;
271285 struct remote_header_v0 * header = localized_remote_header (remote );
272286
273287 if (header == NULL ) {
@@ -315,18 +329,33 @@ pcmk__remote_message_xml(pcmk__remote_t *remote)
315329 /* take ownership of the buffer */
316330 remote -> buffer_offset = 0 ;
317331
318- CRM_LOG_ASSERT ( remote -> buffer [ sizeof ( struct remote_header_v0 ) + header -> payload_uncompressed - 1 ] == 0 ) ;
332+ data_size = ( size_t ) header -> payload_offset + header -> payload_uncompressed ;
319333
320- xml = pcmk__xml_parse (remote -> buffer + header -> payload_offset );
321- if (xml == NULL && header -> version > REMOTE_MSG_VERSION ) {
322- crm_warn ("Couldn't parse v%d message, we only understand v%d" ,
323- header -> version , REMOTE_MSG_VERSION );
334+ // Ensure the buffer is as big as it should be
335+ CRM_CHECK (remote -> buffer_size >= data_size , return NULL );
324336
325- } else if (xml == NULL ) {
326- crm_err ("Couldn't parse: '%.120s'" , remote -> buffer + header -> payload_offset );
327- }
337+ /* Ensure the buffer is null-terminated (see
338+ * pcmk__read_available_remote_data()).
339+ *
340+ * Note that payload_uncompressed contains the payload size including the
341+ * null byte (see pcmk__remote_send_xml()).
342+ */
343+ CRM_CHECK (remote -> buffer [data_size ] == '\0' , return NULL );
344+
345+ payload = remote -> buffer + header -> payload_offset ;
346+
347+ xml = pcmk__xml_parse (payload );
348+ if (xml == NULL ) {
349+ if (header -> version > REMOTE_MSG_VERSION ) {
350+ crm_warn ("Couldn't parse v%d message, we only understand v%d" ,
351+ header -> version , REMOTE_MSG_VERSION );
352+ } else {
353+ crm_err ("Couldn't parse: '%.120s'" , payload );
354+ }
328355
329- crm_log_xml_trace (xml , "[remote msg]" );
356+ } else {
357+ crm_log_xml_trace (xml , "[remote msg]" );
358+ }
330359 return xml ;
331360}
332361
0 commit comments