Commit 7dd65017 authored by unknown's avatar unknown

Add check of format specifiers in error message strings

Update error message text accordingly to be equal between all translations


extra/comp_err.c:
  Add check of format specifiers in error message strings
sql/share/errmsg.txt:
  Update error messages after checks
parent 40bf2b37
...@@ -132,6 +132,8 @@ static struct message *parse_message_string(struct message *new_message, ...@@ -132,6 +132,8 @@ static struct message *parse_message_string(struct message *new_message,
char *str); char *str);
static struct message *find_message(struct errors *err, const char *lang, static struct message *find_message(struct errors *err, const char *lang,
my_bool no_default); my_bool no_default);
static int check_message_format(struct errors *err,
const char* mess);
static int parse_input_file(const char *file_name, struct errors **top_error, static int parse_input_file(const char *file_name, struct errors **top_error,
struct languages **top_language); struct languages **top_language);
static int get_options(int *argc, char ***argv); static int get_options(int *argc, char ***argv);
...@@ -458,6 +460,13 @@ static int parse_input_file(const char *file_name, struct errors **top_error, ...@@ -458,6 +460,13 @@ static int parse_input_file(const char *file_name, struct errors **top_error,
current_error->er_name, current_message.lang_short_name); current_error->er_name, current_message.lang_short_name);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
if (check_message_format(current_error, current_message.text))
{
fprintf(stderr, "Wrong formatspecifier of error message string"
" for error '%s' in language '%s'\n",
current_error->er_name, current_message.lang_short_name);
DBUG_RETURN(0);
}
if (insert_dynamic(&current_error->msg, (byte *) & current_message)) if (insert_dynamic(&current_error->msg, (byte *) & current_message))
DBUG_RETURN(0); DBUG_RETURN(0);
continue; continue;
...@@ -599,6 +608,117 @@ static struct message *find_message(struct errors *err, const char *lang, ...@@ -599,6 +608,117 @@ static struct message *find_message(struct errors *err, const char *lang,
} }
/*
Check message format specifiers against error message for
previous language
SYNOPSIS
checksum_format_specifier()
msg String for which to generate checksum
for the format specifiers
RETURN VALUE
Returns the checksum for all the characters of the
format specifiers
Ex.
"text '%-64.s' text part 2 %d'"
^^^^^^ ^^
characters will be xored to form checksum
NOTE:
Does not support format specifiers with positional args
like "%2$s" but that is not yet supported by my_vsnprintf
either.
*/
static char checksum_format_specifier(const char* msg)
{
char chksum= 0;
const char* p= msg;
int is_format_specifier= 0;
int num_format_specifiers= 0;
while (*p)
{
if (*p == '%')
{
is_format_specifier= 1; /* Entering format specifier */
num_format_specifiers++;
}
if (is_format_specifier)
{
chksum^= *p;
switch(*p)
{
case 'd':
case 'u':
case 'x':
case 's':
is_format_specifier= 0; /* Not in format specifier anymore */
break;
default:
break;
}
}
p++;
}
if (is_format_specifier)
{
/* Still inside a format specifier after end of string */
fprintf(stderr, "Still inside formatspecifier after end of string"
" in'%s'\n", msg);
DBUG_ASSERT(is_format_specifier==0);
}
/* Add number of format specifiers to checksum as extra safeguard */
chksum+= num_format_specifiers;
return chksum;
}
/*
Check message format specifiers against error message for
previous language
SYNOPSIS
check_message_format()
err Error to check message for
mess Message to check
RETURN VALUE
Returns 0 if no previous error message or message format is ok
*/
static int check_message_format(struct errors *err,
const char* mess)
{
struct message *first;
DBUG_ENTER("check_message_format");
/* Get first message(if any) */
if ((err->msg).elements == 0)
DBUG_RETURN(0); /* No previous message to compare against */
first= dynamic_element(&err->msg, 0, struct message*);
DBUG_ASSERT(first != NULL);
if (checksum_format_specifier(first->text) !=
checksum_format_specifier(mess))
{
/* Check sum of format specifiers failed, they should be equal */
DBUG_RETURN(1);
}
DBUG_RETURN(0);
}
/* /*
Skips spaces and or tabs till the beginning of the next word Skips spaces and or tabs till the beginning of the next word
Returns pointer to the beginning of the first character of the word Returns pointer to the beginning of the first character of the word
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment