diff options
author | Michael Widenius <monty@askmonty.org> | 2011-05-20 14:36:13 +0300 |
---|---|---|
committer | Michael Widenius <monty@askmonty.org> | 2011-05-20 14:36:13 +0300 |
commit | c9a0d7338cb5c12ba8775f7b8fbfc7951bf9db4e (patch) | |
tree | 2c658e48c564b7fbb2342113f332a554d67e075a | |
parent | 2c62cf25c3b0b0fa1d0fd68fa44330adb822f7a3 (diff) | |
download | mariadb-git-c9a0d7338cb5c12ba8775f7b8fbfc7951bf9db4e.tar.gz |
Ensure we don't read a MariaDB 5.3 errmsg.sys file or new errmsg.sys file with holes for not used error messages
sql/derror.cc:
Ensure we don't read a MariaDB 5.3 errmsg.sys file with moved error messages or a new errmsg.sys file with holes for not used error messages
If error message file didn't exist and we have not read one in the past, don't continue.
Give better error message if the errmsg.sys header has changed.
-rw-r--r-- | sql/derror.cc | 86 |
1 files changed, 67 insertions, 19 deletions
diff --git a/sql/derror.cc b/sql/derror.cc index a8cfa00ad1d..fd9cb02095f 100644 --- a/sql/derror.cc +++ b/sql/derror.cc @@ -1,4 +1,5 @@ /* Copyright (C) 2000-2005 MySQL AB + Copyright (C) 2011 Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,6 +25,7 @@ #include "mysql_priv.h" #include "mysys_err.h" +static bool check_error_mesg(const char *file_name, const char **errmsg); static bool read_texts(const char *file_name,const char ***point, uint error_messages); static void init_myfunc_errs(void); @@ -32,9 +34,12 @@ static void init_myfunc_errs(void); Read messages from errorfile. This function can be called multiple times to reload the messages. - If it fails to load the messages, it will fail softly by initializing - the errmesg pointer to an array of empty strings or by keeping the - old array if it exists. + + If it fails to load the messages: + - If we already have error messages loaded, keep the old ones and + return FALSE(ok) + - Initializing the errmesg pointer to an array of empty strings + and return TRUE (error) @retval FALSE OK @@ -44,25 +49,44 @@ static void init_myfunc_errs(void); bool init_errmessage(void) { - const char **errmsgs, **ptr; + const char **errmsgs, **ptr, **org_errmsgs; + bool error= FALSE; DBUG_ENTER("init_errmessage"); /* Get a pointer to the old error messages pointer array. read_texts() tries to free it. */ - errmsgs= my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST); + org_errmsgs= my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST); /* Read messages from file. */ - if (read_texts(ERRMSG_FILE, &errmsgs, ER_ERROR_LAST - ER_ERROR_FIRST + 1) && - !errmsgs) + if (read_texts(ERRMSG_FILE, &errmsgs, ER_ERROR_LAST - ER_ERROR_FIRST + 1) || + check_error_mesg(ERRMSG_FILE, errmsgs)) { - if (!(errmsgs= (const char**) my_malloc((ER_ERROR_LAST-ER_ERROR_FIRST+1)* - sizeof(char*), MYF(0)))) - DBUG_RETURN(TRUE); - for (ptr= errmsgs; ptr < errmsgs + ER_ERROR_LAST - ER_ERROR_FIRST; ptr++) - *ptr= ""; + x_free(errmsgs); + + if (org_errmsgs) + { + /* Use old error messages */ + errmsgs= org_errmsgs; + } + else + { + /* + No error messages. Create a temporary empty error message so + that we don't get a crash if some code wrongly tries to access + a non existing error message. + */ + if (!(errmsgs= (const char**) my_malloc((ER_ERROR_LAST-ER_ERROR_FIRST+1)* + sizeof(char*), MYF(0)))) + DBUG_RETURN(TRUE); + for (ptr= errmsgs; ptr < errmsgs + ER_ERROR_LAST - ER_ERROR_FIRST; ptr++) + *ptr= ""; + error= TRUE; + } } + else + x_free(org_errmsgs); // Free old language /* Register messages for use with my_error(). */ if (my_error_register(errmsgs, ER_ERROR_FIRST, ER_ERROR_LAST)) @@ -73,7 +97,29 @@ bool init_errmessage(void) errmesg= errmsgs; /* Init global variabel */ init_myfunc_errs(); /* Init myfunc messages */ - DBUG_RETURN(FALSE); + DBUG_RETURN(error); +} + + +/** + Check the error messages array contains all relevant error messages +*/ + +static bool check_error_mesg(const char *file_name, const char **errmsg) +{ + /* + The last MySQL error message can't be an empty string; If it is, + it means that the error file doesn't contain all MySQL messages + and is probably from an older version of MySQL / MariaDB. + */ + if (errmsg[ER_ERROR_LAST - ER_ERROR_FIRST][0] == 0) + { + sql_print_error("Error message file '%s' is probably from and older " + "version of MariaDB / MYSQL as it doesn't contain all " + "error messages", file_name); + return 1; + } + return 0; } @@ -99,6 +145,8 @@ static bool read_texts(const char *file_name,const char ***point, const char *errmsg; DBUG_ENTER("read_texts"); + *point= 0; + LINT_INIT(buff); funktpos=0; if ((file=my_open(fn_format(name,file_name,language,"",4), @@ -108,6 +156,7 @@ static bool read_texts(const char *file_name,const char ***point, funktpos=1; if (my_read(file,(uchar*) head,32,MYF(MY_NABP))) goto err; + funktpos=2; if (head[0] != (uchar) 254 || head[1] != (uchar) 254 || head[2] != 2 || head[3] != 1) goto err; /* purecov: inspected */ @@ -133,19 +182,16 @@ Please install the latest version of this file.",name); if (count < error_messages) { sql_print_error("\ -Error message file '%s' had only %d error messages,\n\ -but it should contain at least %d error messages.\n\ -Check that the above file is the right version for this program!", +Error message file '%s' had only %d error messages, but it should contain at least %d error messages.\nCheck that the above file is the right version for this program!", name,count,error_messages); VOID(my_close(file,MYF(MY_WME))); DBUG_RETURN(1); } - x_free((uchar*) *point); /* Free old language */ if (!(*point= (const char**) my_malloc((size_t) (length+count*sizeof(char*)),MYF(0)))) { - funktpos=2; /* purecov: inspected */ + funktpos=3; /* purecov: inspected */ goto err; /* purecov: inspected */ } buff= (uchar*) (*point + count); @@ -169,9 +215,11 @@ Check that the above file is the right version for this program!", err: switch (funktpos) { - case 2: + case 3: errmsg= "Not enough memory for messagefile '%s'"; break; + case 2: + errmsg= "Incompatible header in messagefile '%s'. Probably from another version of MariaDB"; case 1: errmsg= "Can't read from messagefile '%s'"; break; |