Skip to content

Commit b9380f0

Browse files
Davi ArnautDavi Arnaut
authored andcommitted
Bug#48983: Bad strmake calls (length one too long)
The problem is a somewhat common misusage of the strmake function. The strmake(dst, src, len) function writes at most /len/ bytes to the string pointed to by src, not including the trailing null byte. Hence, if /len/ is the exact length of the destination buffer, a one byte buffer overflow can occur if the length of the source string is equal to or greater than /len/.
1 parent 0f73979 commit b9380f0

File tree

12 files changed

+22
-19
lines changed

12 files changed

+22
-19
lines changed

client/mysqldump.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
782782
&err_ptr, &err_len);
783783
if (err_len)
784784
{
785-
strmake(buff, err_ptr, min(sizeof(buff), err_len));
785+
strmake(buff, err_ptr, min(sizeof(buff) - 1, err_len));
786786
fprintf(stderr, "Invalid mode to --compatible: %s\n", buff);
787787
exit(1);
788788
}
@@ -3452,7 +3452,7 @@ static ulong find_set(TYPELIB *lib, const char *x, uint length,
34523452

34533453
for (; pos != end && *pos != ','; pos++) ;
34543454
var_len= (uint) (pos - start);
3455-
strmake(buff, start, min(sizeof(buff), var_len));
3455+
strmake(buff, start, min(sizeof(buff) - 1, var_len));
34563456
find= find_type(buff, lib, var_len);
34573457
if (!find)
34583458
{

libmysql/libmysql.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,10 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
712712
if (!passwd)
713713
passwd="";
714714

715-
/* Store user into the buffer */
715+
/*
716+
Store user into the buffer.
717+
Advance position as strmake returns a pointer to the closing NUL.
718+
*/
716719
end= strmake(end, user, USERNAME_LENGTH) + 1;
717720

718721
/* write scrambled password according to server capabilities */
@@ -1252,7 +1255,7 @@ mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
12521255
{
12531256
MYSQL_RES *result;
12541257
MYSQL_FIELD *fields;
1255-
char buff[257],*end;
1258+
char buff[258],*end;
12561259
DBUG_ENTER("mysql_list_fields");
12571260
DBUG_PRINT("enter",("table: '%s' wild: '%s'",table,wild ? wild : ""));
12581261

libmysqld/lib_sql.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ void embedded_get_error(MYSQL *mysql, MYSQL_DATA *data)
7373
NET *net= &mysql->net;
7474
struct embedded_query_result *ei= data->embedded_info;
7575
net->last_errno= ei->last_errno;
76-
strmake(net->last_error, ei->info, sizeof(net->last_error));
76+
strmake(net->last_error, ei->info, sizeof(net->last_error) - 1);
7777
memcpy(net->sqlstate, ei->sqlstate, sizeof(net->sqlstate));
7878
mysql->server_status= ei->server_status;
7979
my_free((gptr) data, MYF(0));

mysys/default.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
605605
int recursion_level)
606606
{
607607
char name[FN_REFLEN + 10], buff[4096], curr_gr[4096], *ptr, *end, **tmp_ext;
608-
char *value, option[4096], tmp[FN_REFLEN];
608+
char *value, option[4096+2], tmp[FN_REFLEN];
609609
static const char includedir_keyword[]= "includedir";
610610
static const char include_keyword[]= "include";
611611
const int max_recursion_level= 10;

mysys/mf_pack.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ my_bool my_use_symdir=0; /* Set this if you want to use symdirs */
234234
#ifdef USE_SYMDIR
235235
void symdirget(char *dir)
236236
{
237-
char buff[FN_REFLEN];
237+
char buff[FN_REFLEN+1];
238238
char *pos=strend(dir);
239239
if (dir[0] && pos[-1] != FN_DEVCHAR && my_access(dir, F_OK))
240240
{
@@ -246,7 +246,7 @@ void symdirget(char *dir)
246246
*pos++=temp; *pos=0; /* Restore old filename */
247247
if (file >= 0)
248248
{
249-
if ((length= my_read(file, buff, sizeof(buff), MYF(0))) > 0)
249+
if ((length= my_read(file, buff, sizeof(buff) - 1, MYF(0))) > 0)
250250
{
251251
for (pos= buff + length ;
252252
pos > buff && (iscntrl(pos[-1]) || isspace(pos[-1])) ;

server-tools/instance-manager/commands.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ Set_option::Set_option(Instance_map *instance_map_arg,
651651
instance_name= instance->options.instance_name;
652652

653653
/* add prefix for add_option */
654-
if ((option_len_arg < MAX_OPTION_LEN - 1) ||
654+
if ((option_len_arg < MAX_OPTION_LEN - 1) &&
655655
(option_value_len_arg < MAX_OPTION_LEN - 1))
656656
{
657657
strmake(option, option_arg, option_len_arg);

server-tools/instance-manager/listener.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ create_unix_socket(struct sockaddr_un &unix_socket_address)
331331

332332
unix_socket_address.sun_family= AF_UNIX;
333333
strmake(unix_socket_address.sun_path, options.socket_file_name,
334-
sizeof(unix_socket_address.sun_path));
334+
sizeof(unix_socket_address.sun_path) - 1);
335335
unlink(unix_socket_address.sun_path); // in case we have stale socket file
336336

337337
/*

sql/log.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ const char *MYSQL_LOG::generate_name(const char *log_name,
501501
{
502502
char *p = fn_ext(log_name);
503503
uint length=(uint) (p-log_name);
504-
strmake(buff,log_name,min(length,FN_REFLEN));
504+
strmake(buff, log_name, min(length, FN_REFLEN-1));
505505
return (const char*)buff;
506506
}
507507
return log_name;
@@ -1503,7 +1503,7 @@ int MYSQL_LOG::purge_logs_before_date(time_t purge_time)
15031503
if (stat_area.st_mtime < purge_time)
15041504
strmake(to_log,
15051505
log_info.log_file_name,
1506-
sizeof(log_info.log_file_name));
1506+
sizeof(log_info.log_file_name) - 1);
15071507
else
15081508
break;
15091509
}
@@ -2604,11 +2604,11 @@ bool flush_error_log()
26042604
if (opt_error_log)
26052605
{
26062606
char err_renamed[FN_REFLEN], *end;
2607-
end= strmake(err_renamed,log_error_file,FN_REFLEN-4);
2607+
end= strmake(err_renamed,log_error_file,FN_REFLEN-5);
26082608
strmov(end, "-old");
26092609
VOID(pthread_mutex_lock(&LOCK_error_log));
26102610
#ifdef __WIN__
2611-
char err_temp[FN_REFLEN+4];
2611+
char err_temp[FN_REFLEN+5];
26122612
/*
26132613
On Windows is necessary a temporary file for to rename
26142614
the current error file.

sql/sp_pcontext.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ typedef struct sp_label
7171
typedef struct sp_cond_type
7272
{
7373
enum { number, state, warning, notfound, exception } type;
74-
char sqlstate[6];
74+
char sqlstate[SQLSTATE_LENGTH+1];
7575
uint mysqlerr;
7676
} sp_cond_type_t;
7777

sql/sql_acl.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh,
914914
*mqh= acl_user->user_resource;
915915

916916
if (acl_user->host.hostname)
917-
strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME);
917+
strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME - 1);
918918
else
919919
*sctx->priv_host= 0;
920920
}
@@ -1015,7 +1015,7 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host,
10151015
sctx->priv_user= acl_user->user ? user : (char *) "";
10161016

10171017
if (acl_user->host.hostname)
1018-
strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME);
1018+
strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME - 1);
10191019
else
10201020
*sctx->priv_host= 0;
10211021
}

sql/sql_parse.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ static int check_connection(THD *thd)
917917
vio_keepalive(net->vio, TRUE);
918918
{
919919
/* buff[] needs to big enough to hold the server_version variable */
920-
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
920+
char buff[SERVER_VERSION_LENGTH + 1 + SCRAMBLE_LENGTH + 1 + 64];
921921
ulong client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
922922
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION);
923923

sql/sql_table.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
742742
!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
743743
MY_CS_BINSORT,MYF(0))))
744744
{
745-
char tmp[64];
745+
char tmp[65];
746746
strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
747747
STRING_WITH_LEN("_bin"));
748748
my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);

0 commit comments

Comments
 (0)