Skip to content

Commit 25221cc

Browse files
author
Guilhem Bichot
committed
Fix for BUG#11755168 '46895: test "outfile_loaddata" fails (reproducible)'.
In sql_class.cc, 'row_count', of type 'ha_rows', was used as last argument for ER_TRUNCATED_WRONG_VALUE_FOR_FIELD which is "Incorrect %-.32s value: '%-.128s' for column '%.192s' at row %ld". So 'ha_rows' was used as 'long'. On SPARC32 Solaris builds, 'long' is 4 bytes and 'ha_rows' is 'longlong' i.e. 8 bytes. So the printf-like code was reading only the first 4 bytes. Because the CPU is big-endian, 1LL is 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 so the first four bytes yield 0. So the warning message had "row 0" instead of "row 1" in test outfile_loaddata.test: -Warning 1366 Incorrect string value: '\xE1\xE2\xF7' for column 'b' at row 1 +Warning 1366 Incorrect string value: '\xE1\xE2\xF7' for column 'b' at row 0 All error-messaging functions which internally invoke some printf-life function are potential candidate for such mistakes. One apparently easy way to catch such mistakes is to use ATTRIBUTE_FORMAT (from my_attribute.h). But this works only when call site has both: a) the format as a string literal b) the types of arguments. So: func(ER(ER_BLAH), 10); will silently not be checked, because ER(ER_BLAH) is not known at compile time (it is known at run-time, and depends on the chosen language). And func("%s", a va_list argument); has the same problem, as the *real* type of arguments is not known at this site at compile time (it's known in some caller). Moreover, func(ER(ER_BLAH)); though possibly correct (if ER(ER_BLAH) has no '%' markers), will not compile (gcc says "error: format not a string literal and no format arguments"). Consequences: 1) ATTRIBUTE_FORMAT is here added only to functions which in practice take "string literal" formats: "my_error_reporter" and "print_admin_msg". 2) it cannot be added to the other functions: my_error(), push_warning_printf(), Table_check_intact::report_error(), general_log_print(). To do a one-time check of functions listed in (2), the following "static code analysis" has been done: 1) replace my_error(ER_xxx, arguments for substitution in format) with the equivalent my_printf_error(ER_xxx,ER(ER_xxx), arguments for substitution in format), so that we have ER(ER_xxx) and the arguments *in the same call site* 2) add ATTRIBUTE_FORMAT to push_warning_printf(), Table_check_intact::report_error(), general_log_print() 3) replace ER(xxx) with the hard-coded English text found in errmsg.txt (like: ER(ER_UNKNOWN_ERROR) is replaced with "Unknown error"), so that a call site has the format as string literal 4) this way, ATTRIBUTE_FORMAT can effectively do its job 5) compile, fix errors detected by ATTRIBUTE_FORMAT 6) revert steps 1-2-3. The present patch has no compiler error when submitted again to the static code analysis above. It cannot catch all problems though: see Field::set_warning(), in which a call to push_warning_printf() has a variable error (thus, not replacable by a string literal); I checked set_warning() calls by hand though. See also WL 5883 for one proposal to avoid such bugs from appearing again in the future. The issues fixed in the patch are: a) mismatch in types (like 'int' passed to '%ld') b) more arguments passed than specified in the format. This patch resolves mismatches by changing the type/number of arguments, not by changing error messages of sql/share/errmsg.txt. The latter would be wrong, per the following old rule: errmsg.txt must be as stable as possible; no insertions or deletions of messages, no changes of type or number of printf-like format specifiers, are allowed, as long as the change impacts a message already released in a GA version. If this rule is not followed: - Connectors, which use error message numbers, will be confused (by insertions/deletions of messages) - using errmsg.sys of MySQL 5.1.n with mysqld of MySQL 5.1.(n+1) could produce wrong messages or crash; such usage can easily happen if installing 5.1.(n+1) while /etc/my.cnf still has --language=/path/to/5.1.n/xxx; or if copying mysqld from 5.1.(n+1) into a 5.1.n installation. When fixing b), I have verified that the superfluous arguments were not used in the format in the first 5.1 GA (5.1.30 'bteam@astra04-20081114162938-z8mctjp6st27uobm'). Had they been used, then passing them today, even if the message doesn't use them anymore, would have been necessary, as explained above.
1 parent 4731736 commit 25221cc

28 files changed

+133
-137
lines changed

include/my_getopt.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (C) 2002-2004 MySQL AB
1+
/* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -11,7 +11,7 @@
1111
1212
You should have received a copy of the GNU General Public License
1313
along with this program; if not, write to the Free Software
14-
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
14+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
1515

1616
#ifndef _my_getopt_h
1717
#define _my_getopt_h
@@ -59,7 +59,9 @@ struct my_option
5959
};
6060

6161
typedef my_bool (*my_get_one_option)(int, const struct my_option *, char *);
62-
typedef void (*my_error_reporter)(enum loglevel level, const char *format, ...);
62+
typedef void (*my_error_reporter)(enum loglevel level, const char *format, ...)
63+
ATTRIBUTE_FORMAT_FPTR(printf, 2, 3);
64+
6365
/**
6466
Used to retrieve a reference to the object (variable) that holds the value
6567
for the given option. For example, if var_type is GET_UINT, the function

mysql-test/collections/default.experimental

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ innodb_plugin.* @solaris # Bug#56063 InnoDB Plugin mysql-tests f
1919
main.ctype_gbk_binlog @solaris # Bug#46010: main.ctype_gbk_binlog fails sporadically : Table 't2' already exists
2020
main.func_str @solaris # joro: Bug#40928
2121
main.sp @solaris # joro : Bug#54138
22-
main.outfile_loaddata @solaris # joro : Bug #46895
2322

2423
ndb.* # joro : NDB tests marked as experimental as agreed with bochklin
2524

sql/derror.cc

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (C) 2000-2005 MySQL AB
1+
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -11,8 +11,7 @@
1111
1212
You should have received a copy of the GNU General Public License
1313
along with this program; if not, write to the Free Software
14-
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
15-
14+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
1615

1716
/**
1817
@file
@@ -96,7 +95,6 @@ static bool read_texts(const char *file_name,const char ***point,
9695
char name[FN_REFLEN];
9796
uchar *buff;
9897
uchar head[32],*pos;
99-
const char *errmsg;
10098
DBUG_ENTER("read_texts");
10199

102100
LINT_INIT(buff);
@@ -168,18 +166,9 @@ Check that the above file is the right version for this program!",
168166
DBUG_RETURN(0);
169167

170168
err:
171-
switch (funktpos) {
172-
case 2:
173-
errmsg= "Not enough memory for messagefile '%s'";
174-
break;
175-
case 1:
176-
errmsg= "Can't read from messagefile '%s'";
177-
break;
178-
default:
179-
errmsg= "Can't find messagefile '%s'";
180-
break;
181-
}
182-
sql_print_error(errmsg, name);
169+
sql_print_error((funktpos == 2) ? "Not enough memory for messagefile '%s'" :
170+
((funktpos == 1) ? "Can't read from messagefile '%s'" :
171+
"Can't find messagefile '%s'"), name);
183172
err1:
184173
if (file != FERR)
185174
VOID(my_close(file,MYF(MY_WME)));

sql/events.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (C) 2004-2006 MySQL AB
1+
/* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -11,7 +11,7 @@
1111
1212
You should have received a copy of the GNU General Public License
1313
along with this program; if not, write to the Free Software
14-
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
14+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
1515

1616
#include "mysql_priv.h"
1717
#include "events.h"
@@ -547,7 +547,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
547547
!sortcmp_lex_string(parse_data->name, *new_name,
548548
system_charset_info))
549549
{
550-
my_error(ER_EVENT_SAME_NAME, MYF(0), parse_data->name.str);
550+
my_error(ER_EVENT_SAME_NAME, MYF(0));
551551
DBUG_RETURN(TRUE);
552552
}
553553

@@ -1150,7 +1150,7 @@ Events::switch_event_scheduler_state(enum_opt_event_scheduler new_state)
11501150

11511151
if (ret)
11521152
{
1153-
my_error(ER_EVENT_SET_VAR_ERROR, MYF(0));
1153+
my_error(ER_EVENT_SET_VAR_ERROR, MYF(0), 0);
11541154
goto end;
11551155
}
11561156

sql/field.cc

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -11,8 +11,7 @@
1111
1212
You should have received a copy of the GNU General Public License
1313
along with this program; if not, write to the Free Software
14-
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
15-
14+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
1615

1716
/**
1817
@file
@@ -9585,7 +9584,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
95859584
if (decimals >= NOT_FIXED_DEC)
95869585
{
95879586
my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
9588-
NOT_FIXED_DEC-1);
9587+
static_cast<ulong>(NOT_FIXED_DEC - 1));
95899588
DBUG_RETURN(TRUE);
95909589
}
95919590

@@ -9655,8 +9654,8 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
96559654
my_decimal_trim(&length, &decimals);
96569655
if (length > DECIMAL_MAX_PRECISION)
96579656
{
9658-
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
9659-
DECIMAL_MAX_PRECISION);
9657+
my_error(ER_TOO_BIG_PRECISION, MYF(0), static_cast<int>(length),
9658+
fld_name, static_cast<ulong>(DECIMAL_MAX_PRECISION));
96609659
DBUG_RETURN(TRUE);
96619660
}
96629661
if (length < decimals)
@@ -9881,7 +9880,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
98819880
if (length > MAX_BIT_FIELD_LENGTH)
98829881
{
98839882
my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), fld_name,
9884-
MAX_BIT_FIELD_LENGTH);
9883+
static_cast<ulong>(MAX_BIT_FIELD_LENGTH));
98859884
DBUG_RETURN(TRUE);
98869885
}
98879886
pack_length= (length + 7) / 8;

sql/ha_ndbcluster.cc

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (C) 2000-2003 MySQL AB
1+
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -11,8 +11,7 @@
1111
1212
You should have received a copy of the GNU General Public License
1313
along with this program; if not, write to the Free Software
14-
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15-
*/
14+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
1615

1716
/**
1817
@file
@@ -8411,7 +8410,7 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table,
84118410
DBUG_PRINT("error", ("get_share: failed to alloc share"));
84128411
if (!have_lock)
84138412
pthread_mutex_unlock(&ndbcluster_mutex);
8414-
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(*share));
8413+
my_error(ER_OUTOFMEMORY, MYF(0), static_cast<int>(sizeof(*share)));
84158414
DBUG_RETURN(0);
84168415
}
84178416
}

sql/ha_ndbcluster_binlog.cc

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (C) 2000-2003 MySQL AB
1+
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -11,8 +11,7 @@
1111
1212
You should have received a copy of the GNU General Public License
1313
along with this program; if not, write to the Free Software
14-
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15-
*/
14+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
1615

1716
#include "mysql_priv.h"
1817
#include "sql_show.h"
@@ -1198,12 +1197,14 @@ ndbcluster_update_slock(THD *thd,
11981197
}
11991198

12001199
if (ndb_error)
1200+
{
1201+
char buf[1024];
1202+
my_snprintf(buf, sizeof(buf), "Could not release lock on '%s.%s'",
1203+
db, table_name);
12011204
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
12021205
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
1203-
ndb_error->code,
1204-
ndb_error->message,
1205-
"Could not release lock on '%s.%s'",
1206-
db, table_name);
1206+
ndb_error->code, ndb_error->message, buf);
1207+
}
12071208
if (trans)
12081209
ndb->closeTransaction(trans);
12091210
ndb->setDatabaseName(save_db);

