From 4ff192bb404f5f7a7fe9e471c9ab2eb45aff4d05 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 21 Sep 2016 17:35:54 +0200 Subject: [PATCH] few bugs in the tracker support * ma_multi_malloc wanted uint for size arguments, not size_t * ma_multi_malloc needs NULL pointer at the end. Simple 0 is not always the right size * don't look for tracker info, if the packet does not even has the info_len field --- libmariadb/ma_alloc.c | 6 +- libmariadb/mariadb_lib.c | 167 ++++++++++++++++++++------------------- 2 files changed, 88 insertions(+), 85 deletions(-) diff --git a/libmariadb/ma_alloc.c b/libmariadb/ma_alloc.c index 564d445b..8894637b 100644 --- a/libmariadb/ma_alloc.c +++ b/libmariadb/ma_alloc.c @@ -166,13 +166,13 @@ void *ma_multi_malloc(myf myFlags, ...) { va_list args; char **ptr,*start,*res; - uint tot_length,length; + size_t tot_length,length; va_start(args,myFlags); tot_length=0; while ((ptr=va_arg(args, char **))) { - length=va_arg(args,uint); + length=va_arg(args, size_t); tot_length+=ALIGN_SIZE(length); } va_end(args); @@ -185,7 +185,7 @@ void *ma_multi_malloc(myf myFlags, ...) while ((ptr=va_arg(args, char **))) { *ptr=res; - length=va_arg(args,uint); + length=va_arg(args,size_t); res+=ALIGN_SIZE(length); } va_end(args); diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index 31cd6a71..a856637e 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -1929,79 +1929,50 @@ get_info: pos+=2; mysql->warning_count=uint2korr(pos); pos+=2; - if (pos < mysql->net.read_pos+length && (item_len= net_field_length(&pos))) - mysql->info=(char*) pos; - - /* check if server supports session tracking */ - if (mysql->server_capabilities & CLIENT_SESSION_TRACKING) + if (pos < mysql->net.read_pos+length) { - ma_clear_session_state(mysql); - pos+= item_len; + if ((item_len= net_field_length(&pos))) + mysql->info=(char*) pos; - if (mysql->server_status & SERVER_SESSION_STATE_CHANGED) + /* check if server supports session tracking */ + if (mysql->server_capabilities & CLIENT_SESSION_TRACKING) { - int i; - if (pos < mysql->net.read_pos + length) + ma_clear_session_state(mysql); + pos+= item_len; + + if (mysql->server_status & SERVER_SESSION_STATE_CHANGED) { - LIST *session_item; - MYSQL_LEX_STRING *str= NULL; - enum enum_session_state_type si_type; - uchar *old_pos= pos; - size_t item_len= net_field_length(&pos); /* length for all items */ - - /* length was already set, so make sure that info will be zero terminated */ - if (mysql->info) - *old_pos= 0; - - while (item_len > 0) + int i; + if (pos < mysql->net.read_pos + length) { - size_t plen; - char *data; - old_pos= pos; - si_type= (enum enum_session_state_type)net_field_length(&pos); - switch(si_type) { - case SESSION_TRACK_SCHEMA: - case SESSION_TRACK_STATE_CHANGE: - case SESSION_TRACK_TRANSACTION_CHARACTERISTICS: - case SESSION_TRACK_SYSTEM_VARIABLES: - net_field_length(&pos); /* ignore total length, item length will follow next */ - plen= net_field_length(&pos); - if (!ma_multi_malloc(0, - &session_item, sizeof(LIST), - &str, sizeof(MYSQL_LEX_STRING), - &data, plen, - 0)) - { - SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); - return -1; - } - str->length= plen; - str->str= data; - memcpy(str->str, (char *)pos, plen); - pos+= plen; - session_item->data= str; - mysql->extension->session_state[si_type].list= list_add(mysql->extension->session_state[si_type].list, session_item); + LIST *session_item; + MYSQL_LEX_STRING *str= NULL; + enum enum_session_state_type si_type; + uchar *old_pos= pos; + size_t item_len= net_field_length(&pos); /* length for all items */ - /* in case schema has changed, we have to update mysql->db */ - if (si_type == SESSION_TRACK_SCHEMA) - { - free(mysql->db); - mysql->db= malloc(plen + 1); - memcpy(mysql->db, str->str, plen); - mysql->db[plen]= 0; - } - else if (si_type == SESSION_TRACK_SYSTEM_VARIABLES) - { - my_bool set_charset= 0; - /* make sure that we update charset in case it has changed */ - if (!strncmp(str->str, "character_set_client", str->length)) - set_charset= 1; + /* length was already set, so make sure that info will be zero terminated */ + if (mysql->info) + *old_pos= 0; + + while (item_len > 0) + { + size_t plen; + char *data; + old_pos= pos; + si_type= (enum enum_session_state_type)net_field_length(&pos); + switch(si_type) { + case SESSION_TRACK_SCHEMA: + case SESSION_TRACK_STATE_CHANGE: + case SESSION_TRACK_TRANSACTION_CHARACTERISTICS: + case SESSION_TRACK_SYSTEM_VARIABLES: + net_field_length(&pos); /* ignore total length, item length will follow next */ plen= net_field_length(&pos); if (!ma_multi_malloc(0, &session_item, sizeof(LIST), &str, sizeof(MYSQL_LEX_STRING), &data, plen, - 0)) + NULL)) { SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); return -1; @@ -2012,31 +1983,63 @@ get_info: pos+= plen; session_item->data= str; mysql->extension->session_state[si_type].list= list_add(mysql->extension->session_state[si_type].list, session_item); - if (set_charset && - strncmp(mysql->charset->csname, str->str, str->length) != 0) + + /* in case schema has changed, we have to update mysql->db */ + if (si_type == SESSION_TRACK_SCHEMA) { - char cs_name[64]; - MARIADB_CHARSET_INFO *cs_info; - memcpy(cs_name, str->str, str->length); - cs_name[str->length]= 0; - if ((cs_info = (MARIADB_CHARSET_INFO *)mysql_find_charset_name(cs_name))) - mysql->charset= cs_info; + free(mysql->db); + mysql->db= malloc(plen + 1); + memcpy(mysql->db, str->str, plen); + mysql->db[plen]= 0; } + else if (si_type == SESSION_TRACK_SYSTEM_VARIABLES) + { + my_bool set_charset= 0; + /* make sure that we update charset in case it has changed */ + if (!strncmp(str->str, "character_set_client", str->length)) + set_charset= 1; + plen= net_field_length(&pos); + if (!ma_multi_malloc(0, + &session_item, sizeof(LIST), + &str, sizeof(MYSQL_LEX_STRING), + &data, plen, + NULL)) + { + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); + return -1; + } + str->length= plen; + str->str= data; + memcpy(str->str, (char *)pos, plen); + pos+= plen; + session_item->data= str; + mysql->extension->session_state[si_type].list= list_add(mysql->extension->session_state[si_type].list, session_item); + if (set_charset && + strncmp(mysql->charset->csname, str->str, str->length) != 0) + { + char cs_name[64]; + MARIADB_CHARSET_INFO *cs_info; + memcpy(cs_name, str->str, str->length); + cs_name[str->length]= 0; + if ((cs_info = (MARIADB_CHARSET_INFO *)mysql_find_charset_name(cs_name))) + mysql->charset= cs_info; + } + } + break; + default: + /* not supported yet */ + plen= net_field_length(&pos); + pos+= plen; + break; } - break; - default: - /* not supported yet */ - plen= net_field_length(&pos); - pos+= plen; - break; + item_len-= (pos - old_pos); } - item_len-= (pos - old_pos); } - } - for (i= SESSION_TRACK_BEGIN; i <= SESSION_TRACK_END; i++) - { - mysql->extension->session_state[i].list= list_reverse(mysql->extension->session_state[i].list); - mysql->extension->session_state[i].current= mysql->extension->session_state[i].list; + for (i= SESSION_TRACK_BEGIN; i <= SESSION_TRACK_END; i++) + { + mysql->extension->session_state[i].list= list_reverse(mysql->extension->session_state[i].list); + mysql->extension->session_state[i].current= mysql->extension->session_state[i].list; + } } } }