Bug #48983 Bad strmake calls (length one too long)
| Submitted: | 23 Nov 2009 10:41 | Modified: | 12 Mar 2010 16:47 |
|---|---|---|---|
| Reporter: | Mattias Jonsson | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: General | Severity: | S2 (Serious) |
| Version: | 5.0, 5.1, 5.6 bzr | OS: | Any |
| Assigned to: | Davi Arnaut | CPU Architecture: | Any |
[23 Nov 2009 10:41]
Mattias Jonsson
[23 Nov 2009 10:43]
Mattias Jonsson
Here is some notes from my own findings of bad strmake calls:
libmysql/libmysql.c mysql_change_user uses a too small buffer
char buff[USERNAME_LENGTH+SCRAMBLED_PASSWORD_CHAR_LENGTH+NAME_LEN+2];
char *end= buff;
end= strmake(end, user, USERNAME_LENGTH) + 1;
/* now USERNAME_LENGTH + 1 */
if (passwd[0])
{
if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{
*end++= SCRAMBLE_LENGTH;
scramble(end, mysql->scramble, passwd);
end+= SCRAMBLE_LENGTH;
/* now USERNAME_LENGTH + 1 + 1 + SCRAMBLE_LENGTH (20) =>
USERNAME_LENGTH + 1 + 1 + SHA1_HASH_SIZE (20)
OK, always at least 19 bytes too long instead of too short...
*/
end= strmake(end, db ? db : "", NAME_LEN) + 1;
if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{
int2store(end, (ushort) mysql->charset->number);
end+= 2;
}
max is now USERNAME_LENGTH + 1 + 1 + SCRAMBLE_LENGTH + NAME_LEN + 1 + 2
read_user_name:
strmake(name, str ? str : "UNKNOWN_USER", USERNAME_LENGTH);
mysql_real_connect uses too small buffer:
char name_buff[USERNAME_LENGTH];
...
read_user_name(name_buff);
Also in sql-common/client.c (but may be OK?!?!)
if (user && user[0])
strmake(end,user,USERNAME_LENGTH); /* Max user name */
else
read_user_name((char*) end);
Maybe OK, since it uses 'end' after this too...
mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
{
MYSQL_RES *result;
MYSQL_FIELD *fields;
char buff[257],*end;
DBUG_ENTER("mysql_list_fields");
DBUG_PRINT("enter",("table: '%s' wild: '%s'",table,wild ? wild : ""));
end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128);
If table and wild is >= 128 then buf[258] (*end) ? will be overwritten!
in server-tools/instance-manager/instance_map.cc:
static void parse_option(const char *option_str,
char *option_name_buf,
char *option_value_buf)
{
const char *eq_pos;
const char *ptr= option_str;
while (*ptr == '-')
++ptr;
strmake(option_name_buf, ptr, MAX_OPTION_LEN + 1);
in server-tools/instance-manager/listener.cc create_unix_socket:
strmake(unix_socket_address.sun_path, Options::Main::socket_file_name,
sizeof(unix_socket_address.sun_path));
in server-tools/instance-manager/options.cc setup_windows_defaults:
char base_name[FN_REFLEN];
char im_name[FN_REFLEN];
strmake(base_name, base_name_ptr, FN_REFLEN);
*base_name_ptr= 0;
strmake(im_name, base_name, FN_REFLEN);
in server-tools/instance-manager/user_map.cc User::User:
user_length= (uint8) (strmake(user, user_name_arg->str,
USERNAME_LENGTH + 1) - user);
from user_map.h:
char user[USERNAME_LENGTH + 1];
in sql/log.cc MYSQL_LOG::generate_name:
strmake(buff, log_name, min(length, FN_REFLEN));
(open_slow_log:
char buf[FN_REFLEN];
return open(generate_name(log_name, ".log", 0, buf), LOG_NORMAL, 0,
WRITE_CACHE);
)
And the same for open-query_log...
in sql/log.cc MYSQL_BIN_LOG::purge_logs_before_date:
char to_log[FN_REFLEN];
strmake(to_log,
log_info.log_file_name,
sizeof(log_info.log_file_name));
typedef struct st_log_info
{
char log_file_name[FN_REFLEN];
Just looking at get_object in sql/repl_failsafe.cc i got scared :) (ok saves some lines, but no beauty at all) but correct.
in sql/rpl_mi.cc init_master_info_with_options:
if (master_password)
strmake(mi->password, master_password, MAX_PASSWORD_LENGTH);
in sql/sql_acl.cc acl_getroot and acl_getroot_no_password:
if (acl_user->host.hostname)
strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME);
Hmm STRING_BUFFER_USUAL_SIZE, lack of imagination when brainstorming for name?
in sql/sql_plugin.cc check_func_set:
strmake(buff, error, min(sizeof(buff), error_len));
in sql/sql_table.cc mysql_prepare_create_table:
char tmp[64];
strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
STRING_WITH_LEN("_bin"));
in sql-common/client.c...
in strings/ctype-tis620.c my_strnxfrm_tis620:
len= (size_t) (strmake((char*) dest, (char*) src, min(len, srclen)) -
(char*) dest);
I have not looked at the assembler code for strmake...
[25 Nov 2009 22:57]
Sveta Smirnova
Thank you for the report.
Verified as described.
To repeat:
add to strmake call output of n to error log: fprintf(stderr, "N: %d\n", n);
$bzr diff
=== modified file 'strings/strmake.c'
--- strings/strmake.c 2009-07-16 13:17:47 +0000
+++ strings/strmake.c 2009-11-25 22:49:10 +0000
@@ -50,5 +50,6 @@
if (! (*dst++ = *src++))
return dst-1;
*dst=0;
+ fprintf(stderr, "N: %d\n", n);
return dst;
}
Run test partition_innodb_semi_consistent , save file var/log/mysqld.1.err
Modify strmake so it revert the patch for bug #46042:
=== modified file 'strings/strmake.c'
--- strings/strmake.c 2009-07-16 13:17:47 +0000
+++ strings/strmake.c 2009-11-25 22:38:09 +0000
@@ -41,14 +41,20 @@
write a character rather than '\0' as this makes spotting these
problems in the results easier.
*/
+ /*
uint n= 0;
while (n < length && src[n++]);
memset(dst + n, (int) 'Z', length - n + 1);
+ */
+ uint n= strlen(src) + 1;
+ if (n <= length)
+ memset(dst + n, (int) 'Z', length - n + 1);
#endif
while (length--)
if (! (*dst++ = *src++))
return dst-1;
*dst=0;
+ fprintf(stderr, "N: %d\n", n);
return dst;
}
Run test partition_innodb_semi_consistent, then compare saved mysqld.1.err and new one. You will see values of n would be different. Then compare if all strmake calls changed after fix for bug #46042 was applied. They are not.
[17 Dec 2009 17:59]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/94822 2824 Davi Arnaut 2009-12-17 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/. @ client/mysqldump.c Make room for the trailing null byte. @ libmysql/libmysql.c Add comment, there is enough room in the buffer. Increase buffer length, two strings are concatenated. @ libmysqld/lib_sql.cc Make room for the trailing null byte. @ mysys/default.c Make room for the trailing null bytes. @ mysys/mf_pack.c Make room for the trailing null byte. @ server-tools/instance-manager/commands.cc Copy only if overflow isn't possible in both cases. @ server-tools/instance-manager/listener.cc Make room for the trailing null byte. @ sql/log.cc Make room for the trailing null byte. @ sql/sp_pcontext.h Cosmetic fix. @ sql/sql_acl.cc MAX_HOSTNAME already specifies space for the trailing null byte. @ sql/sql_parse.cc Make room for the trailing null byte. @ sql/sql_table.cc Make room for the trailing null byte.
[18 Dec 2009 19:14]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/94997 3286 Davi Arnaut 2009-12-18 Bug#48983: Bad strmake calls (length one too long) MySQL 5.1 specific fixes.
[18 Dec 2009 19:16]
Davi Arnaut
Queued to mysql-5.0-bugteam and up.
[14 Jan 2010 8:26]
Bugs System
Pushed into 5.0.90 (revid:joro@sun.com-20100114082402-05fod2h6z9x9wok8) (version source revid:davi.arnaut@sun.com-20091217175838-pzt20wyp63immpzl) (merge vers: 5.0.89) (pib:16)
[15 Jan 2010 9:01]
Bugs System
Pushed into 5.1.43 (revid:joro@sun.com-20100115085139-qkh0i0fpohd9u9p5) (version source revid:davi.arnaut@sun.com-20091218191409-gdgq8s7ctl6twd01) (merge vers: 5.1.42) (pib:16)
[22 Jan 2010 1:24]
Paul DuBois
Noted in 5.0.90, 5.1.43 changelogs. Several strmake() calls had an incorrect length argument (too large by one). Setting report to NDI pending push to 5.5.x+.
[5 Feb 2010 11:48]
Bugs System
Pushed into mysql-next-mr (revid:alik@sun.com-20100204063540-9czpdmpixi3iw2yb) (version source revid:alik@sun.com-20091224075613-es9uswo4lidkm3tj) (pib:16)
[5 Feb 2010 11:55]
Bugs System
Pushed into 6.0.14-alpha (revid:alik@sun.com-20100205113942-oqovjy0eoqbarn7i) (version source revid:alik@sun.com-20100204064210-ljwanqvrjs83s1gq) (merge vers: 6.0.14-alpha) (pib:16)
[5 Feb 2010 12:01]
Bugs System
Pushed into 5.5.2-m2 (revid:alik@sun.com-20100203172258-1n5dsotny40yufxw) (version source revid:alexey.kopytov@sun.com-20091223134205-pk9yvgfvpn3hy7lh) (merge vers: 5.5.1-m2) (pib:16)
[5 Feb 2010 17:11]
Paul DuBois
Noted in 5.5.2, 6.0.14 changelogs. Setting report to Need Merge pending push to Celosia.
[12 Mar 2010 14:15]
Bugs System
Pushed into 5.1.44-ndb-7.0.14 (revid:jonas@mysql.com-20100312135944-t0z8s1da2orvl66x) (version source revid:jonas@mysql.com-20100312115609-woou0te4a6s4ae9y) (merge vers: 5.1.44-ndb-7.0.14) (pib:16)
[12 Mar 2010 14:31]
Bugs System
Pushed into 5.1.44-ndb-6.2.19 (revid:jonas@mysql.com-20100312134846-tuqhd9w3tv4xgl3d) (version source revid:jonas@mysql.com-20100312060623-mx6407w2vx76h3by) (merge vers: 5.1.44-ndb-6.2.19) (pib:16)
[12 Mar 2010 14:47]
Bugs System
Pushed into 5.1.44-ndb-6.3.33 (revid:jonas@mysql.com-20100312135724-xcw8vw2lu3mijrhn) (version source revid:jonas@mysql.com-20100312103652-snkltsd197l7q2yg) (merge vers: 5.1.44-ndb-6.3.33) (pib:16)
[12 Mar 2010 16:47]
Paul DuBois
Fixed in earlier 5.1.x, 5.5.x.
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.050 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.