Skip to content

Commit

Permalink
sanity checks for client-supplied OK packet content
Browse files Browse the repository at this point in the history
reported by Matthias Kaiser, Apple Information Security
  • Loading branch information
vuvova committed May 7, 2020
1 parent f8213af commit 2759b87
Showing 1 changed file with 37 additions and 20 deletions.
57 changes: 37 additions & 20 deletions libmariadb/mariadb_lib.c
Expand Up @@ -81,6 +81,8 @@
#define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15)
#define MA_RPL_VERSION_HACK "5.5.5-"

#define CHARSET_NAME_LEN 64

#undef max_allowed_packet
#undef net_buffer_length
extern ulong max_allowed_packet; /* net.c */
Expand Down Expand Up @@ -2139,17 +2141,22 @@ mysql_send_query(MYSQL* mysql, const char* query, unsigned long length)

int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
{
uchar *end= mysql->net.read_pos+length;
size_t item_len;
mysql->affected_rows= net_field_length_ll(&pos);
mysql->insert_id= net_field_length_ll(&pos);
mysql->server_status=uint2korr(pos);
pos+=2;
mysql->warning_count=uint2korr(pos);
pos+=2;
if (pos < mysql->net.read_pos+length)
if (pos > end)
goto corrupted;
if (pos < end)
{
if ((item_len= net_field_length(&pos)))
mysql->info=(char*) pos;
if (pos + item_len > end)
goto corrupted;

/* check if server supports session tracking */
if (mysql->server_capabilities & CLIENT_SESSION_TRACKING)
Expand All @@ -2160,23 +2167,26 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
if (mysql->server_status & SERVER_SESSION_STATE_CHANGED)
{
int i;
if (pos < mysql->net.read_pos + length)
if (pos < end)
{
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 */

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 */
if (mysql->info)
*old_pos= 0;

while (item_len > 0)
while (pos < end)
{
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:
Expand All @@ -2186,16 +2196,14 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
if (si_type != SESSION_TRACK_STATE_CHANGE)
net_field_length(&pos); /* ignore total length, item length will follow next */
plen= net_field_length(&pos);
if (pos + plen > end)
goto corrupted;
if (!(session_item= ma_multi_malloc(0,
&session_item, sizeof(LIST),
&str, sizeof(MYSQL_LEX_STRING),
&data, plen,
NULL)))
{
ma_clear_session_state(mysql);
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
return -1;
}
goto oom;
str->length= plen;
str->str= data;
memcpy(str->str, (char *)pos, plen);
Expand All @@ -2218,41 +2226,40 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
if (!strncmp(str->str, "character_set_client", str->length))
set_charset= 1;
plen= net_field_length(&pos);
if (pos + plen > end)
goto corrupted;
if (!(session_item= ma_multi_malloc(0,
&session_item, sizeof(LIST),
&str, sizeof(MYSQL_LEX_STRING),
&data, plen,
NULL)))
{
ma_clear_session_state(mysql);
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
return -1;
}
goto oom;
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 &&
if (set_charset && str->length < CHARSET_NAME_LEN &&
strncmp(mysql->charset->csname, str->str, str->length) != 0)
{
char cs_name[64];
MARIADB_CHARSET_INFO *cs_info;
char cs_name[CHARSET_NAME_LEN];
const 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)))
if ((cs_info = mysql_find_charset_name(cs_name)))
mysql->charset= cs_info;
}
}
break;
default:
/* not supported yet */
plen= net_field_length(&pos);
if (pos + plen > end)
goto corrupted;
pos+= plen;
break;
}
item_len-= (pos - old_pos);
}
}
for (i= SESSION_TRACK_BEGIN; i <= SESSION_TRACK_END; i++)
Expand All @@ -2267,6 +2274,16 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
else if (mysql->server_capabilities & CLIENT_SESSION_TRACKING)
ma_clear_session_state(mysql);
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)
Expand Down

0 comments on commit 2759b87

Please sign in to comment.