Bug #104753 PreparedStatement.setFetchSize(0) causes ArrayIndexOutOfBoundsException
Submitted: 27 Aug 2021 14:57 Modified: 27 Sep 2022 22:21
Reporter: Pavel Sher Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / J Severity:S3 (Non-critical)
Version:8.0.26 OS:Any
Assigned to: CPU Architecture:Any

[27 Aug 2021 14:57] Pavel Sher
Description:
The following code:

      Connection c = ...

      try {
        PreparedStatement st = c.prepareStatement("create table test_table (id bigint not null, primary key (id))");
        st.execute();
        st.close();
      } catch (SQLException t) {
        throw new RuntimeException(t);
      }

      try {
        PreparedStatement st = c.prepareStatement("insert into test_table (id) values (?)");
        st.setInt(1, 1);
        st.executeUpdate();
        st.close();
      } catch (SQLException t) {
        throw new RuntimeException(t);
      }

      try {
        PreparedStatement st = c.prepareStatement("select max(id) from test_table");
        st.setFetchSize(1);
        st.execute();
        st.close();
      } catch (SQLException t) {
        throw new RuntimeException(t);
      }

      try {
        PreparedStatement st = c.prepareStatement("select max(id) from test_table");
        st.setFetchSize(0);
        st.execute(); // <-- this throws java.lang.ArrayIndexOutOfBoundsException
        st.close();
      } catch (SQLException t) {
        throw new RuntimeException(t);
      }

Fails in the last st.execute() statement with exception:

java.lang.ArrayIndexOutOfBoundsException
	at java.lang.System.arraycopy(Native Method)
	at com.mysql.cj.protocol.a.NativePacketPayload.readBytes(NativePacketPayload.java:563)
	at com.mysql.cj.protocol.a.BinaryRowFactory.extractNativeEncodedColumn(BinaryRowFactory.java:150)
	at com.mysql.cj.protocol.a.BinaryRowFactory.unpackBinaryResultSetRow(BinaryRowFactory.java:115)
	at com.mysql.cj.protocol.a.BinaryRowFactory.createFromMessage(BinaryRowFactory.java:75)
	at com.mysql.cj.protocol.a.BinaryRowFactory.createFromMessage(BinaryRowFactory.java:51)
	at com.mysql.cj.protocol.a.ResultsetRowReader.read(ResultsetRowReader.java:87)
	at com.mysql.cj.protocol.a.ResultsetRowReader.read(ResultsetRowReader.java:42)
	at com.mysql.cj.protocol.a.NativeProtocol.read(NativeProtocol.java:1570)
	at com.mysql.cj.protocol.a.BinaryResultsetReader.read(BinaryResultsetReader.java:92)
	at com.mysql.cj.protocol.a.BinaryResultsetReader.read(BinaryResultsetReader.java:50)
	at com.mysql.cj.protocol.a.NativeProtocol.read(NativeProtocol.java:1583)
	at com.mysql.cj.protocol.a.NativeProtocol.readAllResults(NativeProtocol.java:1637)
	at com.mysql.cj.ServerPreparedQuery.readExecuteResult(ServerPreparedQuery.java:433)
	at com.mysql.cj.ServerPreparedQuery.serverExecute(ServerPreparedQuery.java:211)
	at com.mysql.cj.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:632)
	at com.mysql.cj.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:418)
	... 40 more

The problem reproduces with useCursorFetch=true and cachePrepStmts=true connection properties.

How to repeat:
Create a connection with useCursorFetch=true and cachePrepStmts=true and run some prepared statement with setFetchSize(1), then create another prepared statement for the same query and try to run it with setFetchSize(0). Observe ArrayIndexOutOfBoundsException.

According to Javadoc setFetchSize(0) disables fetch size hint, so one would expect that this call is always safe, but apparently this is not true.

Tested with MySQL Connector/J 8.0.26 & MySQL 8.0.23
[27 Aug 2021 16:00] MySQL Verification Team
Hello Pavel Sher,

Thank you for the report and test case.

regards,
Umesh
[27 Sep 2022 22:21] Daniel So
Posted by developer:
 
Added the following entry to the Connector/J 8.0.31 changelog: 

"Executing a PreparedStatment after applying setFetchSize(0) on it caused an ArrayIndexOutOfBoundsException."