Bug #108320 my_error_register doesn't work as expected
Submitted: 29 Aug 2022 14:26 Modified: 1 Sep 2022 7:27
Reporter: ashe sun (OCA) Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Errors Severity:S3 (Non-critical)
Version:8.0 OS:Any
Assigned to: CPU Architecture:Any

[29 Aug 2022 14:26] ashe sun
Description:
No overlapping with previously registered error numbers is allowed.

There are some problems with the detection logic of the func my_error_register, overlap may not be detected correctly.

  3   /* Search for the right position in the list. */
  2   for (search_meh_pp = &my_errmsgs_list; *search_meh_pp;
  1        search_meh_pp = &(*search_meh_pp)->meh_next) {
347     if ((*search_meh_pp)->meh_last > first) break;
  1   }
  2
  3   /* Error numbers must be unique. No overlapping is allowed. */
  4   if (*search_meh_pp && ((*search_meh_pp)->meh_first <= last)) {
  5     my_free(meh_p);
  6     return 1;
  7   }

How to repeat:
I constructed an overlapping scenario, just add this codes to the end of  share/messages_to_clients.txt, ER_SUNASHE_2 and ER_SUNASHE_3 are going to overlap.

 +  start-error-number 6000
 +
 +  ER_SUNASHE_1
 +    eng "sunashe error1."
 +
 +  ER_SUNASHE_2
 +    eng "sunashe error2."
 +
 +  start-error-number 6001
 +
 +  ER_SUNASHE_3
 +    eng "sunashe error3."
 +
 +  ER_SUNASHE_4
 +    eng "sunashe error4."

You can see these new error numbers in the generated header file(include/mysqld_error.h) after compiling, as shown below:

   5 #define WARN_UNSUPPORTED_ACL_TABLES_READ 4009
   4 #define ER_BINLOG_UNSAFE_ACL_TABLE_READ_IN_DML_DDL 4010
   3 #define ER_SUNASHE_1 6000
   2 #define ER_SUNASHE_2 6001
   1 #define ER_SUNASHE_3 6001
1661 #define ER_SUNASHE_4 6002

my_error_register does not detect this error when starting mysqld

Suggested fix:
diff --git a/mysys/my_error.cc b/mysys/my_error.cc
index 5ff76f1c7b9..476772608a2 100644
--- a/mysys/my_error.cc
+++ b/mysys/my_error.cc
@@ -344,7 +344,7 @@ int my_error_register(const char *(*get_errmsg)(int), int first, int last) {
   /* Search for the right position in the list. */
   for (search_meh_pp = &my_errmsgs_list; *search_meh_pp;
        search_meh_pp = &(*search_meh_pp)->meh_next) {
-    if ((*search_meh_pp)->meh_last > first) break;
+    if ((*search_meh_pp)->meh_last >= first) break;
   }

   /* Error numbers must be unique. No overlapping is allowed. */
[1 Sep 2022 7:27] MySQL Verification Team
Hello ashe sun,

Thank you for the report and feedback.

regards,
Umesh