sql/ha_partition.cc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2005-2008 MySQL AB, 2008 Sun Microsystems, Inc.
1+
/* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -11,7 +11,7 @@
1111
1212
You should have received a copy of the GNU General Public License
1313
along with this program; if not, write to the Free Software
14-
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
14+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
1515

1616
/*
1717
This handler was developed by Mikael Ronstrom for version 5.1 of MySQL.
@@ -1023,6 +1023,10 @@ static int handle_opt_part(THD *thd, HA_CHECK_OPT *check_opt,
10231023
(modelled after mi_check_print_msg)
10241024
TODO: move this into the handler, or rewrite mysql_admin_table.
10251025
*/
1026+
static bool print_admin_msg(THD* thd, const char* msg_type,
1027+
const char* db_name, const char* table_name,
1028+
const char* op_name, const char *fmt, ...)
1029+
ATTRIBUTE_FORMAT(printf, 6, 7);
10261030
static bool print_admin_msg(THD* thd, const char* msg_type,
10271031
const char* db_name, const char* table_name,
10281032
const char* op_name, const char *fmt, ...)

sql/handler.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ handler *get_ha_partition(partition_info *part_info)
275275
}
276276
else
277277
{
278-
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(ha_partition));
278+
my_error(ER_OUTOFMEMORY, MYF(0), static_cast<int>(sizeof(ha_partition)));
279279
}
280280
DBUG_RETURN(((handler*) partition));
281281
}
@@ -1604,7 +1604,8 @@ int ha_recover(HASH *commit_list)
16041604
}
16051605
if (!info.list)
16061606
{
1607-
sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1607+
sql_print_error(ER(ER_OUTOFMEMORY),
1608+
static_cast<int>(info.len*sizeof(XID)));
16081609
DBUG_RETURN(1);
16091610
}
16101611

