You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-07 02:42:49 +03:00
sanity checks for client-supplied OK packet content
reported by Matthias Kaiser, Apple Information Security
This commit is contained in:
@@ -81,6 +81,8 @@
|
|||||||
#define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15)
|
#define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15)
|
||||||
#define MA_RPL_VERSION_HACK "5.5.5-"
|
#define MA_RPL_VERSION_HACK "5.5.5-"
|
||||||
|
|
||||||
|
#define CHARSET_NAME_LEN 64
|
||||||
|
|
||||||
#undef max_allowed_packet
|
#undef max_allowed_packet
|
||||||
#undef net_buffer_length
|
#undef net_buffer_length
|
||||||
extern ulong max_allowed_packet; /* net.c */
|
extern ulong max_allowed_packet; /* net.c */
|
||||||
@@ -2139,6 +2141,7 @@ mysql_send_query(MYSQL* mysql, const char* query, unsigned long length)
|
|||||||
|
|
||||||
int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
|
int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
|
||||||
{
|
{
|
||||||
|
uchar *end= mysql->net.read_pos+length;
|
||||||
size_t item_len;
|
size_t item_len;
|
||||||
mysql->affected_rows= net_field_length_ll(&pos);
|
mysql->affected_rows= net_field_length_ll(&pos);
|
||||||
mysql->insert_id= net_field_length_ll(&pos);
|
mysql->insert_id= net_field_length_ll(&pos);
|
||||||
@@ -2146,10 +2149,14 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
|
|||||||
pos+=2;
|
pos+=2;
|
||||||
mysql->warning_count=uint2korr(pos);
|
mysql->warning_count=uint2korr(pos);
|
||||||
pos+=2;
|
pos+=2;
|
||||||
if (pos < mysql->net.read_pos+length)
|
if (pos > end)
|
||||||
|
goto corrupted;
|
||||||
|
if (pos < end)
|
||||||
{
|
{
|
||||||
if ((item_len= net_field_length(&pos)))
|
if ((item_len= net_field_length(&pos)))
|
||||||
mysql->info=(char*) pos;
|
mysql->info=(char*) pos;
|
||||||
|
if (pos + item_len > end)
|
||||||
|
goto corrupted;
|
||||||
|
|
||||||
/* check if server supports session tracking */
|
/* check if server supports session tracking */
|
||||||
if (mysql->server_capabilities & CLIENT_SESSION_TRACKING)
|
if (mysql->server_capabilities & CLIENT_SESSION_TRACKING)
|
||||||
@@ -2160,23 +2167,26 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
|
|||||||
if (mysql->server_status & SERVER_SESSION_STATE_CHANGED)
|
if (mysql->server_status & SERVER_SESSION_STATE_CHANGED)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if (pos < mysql->net.read_pos + length)
|
if (pos < end)
|
||||||
{
|
{
|
||||||
LIST *session_item;
|
LIST *session_item;
|
||||||
MYSQL_LEX_STRING *str= NULL;
|
MYSQL_LEX_STRING *str= NULL;
|
||||||
enum enum_session_state_type si_type;
|
enum enum_session_state_type si_type;
|
||||||
uchar *old_pos= pos;
|
uchar *old_pos= pos;
|
||||||
size_t item_len= net_field_length(&pos); /* length for all items */
|
|
||||||
|
item_len= net_field_length(&pos); /* length for all items */
|
||||||
|
if (pos + item_len > end)
|
||||||
|
goto corrupted;
|
||||||
|
end= pos + item_len;
|
||||||
|
|
||||||
/* length was already set, so make sure that info will be zero terminated */
|
/* length was already set, so make sure that info will be zero terminated */
|
||||||
if (mysql->info)
|
if (mysql->info)
|
||||||
*old_pos= 0;
|
*old_pos= 0;
|
||||||
|
|
||||||
while (item_len > 0)
|
while (pos < end)
|
||||||
{
|
{
|
||||||
size_t plen;
|
size_t plen;
|
||||||
char *data;
|
char *data;
|
||||||
old_pos= pos;
|
|
||||||
si_type= (enum enum_session_state_type)net_field_length(&pos);
|
si_type= (enum enum_session_state_type)net_field_length(&pos);
|
||||||
switch(si_type) {
|
switch(si_type) {
|
||||||
case SESSION_TRACK_SCHEMA:
|
case SESSION_TRACK_SCHEMA:
|
||||||
@@ -2186,16 +2196,14 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
|
|||||||
if (si_type != SESSION_TRACK_STATE_CHANGE)
|
if (si_type != SESSION_TRACK_STATE_CHANGE)
|
||||||
net_field_length(&pos); /* ignore total length, item length will follow next */
|
net_field_length(&pos); /* ignore total length, item length will follow next */
|
||||||
plen= net_field_length(&pos);
|
plen= net_field_length(&pos);
|
||||||
|
if (pos + plen > end)
|
||||||
|
goto corrupted;
|
||||||
if (!(session_item= ma_multi_malloc(0,
|
if (!(session_item= ma_multi_malloc(0,
|
||||||
&session_item, sizeof(LIST),
|
&session_item, sizeof(LIST),
|
||||||
&str, sizeof(MYSQL_LEX_STRING),
|
&str, sizeof(MYSQL_LEX_STRING),
|
||||||
&data, plen,
|
&data, plen,
|
||||||
NULL)))
|
NULL)))
|
||||||
{
|
goto oom;
|
||||||
ma_clear_session_state(mysql);
|
|
||||||
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
str->length= plen;
|
str->length= plen;
|
||||||
str->str= data;
|
str->str= data;
|
||||||
memcpy(str->str, (char *)pos, plen);
|
memcpy(str->str, (char *)pos, plen);
|
||||||
@@ -2218,30 +2226,28 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
|
|||||||
if (!strncmp(str->str, "character_set_client", str->length))
|
if (!strncmp(str->str, "character_set_client", str->length))
|
||||||
set_charset= 1;
|
set_charset= 1;
|
||||||
plen= net_field_length(&pos);
|
plen= net_field_length(&pos);
|
||||||
|
if (pos + plen > end)
|
||||||
|
goto corrupted;
|
||||||
if (!(session_item= ma_multi_malloc(0,
|
if (!(session_item= ma_multi_malloc(0,
|
||||||
&session_item, sizeof(LIST),
|
&session_item, sizeof(LIST),
|
||||||
&str, sizeof(MYSQL_LEX_STRING),
|
&str, sizeof(MYSQL_LEX_STRING),
|
||||||
&data, plen,
|
&data, plen,
|
||||||
NULL)))
|
NULL)))
|
||||||
{
|
goto oom;
|
||||||
ma_clear_session_state(mysql);
|
|
||||||
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
str->length= plen;
|
str->length= plen;
|
||||||
str->str= data;
|
str->str= data;
|
||||||
memcpy(str->str, (char *)pos, plen);
|
memcpy(str->str, (char *)pos, plen);
|
||||||
pos+= plen;
|
pos+= plen;
|
||||||
session_item->data= str;
|
session_item->data= str;
|
||||||
mysql->extension->session_state[si_type].list= list_add(mysql->extension->session_state[si_type].list, session_item);
|
mysql->extension->session_state[si_type].list= list_add(mysql->extension->session_state[si_type].list, session_item);
|
||||||
if (set_charset &&
|
if (set_charset && str->length < CHARSET_NAME_LEN &&
|
||||||
strncmp(mysql->charset->csname, str->str, str->length) != 0)
|
strncmp(mysql->charset->csname, str->str, str->length) != 0)
|
||||||
{
|
{
|
||||||
char cs_name[64];
|
char cs_name[CHARSET_NAME_LEN];
|
||||||
MARIADB_CHARSET_INFO *cs_info;
|
const MARIADB_CHARSET_INFO *cs_info;
|
||||||
memcpy(cs_name, str->str, str->length);
|
memcpy(cs_name, str->str, str->length);
|
||||||
cs_name[str->length]= 0;
|
cs_name[str->length]= 0;
|
||||||
if ((cs_info = (MARIADB_CHARSET_INFO *)mysql_find_charset_name(cs_name)))
|
if ((cs_info = mysql_find_charset_name(cs_name)))
|
||||||
mysql->charset= cs_info;
|
mysql->charset= cs_info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2249,10 +2255,11 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
|
|||||||
default:
|
default:
|
||||||
/* not supported yet */
|
/* not supported yet */
|
||||||
plen= net_field_length(&pos);
|
plen= net_field_length(&pos);
|
||||||
|
if (pos + plen > end)
|
||||||
|
goto corrupted;
|
||||||
pos+= plen;
|
pos+= plen;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
item_len-= (pos - old_pos);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i= SESSION_TRACK_BEGIN; i <= SESSION_TRACK_END; i++)
|
for (i= SESSION_TRACK_BEGIN; i <= SESSION_TRACK_END; i++)
|
||||||
@@ -2267,6 +2274,16 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
|
|||||||
else if (mysql->server_capabilities & CLIENT_SESSION_TRACKING)
|
else if (mysql->server_capabilities & CLIENT_SESSION_TRACKING)
|
||||||
ma_clear_session_state(mysql);
|
ma_clear_session_state(mysql);
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
|
oom:
|
||||||
|
ma_clear_session_state(mysql);
|
||||||
|
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
corrupted:
|
||||||
|
ma_clear_session_state(mysql);
|
||||||
|
SET_CLIENT_ERROR(mysql, CR_MALFORMED_PACKET, SQLSTATE_UNKNOWN, 0);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mthd_my_read_query_result(MYSQL *mysql)
|
int mthd_my_read_query_result(MYSQL *mysql)
|
||||||
|
Reference in New Issue
Block a user