@@ -569,9 +569,14 @@ row_log_event_uncompress(const Format_description_log_event *description_event,
569
569
570
570
uint32 binlog_get_uncompress_len (const char *buf)
571
571
{
572
- DBUG_ASSERT ((buf[0 ] & 0xe0 ) == 0x80 );
573
- uint32 lenlen = buf[0 ] & 0x07 ;
574
572
uint32 len = 0 ;
573
+ uint32 lenlen = 0 ;
574
+
575
+ if ((buf == NULL ) || ((buf[0 ] & 0xe0 ) != 0x80 ))
576
+ return len;
577
+
578
+ lenlen = buf[0 ] & 0x07 ;
579
+
575
580
switch (lenlen)
576
581
{
577
582
case 1 :
@@ -1385,6 +1390,17 @@ code_name(int code)
1385
1390
}
1386
1391
#endif
1387
1392
1393
+ #define VALIDATE_BYTES_READ (CUR_POS, START, EVENT_LEN ) \
1394
+ do { \
1395
+ uchar *cur_pos= (uchar *)CUR_POS; \
1396
+ uchar *start= (uchar *)START; \
1397
+ uint len= EVENT_LEN; \
1398
+ uint bytes_read= (uint)(cur_pos - start); \
1399
+ DBUG_PRINT (" info" , (" Bytes read: %u event_len:%u.\n " ,\
1400
+ bytes_read, len)); \
1401
+ if (bytes_read >= len) \
1402
+ DBUG_VOID_RETURN; \
1403
+ } while (0 )
1388
1404
1389
1405
/* *
1390
1406
Macro to check that there is enough space to read from memory.
@@ -1396,7 +1412,6 @@ code_name(int code)
1396
1412
#define CHECK_SPACE (PTR,END,CNT ) \
1397
1413
do { \
1398
1414
DBUG_PRINT (" info" , (" Read %s" , code_name (pos[-1 ]))); \
1399
- DBUG_ASSERT ((PTR) + (CNT) <= (END)); \
1400
1415
if ((PTR) + (CNT) > (END)) { \
1401
1416
DBUG_PRINT (" info" , (" query= 0" )); \
1402
1417
query= 0 ; \
@@ -1731,7 +1746,9 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
1731
1746
1732
1747
uint32 max_length= uint32 (event_len - ((const char *)(end + db_len + 1 ) -
1733
1748
(buf - common_header_len)));
1734
- if (q_len != max_length)
1749
+ if (q_len != max_length ||
1750
+ (event_len < uint ((const char *)(end + db_len + 1 ) -
1751
+ (buf - common_header_len))))
1735
1752
{
1736
1753
q_len= 0 ;
1737
1754
query= NULL ;
@@ -2429,6 +2446,8 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
2429
2446
{
2430
2447
DBUG_ENTER (" Load_log_event::copy_log_event" );
2431
2448
uint data_len;
2449
+ if ((int ) event_len < body_offset)
2450
+ DBUG_RETURN (1 );
2432
2451
char * buf_end = (char *)buf + event_len;
2433
2452
/* this is the beginning of the post-header */
2434
2453
const char * data_head = buf + description_event->common_header_len ;
@@ -2438,9 +2457,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
2438
2457
table_name_len = (uint)data_head[L_TBL_LEN_OFFSET];
2439
2458
db_len = (uint)data_head[L_DB_LEN_OFFSET];
2440
2459
num_fields = uint4korr (data_head + L_NUM_FIELDS_OFFSET);
2441
-
2442
- if ((int ) event_len < body_offset)
2443
- DBUG_RETURN (1 );
2460
+
2444
2461
/*
2445
2462
Sql_ex.init() on success returns the pointer to the first byte after
2446
2463
the sql_ex structure, which is the start of field lengths array.
@@ -2449,7 +2466,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
2449
2466
buf_end,
2450
2467
(uchar)buf[EVENT_TYPE_OFFSET] != LOAD_EVENT)))
2451
2468
DBUG_RETURN (1 );
2452
-
2469
+
2453
2470
data_len = event_len - body_offset;
2454
2471
if (num_fields > data_len) // simple sanity check against corruption
2455
2472
DBUG_RETURN (1 );
@@ -2493,7 +2510,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len,
2493
2510
// The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET
2494
2511
uint8 post_header_len= description_event->post_header_len [ROTATE_EVENT-1 ];
2495
2512
uint ident_offset;
2496
- if (event_len < LOG_EVENT_MINIMAL_HEADER_LEN)
2513
+ if (event_len < (uint)( LOG_EVENT_MINIMAL_HEADER_LEN + post_header_len) )
2497
2514
DBUG_VOID_RETURN;
2498
2515
buf+= LOG_EVENT_MINIMAL_HEADER_LEN;
2499
2516
pos= post_header_len ? uint8korr (buf + R_POS_OFFSET) : 4 ;
@@ -2833,6 +2850,11 @@ User_var_log_event(const char* buf, uint event_len,
2833
2850
we keep the flags set to UNDEF_F.
2834
2851
*/
2835
2852
size_t bytes_read= (val + val_len) - buf_start;
2853
+ if (bytes_read > event_len)
2854
+ {
2855
+ error= true ;
2856
+ goto err;
2857
+ }
2836
2858
if ((data_written - bytes_read) > 0 )
2837
2859
{
2838
2860
flags= (uint) *(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
@@ -3099,7 +3121,8 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len,
3099
3121
uint8 const common_header_len= description_event->common_header_len ;
3100
3122
Log_event_type event_type= (Log_event_type)(uchar)buf[EVENT_TYPE_OFFSET];
3101
3123
m_type= event_type;
3102
-
3124
+ m_cols_ai.bitmap = 0 ;
3125
+
3103
3126
uint8 const post_header_len= description_event->post_header_len [event_type-1 ];
3104
3127
3105
3128
DBUG_PRINT (" enter" ,(" event_len: %u common_header_len: %d "
@@ -3133,7 +3156,14 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len,
3133
3156
which includes length bytes
3134
3157
*/
3135
3158
var_header_len= uint2korr (post_start);
3136
- assert (var_header_len >= 2 );
3159
+ /* Check length and also avoid out of buffer read */
3160
+ if (var_header_len < 2 ||
3161
+ event_len < static_cast <unsigned int >(var_header_len +
3162
+ (post_start - buf)))
3163
+ {
3164
+ m_cols.bitmap = 0 ;
3165
+ DBUG_VOID_RETURN;
3166
+ }
3137
3167
var_header_len-= 2 ;
3138
3168
3139
3169
/* Iterate over var-len header, extracting 'chunks' */
@@ -3449,6 +3479,9 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
3449
3479
DBUG_DUMP (" event buffer" , (uchar*) buf, event_len);
3450
3480
#endif
3451
3481
3482
+ if (event_len < (uint)(common_header_len + post_header_len))
3483
+ DBUG_VOID_RETURN;
3484
+
3452
3485
/* Read the post-header */
3453
3486
const char *post_start= buf + common_header_len;
3454
3487
@@ -3475,15 +3508,18 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
3475
3508
3476
3509
/* Extract the length of the various parts from the buffer */
3477
3510
uchar const *const ptr_dblen= (uchar const *)vpart + 0 ;
3511
+ VALIDATE_BYTES_READ (ptr_dblen, buf, event_len);
3478
3512
m_dblen= *(uchar*) ptr_dblen;
3479
3513
3480
3514
/* Length of database name + counter + terminating null */
3481
3515
uchar const *const ptr_tbllen= ptr_dblen + m_dblen + 2 ;
3516
+ VALIDATE_BYTES_READ (ptr_tbllen, buf, event_len);
3482
3517
m_tbllen= *(uchar*) ptr_tbllen;
3483
3518
3484
3519
/* Length of table name + counter + terminating null */
3485
3520
uchar const *const ptr_colcnt= ptr_tbllen + m_tbllen + 2 ;
3486
3521
uchar *ptr_after_colcnt= (uchar*) ptr_colcnt;
3522
+ VALIDATE_BYTES_READ (ptr_after_colcnt, buf, event_len);
3487
3523
m_colcnt= net_field_length (&ptr_after_colcnt);
3488
3524
3489
3525
DBUG_PRINT (" info" ,(" m_dblen: %lu off: %ld m_tbllen: %lu off: %ld m_colcnt: %lu off: %ld" ,
@@ -3506,22 +3542,27 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
3506
3542
memcpy (m_coltype, ptr_after_colcnt, m_colcnt);
3507
3543
3508
3544
ptr_after_colcnt= ptr_after_colcnt + m_colcnt;
3509
- bytes_read= (uint) ( ptr_after_colcnt - (uchar *) buf);
3510
- DBUG_PRINT ( " info " , ( " Bytes read: %d " , bytes_read) );
3511
- if (bytes_read < event_len )
3545
+ VALIDATE_BYTES_READ ( ptr_after_colcnt, buf, event_len );
3546
+ m_field_metadata_size= net_field_length (&ptr_after_colcnt );
3547
+ if (m_field_metadata_size <= (m_colcnt * 2 ) )
3512
3548
{
3513
- m_field_metadata_size= net_field_length (&ptr_after_colcnt);
3514
- DBUG_ASSERT (m_field_metadata_size <= (m_colcnt * 2 ));
3515
3549
uint num_null_bytes= (m_colcnt + 7 ) / 8 ;
3516
3550
m_meta_memory= (uchar *)my_multi_malloc (MYF (MY_WME),
3517
- &m_null_bits, num_null_bytes,
3518
- &m_field_metadata, m_field_metadata_size,
3519
- NULL );
3551
+ &m_null_bits, num_null_bytes,
3552
+ &m_field_metadata, m_field_metadata_size,
3553
+ NULL );
3520
3554
memcpy (m_field_metadata, ptr_after_colcnt, m_field_metadata_size);
3521
3555
ptr_after_colcnt= (uchar*)ptr_after_colcnt + m_field_metadata_size;
3522
3556
memcpy (m_null_bits, ptr_after_colcnt, num_null_bytes);
3523
3557
ptr_after_colcnt= (unsigned char *)ptr_after_colcnt + num_null_bytes;
3524
3558
}
3559
+ else
3560
+ {
3561
+ m_coltype= NULL ;
3562
+ my_free (m_memory);
3563
+ m_memory= NULL ;
3564
+ DBUG_VOID_RETURN;
3565
+ }
3525
3566
3526
3567
bytes_read= (uint) (ptr_after_colcnt - (uchar *)buf);
3527
3568
@@ -3843,9 +3884,12 @@ Delete_rows_compressed_log_event::Delete_rows_compressed_log_event(
3843
3884
3844
3885
Update_rows_log_event::~Update_rows_log_event ()
3845
3886
{
3846
- if (m_cols_ai.bitmap == m_bitbuf_ai) // no my_malloc happened
3847
- m_cols_ai.bitmap = 0 ; // so no my_free in my_bitmap_free
3848
- my_bitmap_free (&m_cols_ai); // To pair with my_bitmap_init().
3887
+ if (m_cols_ai.bitmap )
3888
+ {
3889
+ if (m_cols_ai.bitmap == m_bitbuf_ai) // no my_malloc happened
3890
+ m_cols_ai.bitmap = 0 ; // so no my_free in my_bitmap_free
3891
+ my_bitmap_free (&m_cols_ai); // To pair with my_bitmap_init().
3892
+ }
3849
3893
}
3850
3894
3851
3895
0 commit comments