From 74883f5e2f4c0e09f4f4e9e272a8e5bfd91a9489 Mon Sep 17 00:00:00 2001
From: Aleksey Midenkov <midenok@gmail.com>
Date: Thu, 9 Nov 2023 16:26:11 +0300
Subject: [PATCH] MDEV-32082 Server crash in find_field_in_table

Attempt to resolve FOR SYSTEM_TIME expression as field for derived
table is done before derived table is fully prepared, so we fail on
assertion that table_list->table is missing.

Actually Vers_history_point::resolve_unit() is done under the call of
mysql_derived_prepare() itself (sql_derived.cc:824) and the table is
assigned later at 867.

The fix disables unit resolution for field type in FOR SYSTEM_TIME
expression as it does a little sense in any case: making historical
queries based on variable field values produces the result of multiple
time points.

fix_fields_if_needed() in resolve_units() was introduced by 46be31982a4

CVE: CVE-2023-52968
Upstream-Status: Backport [https://github.com/MariaDB/server/commit/74883f5e2f4c0e09f4f4e9e272a8e5bfd91a9489]

Changes:
-Use old my_error API instead of new bad_expression_data_type_error API.

Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
---
 mysql-test/suite/versioning/r/select.result | 11 ++++++++++-
 mysql-test/suite/versioning/t/select.test   | 12 +++++++++++-
 sql/table.cc                                |  6 ++++++
 3 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/mysql-test/suite/versioning/r/select.result b/mysql-test/suite/versioning/r/select.result
index 90c99d1b..714455b6 100644
--- a/mysql-test/suite/versioning/r/select.result
+++ b/mysql-test/suite/versioning/r/select.result
@@ -443,7 +443,7 @@ create or replace table t1 (x int) with system versioning;
 select * from t1 for system_time as of current_timestamp;
 x
 select * from t1 for system_time as of now;
-ERROR 42S22: Unknown column 'now' in 'FOR SYSTEM_TIME'
+ERROR HY000: Illegal parameter data type now for operation 'FOR SYSTEM_TIME'
 ### Issue #405, NATURAL JOIN failure
 create or replace table t1 (a int) with system versioning;
 create or replace table t2 (b int);
@@ -708,3 +708,12 @@ No	A	B	C	D
 33	1	1	1	1
 34	1	1	1	1
 SET GLOBAL innodb_stats_persistent = @saved_stats_persistent;
+#
+# MDEV-32082 Server crash in find_field_in_table
+#
+create table t0 (c0 int) with system versioning;
+select x0 from (
+select c0 x0 from t0
+) for system_time as of nowasdf deriv;
+ERROR HY000: Illegal parameter data type nowasdf for operation 'FOR SYSTEM_TIME'
+drop table t0;
diff --git a/mysql-test/suite/versioning/t/select.test b/mysql-test/suite/versioning/t/select.test
index 9142a8fa..5603d1a3 100644
--- a/mysql-test/suite/versioning/t/select.test
+++ b/mysql-test/suite/versioning/t/select.test
@@ -314,7 +314,7 @@ select * from t1 where (a, 2) in ((1, 1), (2, 2)) and b = 1;
 --echo ### Issue #398, NOW is now non-magic
 create or replace table t1 (x int) with system versioning;
 select * from t1 for system_time as of current_timestamp;
---error ER_BAD_FIELD_ERROR
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 select * from t1 for system_time as of now;

 --echo ### Issue #405, NATURAL JOIN failure
@@ -487,4 +487,14 @@ call verify_trt_dummy(34);

 SET GLOBAL innodb_stats_persistent = @saved_stats_persistent;

+--echo #
+--echo # MDEV-32082 Server crash in find_field_in_table
+--echo #
+create table t0 (c0 int) with system versioning;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+select x0 from (
+  select c0 x0 from t0
+) for system_time as of nowasdf deriv;
+drop table t0;
+
 -- source suite/versioning/common_finish.inc
diff --git a/sql/table.cc b/sql/table.cc
index e0e06702..81a5674a 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -10326,6 +10326,12 @@ bool Vers_history_point::check_unit(THD *thd)
 {
   if (!item)
     return false;
+  if (item->real_type() == Item::FIELD_ITEM)
+  {
+    my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+             item->full_name(), "FOR SYSTEM_TIME");
+    return true;
+  }
   if (item->fix_fields_if_needed(thd, &item))
     return true;
   const Type_handler *t= item->this_item()->real_type_handler();
--
2.40.0
