diff options
author | Arun Kuruvila <arun.kuruvila@oracle.com> | 2018-02-12 15:19:43 +0530 |
---|---|---|
committer | Arun Kuruvila <arun.kuruvila@oracle.com> | 2018-02-12 15:19:43 +0530 |
commit | e4784703ee44d0a0a497a1a411dea20987d501ad (patch) | |
tree | 1f28ecfa226f27d3f65abd9e9c210504d3edcba1 /sql-common | |
parent | e585decb459740ec53b1ac1b85f332f7bd3c8ccf (diff) | |
download | mariadb-git-e4784703ee44d0a0a497a1a411dea20987d501ad.tar.gz |
Bug#25471090: MYSQL USE AFTER FREE
Description:- Mysql client crashes when trying to connect
to a fake server which is sending incorrect packets.
Analysis:- Mysql client crashes when it tries to read
server version details.
Fix:- A check is added in "red_one_row()".
Diffstat (limited to 'sql-common')
-rw-r--r-- | sql-common/client.c | 16 | ||||
-rw-r--r-- | sql-common/pack.c | 37 |
2 files changed, 44 insertions, 9 deletions
diff --git a/sql-common/client.c b/sql-common/client.c index 759d95117cb..9972ca741f2 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1723,18 +1723,20 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) end_pos=pos+pkt_len; for (field=0 ; field < fields ; field++) { - if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH) + len=(ulong) net_field_length_checked(&pos, (ulong)(end_pos - pos)); + if (pos > end_pos) + { + set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate); + return -1; + } + + if (len == NULL_LENGTH) { /* null field */ row[field] = 0; *lengths++=0; } else { - if (len > (ulong) (end_pos - pos)) - { - set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate); - return -1; - } row[field] = (char*) pos; pos+=len; *lengths++=len; diff --git a/sql-common/pack.c b/sql-common/pack.c index 02e91b5c3e3..57ff55689a2 100644 --- a/sql-common/pack.c +++ b/sql-common/pack.c @@ -1,5 +1,4 @@ -/* Copyright (c) 2000-2003, 2007 MySQL AB - Use is subject to license terms +/* Copyright (c) 2000, 2018 Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -46,6 +45,40 @@ ulong STDCALL net_field_length(uchar **packet) return (ulong) uint4korr(pos+1); } +/* The same as above but with max length check */ +ulong STDCALL net_field_length_checked(uchar **packet, ulong max_length) +{ + ulong len; + uchar *pos= (uchar *)*packet; + + if (*pos < 251) + { + (*packet)++; + len= (ulong) *pos; + return (len > max_length) ? max_length : len; + } + if (*pos == 251) + { + (*packet)++; + return NULL_LENGTH; + } + if (*pos == 252) + { + (*packet)+=3; + len= (ulong) uint2korr(pos+1); + return (len > max_length) ? max_length : len; + } + if (*pos == 253) + { + (*packet)+=4; + len= (ulong) uint3korr(pos+1); + return (len > max_length) ? max_length : len; + } + (*packet)+=9; /* Must be 254 when here */ + len= (ulong) uint4korr(pos+1); + return (len > max_length) ? max_length : len; +} + /* The same as above but returns longlong */ my_ulonglong net_field_length_ll(uchar **packet) { |