@@ -1052,9 +1052,14 @@ row_log_event_uncompress(const Format_description_log_event *description_event,
1052
1052
1053
1053
uint32 binlog_get_uncompress_len (const char *buf)
1054
1054
{
1055
- DBUG_ASSERT ((buf[0 ] & 0xe0 ) == 0x80 );
1056
- uint32 lenlen = buf[0 ] & 0x07 ;
1057
1055
uint32 len = 0 ;
1056
+ uint32 lenlen = 0 ;
1057
+
1058
+ if ((buf == NULL ) || ((buf[0 ] & 0xe0 ) != 0x80 ))
1059
+ return len;
1060
+
1061
+ lenlen = buf[0 ] & 0x07 ;
1062
+
1058
1063
switch (lenlen)
1059
1064
{
1060
1065
case 1 :
@@ -4578,6 +4583,17 @@ code_name(int code)
4578
4583
}
4579
4584
#endif
4580
4585
4586
+ #define VALIDATE_BYTES_READ (CUR_POS, START, EVENT_LEN ) \
4587
+ do { \
4588
+ uchar *cur_pos= (uchar *)CUR_POS; \
4589
+ uchar *start= (uchar *)START; \
4590
+ uint len= EVENT_LEN; \
4591
+ uint bytes_read= (uint)(cur_pos - start); \
4592
+ DBUG_PRINT (" info" , (" Bytes read: %u event_len:%u.\n " ,\
4593
+ bytes_read, len)); \
4594
+ if (bytes_read >= len) \
4595
+ DBUG_VOID_RETURN; \
4596
+ } while (0 )
4581
4597
4582
4598
/* *
4583
4599
Macro to check that there is enough space to read from memory.
@@ -4589,7 +4605,6 @@ code_name(int code)
4589
4605
#define CHECK_SPACE (PTR,END,CNT ) \
4590
4606
do { \
4591
4607
DBUG_PRINT (" info" , (" Read %s" , code_name (pos[-1 ]))); \
4592
- DBUG_ASSERT ((PTR) + (CNT) <= (END)); \
4593
4608
if ((PTR) + (CNT) > (END)) { \
4594
4609
DBUG_PRINT (" info" , (" query= 0" )); \
4595
4610
query= 0 ; \
@@ -4924,7 +4939,9 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
4924
4939
4925
4940
uint32 max_length= uint32 (event_len - ((const char *)(end + db_len + 1 ) -
4926
4941
(buf - common_header_len)));
4927
- if (q_len != max_length)
4942
+ if (q_len != max_length ||
4943
+ (event_len < uint ((const char *)(end + db_len + 1 ) -
4944
+ (buf - common_header_len))))
4928
4945
{
4929
4946
q_len= 0 ;
4930
4947
query= NULL ;
@@ -7110,6 +7127,8 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
7110
7127
{
7111
7128
DBUG_ENTER (" Load_log_event::copy_log_event" );
7112
7129
uint data_len;
7130
+ if ((int ) event_len < body_offset)
7131
+ DBUG_RETURN (1 );
7113
7132
char * buf_end = (char *)buf + event_len;
7114
7133
/* this is the beginning of the post-header */
7115
7134
const char * data_head = buf + description_event->common_header_len ;
@@ -7119,9 +7138,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
7119
7138
table_name_len = (uint)data_head[L_TBL_LEN_OFFSET];
7120
7139
db_len = (uint)data_head[L_DB_LEN_OFFSET];
7121
7140
num_fields = uint4korr (data_head + L_NUM_FIELDS_OFFSET);
7122
-
7123
- if ((int ) event_len < body_offset)
7124
- DBUG_RETURN (1 );
7141
+
7125
7142
/*
7126
7143
Sql_ex.init() on success returns the pointer to the first byte after
7127
7144
the sql_ex structure, which is the start of field lengths array.
@@ -7130,7 +7147,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
7130
7147
buf_end,
7131
7148
(uchar)buf[EVENT_TYPE_OFFSET] != LOAD_EVENT)))
7132
7149
DBUG_RETURN (1 );
7133
-
7150
+
7134
7151
data_len = event_len - body_offset;
7135
7152
if (num_fields > data_len) // simple sanity check against corruption
7136
7153
DBUG_RETURN (1 );
@@ -7695,7 +7712,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len,
7695
7712
// The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET
7696
7713
uint8 post_header_len= description_event->post_header_len [ROTATE_EVENT-1 ];
7697
7714
uint ident_offset;
7698
- if (event_len < LOG_EVENT_MINIMAL_HEADER_LEN)
7715
+ if (event_len < (uint)( LOG_EVENT_MINIMAL_HEADER_LEN + post_header_len) )
7699
7716
DBUG_VOID_RETURN;
7700
7717
buf+= LOG_EVENT_MINIMAL_HEADER_LEN;
7701
7718
pos= post_header_len ? uint8korr (buf + R_POS_OFFSET) : 4 ;
@@ -9268,6 +9285,11 @@ User_var_log_event(const char* buf, uint event_len,
9268
9285
we keep the flags set to UNDEF_F.
9269
9286
*/
9270
9287
size_t bytes_read= (val + val_len) - buf_start;
9288
+ if (bytes_read > event_len)
9289
+ {
9290
+ error= true ;
9291
+ goto err;
9292
+ }
9271
9293
if ((data_written - bytes_read) > 0 )
9272
9294
{
9273
9295
flags= (uint) *(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
@@ -10891,7 +10913,8 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len,
10891
10913
uint8 const common_header_len= description_event->common_header_len ;
10892
10914
Log_event_type event_type= (Log_event_type)(uchar)buf[EVENT_TYPE_OFFSET];
10893
10915
m_type= event_type;
10894
-
10916
+ m_cols_ai.bitmap = 0 ;
10917
+
10895
10918
uint8 const post_header_len= description_event->post_header_len [event_type-1 ];
10896
10919
10897
10920
DBUG_PRINT (" enter" ,(" event_len: %u common_header_len: %d "
@@ -10925,7 +10948,14 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len,
10925
10948
which includes length bytes
10926
10949
*/
10927
10950
var_header_len= uint2korr (post_start);
10928
- assert (var_header_len >= 2 );
10951
+ /* Check length and also avoid out of buffer read */
10952
+ if (var_header_len < 2 ||
10953
+ event_len < static_cast <unsigned int >(var_header_len +
10954
+ (post_start - buf)))
10955
+ {
10956
+ m_cols.bitmap = 0 ;
10957
+ DBUG_VOID_RETURN;
10958
+ }
10929
10959
var_header_len-= 2 ;
10930
10960
10931
10961
/* Iterate over var-len header, extracting 'chunks' */
@@ -12597,14 +12627,12 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
12597
12627
m_data_size (0 ), m_field_metadata (0 ), m_field_metadata_size (0 ),
12598
12628
m_null_bits (0 ), m_meta_memory (NULL )
12599
12629
{
12600
- unsigned int bytes_read= 0 ;
12601
12630
DBUG_ENTER (" Table_map_log_event::Table_map_log_event(const char*,uint,...)" );
12602
12631
12603
12632
uint8 common_header_len= description_event->common_header_len ;
12604
12633
uint8 post_header_len= description_event->post_header_len [TABLE_MAP_EVENT-1 ];
12605
12634
DBUG_PRINT (" info" ,(" event_len: %u common_header_len: %d post_header_len: %d" ,
12606
12635
event_len, common_header_len, post_header_len));
12607
-
12608
12636
/*
12609
12637
Don't print debug messages when running valgrind since they can
12610
12638
trigger false warnings.
@@ -12613,6 +12641,9 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
12613
12641
DBUG_DUMP (" event buffer" , (uchar*) buf, event_len);
12614
12642
#endif
12615
12643
12644
+ if (event_len < (uint)(common_header_len + post_header_len))
12645
+ DBUG_VOID_RETURN;
12646
+
12616
12647
/* Read the post-header */
12617
12648
const char *post_start= buf + common_header_len;
12618
12649
@@ -12639,15 +12670,18 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
12639
12670
12640
12671
/* Extract the length of the various parts from the buffer */
12641
12672
uchar const *const ptr_dblen= (uchar const *)vpart + 0 ;
12673
+ VALIDATE_BYTES_READ (ptr_dblen, buf, event_len);
12642
12674
m_dblen= *(uchar*) ptr_dblen;
12643
12675
12644
12676
/* Length of database name + counter + terminating null */
12645
12677
uchar const *const ptr_tbllen= ptr_dblen + m_dblen + 2 ;
12678
+ VALIDATE_BYTES_READ (ptr_tbllen, buf, event_len);
12646
12679
m_tbllen= *(uchar*) ptr_tbllen;
12647
12680
12648
12681
/* Length of table name + counter + terminating null */
12649
12682
uchar const *const ptr_colcnt= ptr_tbllen + m_tbllen + 2 ;
12650
12683
uchar *ptr_after_colcnt= (uchar*) ptr_colcnt;
12684
+ VALIDATE_BYTES_READ (ptr_after_colcnt, buf, event_len);
12651
12685
m_colcnt= net_field_length (&ptr_after_colcnt);
12652
12686
12653
12687
DBUG_PRINT (" info" ,(" m_dblen: %lu off: %ld m_tbllen: %lu off: %ld m_colcnt: %lu off: %ld" ,
@@ -12670,23 +12704,27 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
12670
12704
memcpy (m_coltype, ptr_after_colcnt, m_colcnt);
12671
12705
12672
12706
ptr_after_colcnt= ptr_after_colcnt + m_colcnt;
12673
- bytes_read= (uint) ( ptr_after_colcnt - (uchar *) buf);
12674
- DBUG_PRINT ( " info " , ( " Bytes read: %d " , bytes_read) );
12675
- if (bytes_read < event_len )
12707
+ VALIDATE_BYTES_READ ( ptr_after_colcnt, buf, event_len );
12708
+ m_field_metadata_size= net_field_length (&ptr_after_colcnt );
12709
+ if (m_field_metadata_size <= (m_colcnt * 2 ) )
12676
12710
{
12677
- m_field_metadata_size= net_field_length (&ptr_after_colcnt);
12678
- DBUG_ASSERT (m_field_metadata_size <= (m_colcnt * 2 ));
12679
12711
uint num_null_bytes= (m_colcnt + 7 ) / 8 ;
12680
12712
m_meta_memory= (uchar *)my_multi_malloc (MYF (MY_WME),
12681
- &m_null_bits, num_null_bytes,
12682
- &m_field_metadata, m_field_metadata_size,
12683
- NULL );
12713
+ &m_null_bits, num_null_bytes,
12714
+ &m_field_metadata, m_field_metadata_size,
12715
+ NULL );
12684
12716
memcpy (m_field_metadata, ptr_after_colcnt, m_field_metadata_size);
12685
12717
ptr_after_colcnt= (uchar*)ptr_after_colcnt + m_field_metadata_size;
12686
12718
memcpy (m_null_bits, ptr_after_colcnt, num_null_bytes);
12687
12719
}
12720
+ else
12721
+ {
12722
+ m_coltype= NULL ;
12723
+ my_free (m_memory);
12724
+ m_memory= NULL ;
12725
+ DBUG_VOID_RETURN;
12726
+ }
12688
12727
}
12689
-
12690
12728
DBUG_VOID_RETURN;
12691
12729
}
12692
12730
#endif
@@ -14541,9 +14579,12 @@ void Update_rows_log_event::init(MY_BITMAP const *cols)
14541
14579
14542
14580
Update_rows_log_event::~Update_rows_log_event ()
14543
14581
{
14544
- if (m_cols_ai.bitmap == m_bitbuf_ai) // no my_malloc happened
14545
- m_cols_ai.bitmap = 0 ; // so no my_free in my_bitmap_free
14546
- my_bitmap_free (&m_cols_ai); // To pair with my_bitmap_init().
14582
+ if (m_cols_ai.bitmap )
14583
+ {
14584
+ if (m_cols_ai.bitmap == m_bitbuf_ai) // no my_malloc happened
14585
+ m_cols_ai.bitmap = 0 ; // so no my_free in my_bitmap_free
14586
+ my_bitmap_free (&m_cols_ai); // To pair with my_bitmap_init().
14587
+ }
14547
14588
}
14548
14589
14549
14590
0 commit comments