sql/item_create.cc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -11,7 +11,7 @@
1111
1212
You should have received a copy of the GNU General Public License
1313
along with this program; if not, write to the Free Software
14-
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
14+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
1515

1616
/**
1717
@file
@@ -5083,8 +5083,8 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
50835083
decoded_size= strtoul(c_len, NULL, 10);
50845084
if (errno != 0)
50855085
{
5086-
my_error(ER_TOO_BIG_PRECISION, MYF(0), c_len, a->name,
5087-
DECIMAL_MAX_PRECISION);
5086+
my_error(ER_TOO_BIG_PRECISION, MYF(0), INT_MAX, a->name,
5087+
static_cast<ulong>(DECIMAL_MAX_PRECISION));
50885088
return NULL;
50895089
}
50905090
len= decoded_size;
@@ -5097,8 +5097,8 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
50975097
decoded_size= strtoul(c_dec, NULL, 10);
50985098
if ((errno != 0) || (decoded_size > UINT_MAX))
50995099
{
5100-
my_error(ER_TOO_BIG_SCALE, MYF(0), c_dec, a->name,
5101-
DECIMAL_MAX_SCALE);
5100+
my_error(ER_TOO_BIG_SCALE, MYF(0), INT_MAX, a->name,
5101+
static_cast<ulong>(DECIMAL_MAX_SCALE));
51025102
return NULL;
51035103
}
51045104
dec= decoded_size;
@@ -5111,14 +5111,14 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
51115111
}
51125112
if (len > DECIMAL_MAX_PRECISION)
51135113
{
5114-
my_error(ER_TOO_BIG_PRECISION, MYF(0), len, a->name,
5115-
DECIMAL_MAX_PRECISION);
5114+
my_error(ER_TOO_BIG_PRECISION, MYF(0), static_cast<int>(len), a->name,
5115+
static_cast<ulong>(DECIMAL_MAX_PRECISION));
51165116
return 0;
51175117
}
51185118
if (dec > DECIMAL_MAX_SCALE)
51195119
{
51205120
my_error(ER_TOO_BIG_SCALE, MYF(0), dec, a->name,
5121-
DECIMAL_MAX_SCALE);
5121+
static_cast<ulong>(DECIMAL_MAX_SCALE));
51225122
return 0;
51235123
}
51245124
res= new (thd->mem_root) Item_decimal_typecast(a, len, dec);

0 commit comments

Comments
 (0)