| Bug #119863 | Inaccurate decoding of negative TIME durations in Binary Protocol (Cursor Mode) | ||
|---|---|---|---|
| Submitted: | 9 Feb 11:16 | Modified: | 14 Apr 16:24 |
| Reporter: | Sandeep Mishra | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | Connector / J | Severity: | S2 (Serious) |
| Version: | 8.0.30, 9.6.0 (Verified in both) | OS: | Linux (OpenJDK 17) |
| Assigned to: | Filipe Silva | CPU Architecture: | Any (OpenJDK 17) |
| Tags: | Binary Protocol, data corruption, duration, time, useCursorFetch | ||
[11 Feb 0:22]
Filipe Silva
Hi Sandeep Mishra, Thank you for your interest in MySQL Connector/J and for taking the time to write this report. This issues was verified as described.
[14 Apr 16:24]
Edward Gilmore
Posted by developer: Added the following note to the MySQL Connector/J 9.7.0 release notes: Negative TIME values were incorrecly decoded over the binary protocol. For example, when useServerPrepStmts=true.

Description: When useCursorFetch=true is enabled (forcing the use of the Binary Protocol), the MySQL JDBC Connector incorrectly decodes TIME values that represent negative durations exceeding 24 hours. The root cause is a sign-handling error in MysqlBinaryValueDecoder.decodeTime. The driver correctly identifies the negative sign bit and negates the days component, but it fails to negate the residual hours component before adding them together. For example, for the minimum MySQL TIME value -838:59:59: The server sends: Negative=true, Days=34, Hours=22. The buggy driver logic performs: (-34 * 24) + 22 . The resulting calculation is -816 + 22, which equals -794. The value returned via ResultSet.getString() is shifted by exactly +44 hours (specifically +2 * residual_hours). How to repeat: Run a MySQL 8.0+ server. Initialize a table: CREATE TABLE time_test (id INT PRIMARY KEY, time_col TIME); Link a value: INSERT INTO time_test VALUES (1, '-838:59:59'); Run the following Java code using Connector/J (e.g., 9.6.0) with useCursorFetch=true: ``` // Setup connection with useCursorFetch=true String url = "jdbc:mysql://localhost:3306/db?useCursorFetch=true"; Connection conn = DriverManager.getConnection(url, "user", "pass"); // Trigger Cursor Mode (Binary Protocol) by setting a fetch size Statement stmt = conn.createStatement(); stmt.setFetchSize(10); ResultSet rs = stmt.executeQuery("SELECT time_col FROM time_test WHERE id = 1"); if (rs.next()) { System.out.println("Expected: -838:59:59"); System.out.println("Actual: " + rs.getString(1)); // Prints -794:59:59 } ``` Suggested fix: In com.mysql.cj.protocol.a.MysqlBinaryValueDecoder.java, update the decodeTime method to ensure the hours, minutes, etc components are treated as a negative offset when the negative flag is true.