From 3eec106a5632435038cb2879ac021029e2313b31 Mon Sep 17 00:00:00 2001 From: jmestwa-coder Date: Wed, 3 Jun 2026 16:42:35 +0530 Subject: [PATCH] bound binary-protocol datetime/time parameter reads to the declared length get_param_length() guarantees only `length` bytes for a prepared-statement parameter value sent over the binary protocol. set_param_datetime() reads to[4..6] when length > 4 (needs 7 bytes) and sint4korr(to+7) when length > 7 (needs 11); set_param_time() reads sint4korr(to+8) when length > 8 (needs 12). A client that sends an off-spec datetime length of 5, 6, 8, 9 or 10, or a time length of 9, 10 or 11, makes the server read up to 3 bytes past the validated value, an out-of-bounds read when the value ends at the packet buffer boundary. Gate the optional time and microsecond reads on the canonical encoding lengths (>= 7 and >= 11 for datetime, >= 12 for time) so a short value falls back to the next-shorter form instead of over-reading. Well-formed values (datetime 4/7/11, time 8/12) parse exactly as before. --- sql/sql_prepare.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 4da9773911116..4817053a30a71 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -578,7 +578,7 @@ void Item_param::set_param_time(uchar **pos, ulong len) tm.hour= (uint) to[5] + day * 24; tm.minute= (uint) to[6]; tm.second= (uint) to[7]; - tm.second_part= (length > 8) ? (ulong) sint4korr(to+8) : 0; + tm.second_part= (length >= 12) ? (ulong) sint4korr(to+8) : 0; if (tm.hour > 838) { /* TODO: add warning 'Data truncated' here */ @@ -607,7 +607,7 @@ void Item_param::set_param_datetime(uchar **pos, ulong len) tm.year= (uint) sint2korr(to); tm.month= (uint) to[2]; tm.day= (uint) to[3]; - if (length > 4) + if (length >= 7) { tm.hour= (uint) to[4]; tm.minute= (uint) to[5]; @@ -616,7 +616,7 @@ void Item_param::set_param_datetime(uchar **pos, ulong len) else tm.hour= tm.minute= tm.second= 0; - tm.second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0; + tm.second_part= (length >= 11) ? (ulong) sint4korr(to+7) : 0; } else set_zero_time(&tm, MYSQL_TIMESTAMP_DATETIME);