1*4882a593SmuzhiyunFrom b98375f9df0b024857c03c03bc3e73e8ced8d772 Mon Sep 17 00:00:00 2001
2*4882a593SmuzhiyunFrom: Nayuta Yanagisawa <nayuta.yanagisawa@hey.com>
3*4882a593SmuzhiyunDate: Tue, 27 Sep 2022 15:22:57 +0900
4*4882a593SmuzhiyunSubject: [PATCH] MDEV-29644 a potential bug of null pointer dereference in
5*4882a593Smuzhiyun spider_db_mbase::print_warnings()
6*4882a593Smuzhiyun
7*4882a593SmuzhiyunThe function spider_db_mbase::print_warnings() can potentially result
8*4882a593Smuzhiyunin a null pointer dereference.
9*4882a593Smuzhiyun
10*4882a593SmuzhiyunRemove the null pointer dereference by cleaning up the function.
11*4882a593Smuzhiyun
12*4882a593SmuzhiyunSome small changes to the original commit
13*4882a593Smuzhiyun422fb63a9bbee35c50b6c7be19d199afe0bc98fa.
14*4882a593Smuzhiyun
15*4882a593SmuzhiyunCVE: CVE-2022-47015
16*4882a593Smuzhiyun
17*4882a593SmuzhiyunUpstream-Status: Backport [https://github.com/MariaDB/server/commit/b98375f9df0]
18*4882a593Smuzhiyun
19*4882a593SmuzhiyunCo-Authored-By: Yuchen Pei <yuchen.pei@mariadb.com>
20*4882a593SmuzhiyunSigned-off-by: Mingli Yu <mingli.yu@windriver.com>
21*4882a593Smuzhiyun---
22*4882a593Smuzhiyun .../spider/bugfix/r/mdev_29644.result         |  41 ++++++
23*4882a593Smuzhiyun .../mysql-test/spider/bugfix/t/mdev_29644.cnf |   3 +
24*4882a593Smuzhiyun .../spider/bugfix/t/mdev_29644.test           |  56 ++++++++
25*4882a593Smuzhiyun storage/spider/spd_db_mysql.cc                | 124 ++++++++----------
26*4882a593Smuzhiyun storage/spider/spd_db_mysql.h                 |   2 +-
27*4882a593Smuzhiyun 5 files changed, 154 insertions(+), 72 deletions(-)
28*4882a593Smuzhiyun create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_29644.result
29*4882a593Smuzhiyun create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_29644.cnf
30*4882a593Smuzhiyun create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_29644.test
31*4882a593Smuzhiyun
32*4882a593Smuzhiyundiff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29644.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29644.result
33*4882a593Smuzhiyunnew file mode 100644
34*4882a593Smuzhiyunindex 00000000000..b52cecc5bb7
35*4882a593Smuzhiyun--- /dev/null
36*4882a593Smuzhiyun+++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29644.result
37*4882a593Smuzhiyun@@ -0,0 +1,41 @@
38*4882a593Smuzhiyun+#
39*4882a593Smuzhiyun+# MDEV-29644 a potential bug of null pointer dereference in spider_db_mbase::print_warnings()
40*4882a593Smuzhiyun+#
41*4882a593Smuzhiyun+for master_1
42*4882a593Smuzhiyun+for child2
43*4882a593Smuzhiyun+child2_1
44*4882a593Smuzhiyun+child2_2
45*4882a593Smuzhiyun+child2_3
46*4882a593Smuzhiyun+for child3
47*4882a593Smuzhiyun+connection child2_1;
48*4882a593Smuzhiyun+CREATE DATABASE auto_test_remote;
49*4882a593Smuzhiyun+USE auto_test_remote;
50*4882a593Smuzhiyun+CREATE TABLE tbl_a (
51*4882a593Smuzhiyun+a CHAR(5)
52*4882a593Smuzhiyun+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
53*4882a593Smuzhiyun+SET GLOBAL sql_mode='';
54*4882a593Smuzhiyun+connection master_1;
55*4882a593Smuzhiyun+CREATE DATABASE auto_test_local;
56*4882a593Smuzhiyun+USE auto_test_local;
57*4882a593Smuzhiyun+CREATE TABLE tbl_a (
58*4882a593Smuzhiyun+a CHAR(255)
59*4882a593Smuzhiyun+) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='table "tbl_a", srv "s_2_1"';
60*4882a593Smuzhiyun+SET sql_mode='';
61*4882a593Smuzhiyun+INSERT INTO tbl_a VALUES ("this will be truncated");
62*4882a593Smuzhiyun+NOT FOUND /\[WARN SPIDER RESULT\].* Warning 1265 Data truncated for column 'a' at row 1.*/ in mysqld.1.1.err
63*4882a593Smuzhiyun+SET GLOBAL spider_log_result_errors=4;
64*4882a593Smuzhiyun+INSERT INTO tbl_a VALUES ("this will be truncated");
65*4882a593Smuzhiyun+FOUND 1 /\[WARN SPIDER RESULT\].* Warning 1265 Data truncated for column 'a' at row 1.*/ in mysqld.1.1.err
66*4882a593Smuzhiyun+connection master_1;
67*4882a593Smuzhiyun+SET GLOBAL spider_log_result_errors=DEFAULT;
68*4882a593Smuzhiyun+SET sql_mode=DEFAULT;
69*4882a593Smuzhiyun+DROP DATABASE IF EXISTS auto_test_local;
70*4882a593Smuzhiyun+connection child2_1;
71*4882a593Smuzhiyun+SET GLOBAL sql_mode=DEFAULT;
72*4882a593Smuzhiyun+DROP DATABASE IF EXISTS auto_test_remote;
73*4882a593Smuzhiyun+for master_1
74*4882a593Smuzhiyun+for child2
75*4882a593Smuzhiyun+child2_1
76*4882a593Smuzhiyun+child2_2
77*4882a593Smuzhiyun+child2_3
78*4882a593Smuzhiyun+for child3
79*4882a593Smuzhiyundiff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29644.cnf b/storage/spider/mysql-test/spider/bugfix/t/mdev_29644.cnf
80*4882a593Smuzhiyunnew file mode 100644
81*4882a593Smuzhiyunindex 00000000000..05dfd8a0bce
82*4882a593Smuzhiyun--- /dev/null
83*4882a593Smuzhiyun+++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29644.cnf
84*4882a593Smuzhiyun@@ -0,0 +1,3 @@
85*4882a593Smuzhiyun+!include include/default_mysqld.cnf
86*4882a593Smuzhiyun+!include ../my_1_1.cnf
87*4882a593Smuzhiyun+!include ../my_2_1.cnf
88*4882a593Smuzhiyundiff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29644.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29644.test
89*4882a593Smuzhiyunnew file mode 100644
90*4882a593Smuzhiyunindex 00000000000..3a8fbb251e1
91*4882a593Smuzhiyun--- /dev/null
92*4882a593Smuzhiyun+++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29644.test
93*4882a593Smuzhiyun@@ -0,0 +1,56 @@
94*4882a593Smuzhiyun+--echo #
95*4882a593Smuzhiyun+--echo # MDEV-29644 a potential bug of null pointer dereference in spider_db_mbase::print_warnings()
96*4882a593Smuzhiyun+--echo #
97*4882a593Smuzhiyun+
98*4882a593Smuzhiyun+# The test case below does not cause the potential null pointer dereference.
99*4882a593Smuzhiyun+# It is just for checking spider_db_mbase::fetch_and_print_warnings() works.
100*4882a593Smuzhiyun+
101*4882a593Smuzhiyun+--disable_query_log
102*4882a593Smuzhiyun+--disable_result_log
103*4882a593Smuzhiyun+--source ../../t/test_init.inc
104*4882a593Smuzhiyun+--enable_result_log
105*4882a593Smuzhiyun+--enable_query_log
106*4882a593Smuzhiyun+
107*4882a593Smuzhiyun+--connection child2_1
108*4882a593Smuzhiyun+CREATE DATABASE auto_test_remote;
109*4882a593Smuzhiyun+USE auto_test_remote;
110*4882a593Smuzhiyun+eval CREATE TABLE tbl_a (
111*4882a593Smuzhiyun+    a CHAR(5)
112*4882a593Smuzhiyun+) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
113*4882a593Smuzhiyun+
114*4882a593Smuzhiyun+SET GLOBAL sql_mode='';
115*4882a593Smuzhiyun+
116*4882a593Smuzhiyun+--connection master_1
117*4882a593Smuzhiyun+CREATE DATABASE auto_test_local;
118*4882a593Smuzhiyun+USE auto_test_local;
119*4882a593Smuzhiyun+eval CREATE TABLE tbl_a (
120*4882a593Smuzhiyun+    a CHAR(255)
121*4882a593Smuzhiyun+) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='table "tbl_a", srv "s_2_1"';
122*4882a593Smuzhiyun+
123*4882a593Smuzhiyun+SET sql_mode='';
124*4882a593Smuzhiyun+
125*4882a593Smuzhiyun+let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.1.err;
126*4882a593Smuzhiyun+let SEARCH_PATTERN= \[WARN SPIDER RESULT\].* Warning 1265 Data truncated for column 'a' at row 1.*;
127*4882a593Smuzhiyun+
128*4882a593Smuzhiyun+INSERT INTO tbl_a VALUES ("this will be truncated");
129*4882a593Smuzhiyun+--source include/search_pattern_in_file.inc # should not find
130*4882a593Smuzhiyun+
131*4882a593Smuzhiyun+SET GLOBAL spider_log_result_errors=4;
132*4882a593Smuzhiyun+
133*4882a593Smuzhiyun+INSERT INTO tbl_a VALUES ("this will be truncated");
134*4882a593Smuzhiyun+--source include/search_pattern_in_file.inc # should find
135*4882a593Smuzhiyun+
136*4882a593Smuzhiyun+--connection master_1
137*4882a593Smuzhiyun+SET GLOBAL spider_log_result_errors=DEFAULT;
138*4882a593Smuzhiyun+SET sql_mode=DEFAULT;
139*4882a593Smuzhiyun+DROP DATABASE IF EXISTS auto_test_local;
140*4882a593Smuzhiyun+
141*4882a593Smuzhiyun+--connection child2_1
142*4882a593Smuzhiyun+SET GLOBAL sql_mode=DEFAULT;
143*4882a593Smuzhiyun+DROP DATABASE IF EXISTS auto_test_remote;
144*4882a593Smuzhiyun+
145*4882a593Smuzhiyun+--disable_query_log
146*4882a593Smuzhiyun+--disable_result_log
147*4882a593Smuzhiyun+--source ../t/test_deinit.inc
148*4882a593Smuzhiyun+--enable_query_log
149*4882a593Smuzhiyun+--enable_result_log
150*4882a593Smuzhiyundiff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc
151*4882a593Smuzhiyunindex d377d2bd807..bc8383017f7 100644
152*4882a593Smuzhiyun--- a/storage/spider/spd_db_mysql.cc
153*4882a593Smuzhiyun+++ b/storage/spider/spd_db_mysql.cc
154*4882a593Smuzhiyun@@ -2207,7 +2207,7 @@ int spider_db_mbase::exec_query(
155*4882a593Smuzhiyun         db_conn->affected_rows, db_conn->insert_id,
156*4882a593Smuzhiyun         db_conn->server_status, db_conn->warning_count);
157*4882a593Smuzhiyun       if (spider_param_log_result_errors() >= 3)
158*4882a593Smuzhiyun-        print_warnings(l_time);
159*4882a593Smuzhiyun+        fetch_and_print_warnings(l_time);
160*4882a593Smuzhiyun     } else if (log_result_errors >= 4)
161*4882a593Smuzhiyun     {
162*4882a593Smuzhiyun       time_t cur_time = (time_t) time((time_t*) 0);
163*4882a593Smuzhiyun@@ -2289,81 +2289,63 @@ bool spider_db_mbase::is_xa_nota_error(
164*4882a593Smuzhiyun   DBUG_RETURN(xa_nota);
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun-int spider_db_mbase::print_warnings(
168*4882a593Smuzhiyun-  struct tm *l_time
169*4882a593Smuzhiyun-) {
170*4882a593Smuzhiyun+int spider_db_mbase::fetch_and_print_warnings(struct tm *l_time)
171*4882a593Smuzhiyun+{
172*4882a593Smuzhiyun   int error_num = 0;
173*4882a593Smuzhiyun-  DBUG_ENTER("spider_db_mbase::print_warnings");
174*4882a593Smuzhiyun+  DBUG_ENTER("spider_db_mbase::fetch_and_print_warnings");
175*4882a593Smuzhiyun   DBUG_PRINT("info",("spider this=%p", this));
176*4882a593Smuzhiyun-  if (db_conn->status == MYSQL_STATUS_READY)
177*4882a593Smuzhiyun+
178*4882a593Smuzhiyun+  if (spider_param_dry_access() || db_conn->status != MYSQL_STATUS_READY ||
179*4882a593Smuzhiyun+      db_conn->server_status & SERVER_MORE_RESULTS_EXISTS ||
180*4882a593Smuzhiyun+      !db_conn->warning_count)
181*4882a593Smuzhiyun+    DBUG_RETURN(0);
182*4882a593Smuzhiyun+
183*4882a593Smuzhiyun+  if (mysql_real_query(db_conn, SPIDER_SQL_SHOW_WARNINGS_STR,
184*4882a593Smuzhiyun+                       SPIDER_SQL_SHOW_WARNINGS_LEN))
185*4882a593Smuzhiyun+    DBUG_RETURN(0);
186*4882a593Smuzhiyun+
187*4882a593Smuzhiyun+  MYSQL_RES *res= mysql_store_result(db_conn);
188*4882a593Smuzhiyun+  if (!res)
189*4882a593Smuzhiyun+    DBUG_RETURN(0);
190*4882a593Smuzhiyun+
191*4882a593Smuzhiyun+  uint num_fields= mysql_num_fields(res);
192*4882a593Smuzhiyun+  if (num_fields != 3)
193*4882a593Smuzhiyun   {
194*4882a593Smuzhiyun-    if (
195*4882a593Smuzhiyun-#if MYSQL_VERSION_ID < 50500
196*4882a593Smuzhiyun-      !(db_conn->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) &&
197*4882a593Smuzhiyun-      db_conn->last_used_con->warning_count
198*4882a593Smuzhiyun-#else
199*4882a593Smuzhiyun-      !(db_conn->server_status & SERVER_MORE_RESULTS_EXISTS) &&
200*4882a593Smuzhiyun-      db_conn->warning_count
201*4882a593Smuzhiyun-#endif
202*4882a593Smuzhiyun-    ) {
203*4882a593Smuzhiyun-      if (
204*4882a593Smuzhiyun-        spider_param_dry_access() ||
205*4882a593Smuzhiyun-        !mysql_real_query(db_conn, SPIDER_SQL_SHOW_WARNINGS_STR,
206*4882a593Smuzhiyun-          SPIDER_SQL_SHOW_WARNINGS_LEN)
207*4882a593Smuzhiyun-      ) {
208*4882a593Smuzhiyun-        MYSQL_RES *res = NULL;
209*4882a593Smuzhiyun-        MYSQL_ROW row = NULL;
210*4882a593Smuzhiyun-        uint num_fields;
211*4882a593Smuzhiyun-        if (
212*4882a593Smuzhiyun-          spider_param_dry_access() ||
213*4882a593Smuzhiyun-          !(res = mysql_store_result(db_conn)) ||
214*4882a593Smuzhiyun-          !(row = mysql_fetch_row(res))
215*4882a593Smuzhiyun-        ) {
216*4882a593Smuzhiyun-          if (mysql_errno(db_conn))
217*4882a593Smuzhiyun-          {
218*4882a593Smuzhiyun-            if (res)
219*4882a593Smuzhiyun-              mysql_free_result(res);
220*4882a593Smuzhiyun-            DBUG_RETURN(0);
221*4882a593Smuzhiyun-          }
222*4882a593Smuzhiyun-          /* no record is ok */
223*4882a593Smuzhiyun-        }
224*4882a593Smuzhiyun-        num_fields = mysql_num_fields(res);
225*4882a593Smuzhiyun-        if (num_fields != 3)
226*4882a593Smuzhiyun-        {
227*4882a593Smuzhiyun-          mysql_free_result(res);
228*4882a593Smuzhiyun-          DBUG_RETURN(0);
229*4882a593Smuzhiyun-        }
230*4882a593Smuzhiyun-        if (l_time)
231*4882a593Smuzhiyun-        {
232*4882a593Smuzhiyun-          while (row)
233*4882a593Smuzhiyun-          {
234*4882a593Smuzhiyun-            fprintf(stderr, "%04d%02d%02d %02d:%02d:%02d [WARN SPIDER RESULT] "
235*4882a593Smuzhiyun-              "from [%s] %ld to %ld: %s %s %s\n",
236*4882a593Smuzhiyun+    mysql_free_result(res);
237*4882a593Smuzhiyun+    DBUG_RETURN(0);
238*4882a593Smuzhiyun+  }
239*4882a593Smuzhiyun+
240*4882a593Smuzhiyun+  MYSQL_ROW row= mysql_fetch_row(res);
241*4882a593Smuzhiyun+  if (l_time)
242*4882a593Smuzhiyun+  {
243*4882a593Smuzhiyun+    while (row)
244*4882a593Smuzhiyun+    {
245*4882a593Smuzhiyun+      fprintf(stderr,
246*4882a593Smuzhiyun+              "%04d%02d%02d %02d:%02d:%02d [WARN SPIDER RESULT] from [%s] %ld "
247*4882a593Smuzhiyun+              "to %ld: %s %s %s\n",
248*4882a593Smuzhiyun               l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday,
249*4882a593Smuzhiyun-              l_time->tm_hour, l_time->tm_min, l_time->tm_sec,
250*4882a593Smuzhiyun-              conn->tgt_host, (ulong) db_conn->thread_id,
251*4882a593Smuzhiyun-              (ulong) current_thd->thread_id, row[0], row[1], row[2]);
252*4882a593Smuzhiyun-            row = mysql_fetch_row(res);
253*4882a593Smuzhiyun-          }
254*4882a593Smuzhiyun-        } else {
255*4882a593Smuzhiyun-          while (row)
256*4882a593Smuzhiyun-          {
257*4882a593Smuzhiyun-            DBUG_PRINT("info",("spider row[0]=%s", row[0]));
258*4882a593Smuzhiyun-            DBUG_PRINT("info",("spider row[1]=%s", row[1]));
259*4882a593Smuzhiyun-            DBUG_PRINT("info",("spider row[2]=%s", row[2]));
260*4882a593Smuzhiyun-            longlong res_num =
261*4882a593Smuzhiyun-              (longlong) my_strtoll10(row[1], (char**) NULL, &error_num);
262*4882a593Smuzhiyun-            DBUG_PRINT("info",("spider res_num=%lld", res_num));
263*4882a593Smuzhiyun-            my_printf_error((int) res_num, row[2], MYF(0));
264*4882a593Smuzhiyun-            error_num = (int) res_num;
265*4882a593Smuzhiyun-            row = mysql_fetch_row(res);
266*4882a593Smuzhiyun-          }
267*4882a593Smuzhiyun-        }
268*4882a593Smuzhiyun-        if (res)
269*4882a593Smuzhiyun-          mysql_free_result(res);
270*4882a593Smuzhiyun-      }
271*4882a593Smuzhiyun+              l_time->tm_hour, l_time->tm_min, l_time->tm_sec, conn->tgt_host,
272*4882a593Smuzhiyun+              (ulong) db_conn->thread_id, (ulong) current_thd->thread_id, row[0],
273*4882a593Smuzhiyun+              row[1], row[2]);
274*4882a593Smuzhiyun+      row= mysql_fetch_row(res);
275*4882a593Smuzhiyun+    }
276*4882a593Smuzhiyun+  } else {
277*4882a593Smuzhiyun+    while (row)
278*4882a593Smuzhiyun+    {
279*4882a593Smuzhiyun+      DBUG_PRINT("info",("spider row[0]=%s", row[0]));
280*4882a593Smuzhiyun+      DBUG_PRINT("info",("spider row[1]=%s", row[1]));
281*4882a593Smuzhiyun+      DBUG_PRINT("info",("spider row[2]=%s", row[2]));
282*4882a593Smuzhiyun+      longlong res_num =
283*4882a593Smuzhiyun+        (longlong) my_strtoll10(row[1], (char**) NULL, &error_num);
284*4882a593Smuzhiyun+      DBUG_PRINT("info",("spider res_num=%lld", res_num));
285*4882a593Smuzhiyun+      my_printf_error((int) res_num, row[2], MYF(0));
286*4882a593Smuzhiyun+      error_num = (int) res_num;
287*4882a593Smuzhiyun+      row = mysql_fetch_row(res);
288*4882a593Smuzhiyun     }
289*4882a593Smuzhiyun   }
290*4882a593Smuzhiyun+
291*4882a593Smuzhiyun+  mysql_free_result(res);
292*4882a593Smuzhiyun+
293*4882a593Smuzhiyun   DBUG_RETURN(error_num);
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun@@ -14668,7 +14650,7 @@ int spider_mbase_handler::show_table_status(
297*4882a593Smuzhiyun       DBUG_RETURN(error_num);
298*4882a593Smuzhiyun     }
299*4882a593Smuzhiyun   }
300*4882a593Smuzhiyun-  if ((error_num = ((spider_db_mbase *) conn->db_conn)->print_warnings(NULL)))
301*4882a593Smuzhiyun+  if ((error_num = ((spider_db_mbase *) conn->db_conn)->fetch_and_print_warnings(NULL)))
302*4882a593Smuzhiyun   {
303*4882a593Smuzhiyun     DBUG_RETURN(error_num);
304*4882a593Smuzhiyun   }
305*4882a593Smuzhiyundiff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h
306*4882a593Smuzhiyunindex e90461ea278..a2012352f21 100644
307*4882a593Smuzhiyun--- a/storage/spider/spd_db_mysql.h
308*4882a593Smuzhiyun+++ b/storage/spider/spd_db_mysql.h
309*4882a593Smuzhiyun@@ -442,7 +442,7 @@ class spider_db_mbase: public spider_db_conn
310*4882a593Smuzhiyun   bool is_xa_nota_error(
311*4882a593Smuzhiyun     int error_num
312*4882a593Smuzhiyun   );
313*4882a593Smuzhiyun-  int print_warnings(
314*4882a593Smuzhiyun+  int fetch_and_print_warnings(
315*4882a593Smuzhiyun     struct tm *l_time
316*4882a593Smuzhiyun   );
317*4882a593Smuzhiyun   spider_db_result *store_result(
318*4882a593Smuzhiyun--
319*4882a593Smuzhiyun2.25.1
320*4882a593Smuzhiyun
321