Skip to content

Commit 586af41

Browse files
Bug#25714674: MYSQL SERVER REMOTE PREAUTH PROBLEM THROUGH INTEGER OVERFLOW
Description: A missing length check for length-encoded string causes problem in preauthorization stage.
1 parent 3acb193 commit 586af41

File tree

4 files changed

+44
-0
lines changed

4 files changed

+44
-0
lines changed

include/mysql.h.pp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@
245245
my_ulonglong net_field_length_ll(uchar **packet);
246246
uchar *net_store_length(uchar *pkg, ulonglong length);
247247
unsigned int net_length_size(ulonglong num);
248+
unsigned int net_field_length_size(uchar *pos);
248249
#include "mysql/client_plugin.h"
249250
struct st_mysql_client_plugin
250251
{

include/mysql_com.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,7 @@ ulong STDCALL net_field_length(uchar **packet);
10641064
my_ulonglong net_field_length_ll(uchar **packet);
10651065
uchar *net_store_length(uchar *pkg, ulonglong length);
10661066
unsigned int net_length_size(ulonglong num);
1067+
unsigned int net_field_length_size(uchar *pos);
10671068

10681069
#ifdef __cplusplus
10691070
}

mysys/pack.cc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,24 @@ uint net_length_size(ulonglong num)
142142
return 9;
143143
}
144144

145+
146+
/**
147+
length of buffer required to represent a length-encoded string
148+
give the length part of length encoded string. This function can
149+
be used before calling net_field_lenth/net_field_length_ll.
150+
151+
@param [in] pos Length information of length-encoded string
152+
153+
@return length of buffer needed to store this number [1, 3, 4, 9].
154+
*/
155+
156+
uint net_field_length_size(uchar *pos)
157+
{
158+
if (*pos <= 251)
159+
return 1;
160+
if (*pos == 252)
161+
return 3;
162+
if (*pos == 253)
163+
return 4;
164+
return 9;
165+
}

sql/auth/sql_authentication.cc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,6 +1300,7 @@ char *get_56_lenc_string(char **buffer,
13001300
{
13011301
static char empty_string[1]= { '\0' };
13021302
char *begin= *buffer;
1303+
uchar *pos= (uchar *)begin;
13031304

13041305
if (*max_bytes_available == 0)
13051306
return NULL;
@@ -1320,6 +1321,23 @@ char *get_56_lenc_string(char **buffer,
13201321
return empty_string;
13211322
}
13221323

1324+
/* Make sure we have enough bytes available for net_field_length_ll */
1325+
1326+
DBUG_EXECUTE_IF("buffer_too_short_3",
1327+
*pos= 252; *max_bytes_available= 2;
1328+
);
1329+
DBUG_EXECUTE_IF("buffer_too_short_4",
1330+
*pos= 253; *max_bytes_available= 3;
1331+
);
1332+
DBUG_EXECUTE_IF("buffer_too_short_9",
1333+
*pos= 254; *max_bytes_available= 8;
1334+
);
1335+
1336+
size_t required_length= (size_t)net_field_length_size(pos);
1337+
1338+
if (*max_bytes_available < required_length)
1339+
return NULL;
1340+
13231341
*string_length= (size_t)net_field_length_ll((uchar **)buffer);
13241342

13251343
DBUG_EXECUTE_IF("sha256_password_scramble_too_long",
@@ -1328,6 +1346,9 @@ char *get_56_lenc_string(char **buffer,
13281346

13291347
size_t len_len= (size_t)(*buffer - begin);
13301348

1349+
DBUG_ASSERT((*max_bytes_available >= len_len) &&
1350+
(len_len == required_length));
1351+
13311352
if (*string_length > *max_bytes_available - len_len)
13321353
return NULL;
13331354

0 commit comments

Comments
 (0)