aws-mysql-jdbc icon indicating copy to clipboard operation
aws-mysql-jdbc copied to clipboard

ClientPreparedQueryBindings IllegalArgumentException for large byte arrays

Open fgoldenberg-sdl opened this issue 2 years ago • 1 comments

Describe the bug

For large byte arrays, the ByteArrayOutputStream constructor is called with a negative value at due to the maximum possible value for an int, raising an IllegalArgumentException. Sample stacktrace:

Caused by: java.lang.IllegalArgumentException: Negative initial size: -1818412943 at java.base/java.io.ByteArrayOutputStream.(Unknown Source) at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.ClientPreparedQueryBindings.setBytes(ClientPreparedQueryBindings.java:219) at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.ClientPreparedQueryBindings.setBytes(ClientPreparedQueryBindings.java:203) at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.jdbc.ClientPreparedStatement.setBytes(ClientPreparedStatement.java:1505) at org.apache.commons.dbcp.DelegatingPreparedStatement.setBytes(DelegatingPreparedStatement.java:138) at org.apache.commons.dbcp.DelegatingPreparedStatement.setBytes(DelegatingPreparedStatement.java:138) at org.apache.commons.dbcp.DelegatingPreparedStatement.setBytes(DelegatingPreparedStatement.java:138) at org.hibernate.type.descriptor.sql.BlobTypeDescriptor$3$1.doBind(BlobTypeDescriptor.java:113) at org.hibernate.type.descriptor.sql.BlobTypeDescriptor$2$1.doBind(BlobTypeDescriptor.java:86) at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:73) at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:276) at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:271) at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:39) at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:3073) at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:3048) at org.hibernate.persister.entity.AbstractEntityPersister$2.bindValues(AbstractEntityPersister.java:3271) at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:42) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3279) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3885) at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:84) at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:645) at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:282) at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:263) at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:317) at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:330) at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:287) at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:123) at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:185) at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:128) at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:55) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:774) at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:760)

Expected Behavior

No exception is thrown

Current Behavior

An IllegalArgumentException is thrown at the ByteArrayOutputStream constructor

Reproduction Steps

Invoke ClientPreparedQueryBindings::setBytes with a large byte array

Possible Solution

No response

Additional Information/Context

No response

The AWS JDBC Driver for MySQL version used

1.1.0

JDK version used

17

Operating System and version

Windows 10 enterprise

fgoldenberg-sdl avatar Sep 14 '22 06:09 fgoldenberg-sdl

Hello @fgoldenberg-sdl

Thank you for raising the issue. We understand this issue is causing inconveniences in your workflows. We'll be investigating this issue and will update you when we have a release. We appreciate your patience.

sergiyvamz avatar Sep 14 '22 17:09 sergiyvamz

Hello @fgoldenberg-sdl

The driver has been recently rebased onto MySQL Connector/J 8.0.31. Will you be able to test out a snapshot build here and let us know if the issue persists?

Thank you!

sergiyvamz avatar Oct 19 '22 21:10 sergiyvamz

Closing this issue since it has been addressed in #295. Pleas re-open this issue if it is still a problem.

hsuamz avatar Dec 13 '22 00:12 hsuamz

This issue still occurs on versions 1.1.2 and 1.1.3 of the driver. My colleague @fgoldenberg-sdl raised the above error.

The error on our latest run against 1.1.3 is:

Caused by: java.lang.IllegalArgumentException: Negative initial size: -1818412943 2023-01-18T15:37:15.628419002Z at java.base/java.io.ByteArrayOutputStream.<init>(ByteArrayOutputStream.java:76) 2023-01-18T15:37:15.628421284Z at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.protocol.a.AbstractValueEncoder.escapeBytesIfNeeded(AbstractValueEncoder.java:227) 2023-01-18T15:37:15.628423517Z at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.protocol.a.ByteArrayValueEncoder.getBytes(ByteArrayValueEncoder.java:58) 2023-01-18T15:37:15.628425687Z at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.protocol.a.AbstractValueEncoder.encodeAsText(AbstractValueEncoder.java:92) 2023-01-18T15:37:15.628427875Z at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.NativeQueryBindValue.writeAsText(NativeQueryBindValue.java:383) 2023-01-18T15:37:15.628432608Z at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.protocol.a.NativeMessageBuilder.buildComQuery(NativeMessageBuilder.java:175) 2023-01-18T15:37:15.628434994Z at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.protocol.a.NativeMessageBuilder.buildComQuery(NativeMessageBuilder.java:51) 2023-01-18T15:37:15.628437185Z at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.ClientPreparedQuery.fillSendPacket(ClientPreparedQuery.java:222) 2023-01-18T15:37:15.628439386Z at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1047) 2023-01-18T15:37:15.628441580Z at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1009) 2023-01-18T15:37:15.628443784Z at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1320) 2023-01-18T15:37:15.628446019Z at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:994) 2023-01-18T15:37:15.628448748Z at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105) 2023-01-18T15:37:15.628452759Z at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105) 2023-01-18T15:37:15.628456130Z at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105) 2023-01-18T15:37:15.628459527Z at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175) 2023-01-18T15:37:15.628461928Z at org.hibernate.dialect.identity.GetGeneratedKeysDelegate.executeAndExtract(GetGeneratedKeysDelegate.java:57) 2023-01-18T15:37:15.628464075Z at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:42) 2023-01-18T15:37:15.628466337Z at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3077) 2023-01-18T15:37:15.628468489Z at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3667) 2023-01-18T15:37:15.628470620Z at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81) 2023-01-18T15:37:15.628472866Z at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:645) 2023-01-18T15:37:15.628474973Z at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:282) 2023-01-18T15:37:15.628477101Z at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:263) 2023-01-18T15:37:15.628479222Z at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:317) 2023-01-18T15:37:15.628481298Z at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:332) 2023-01-18T15:37:15.628483402Z at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:289) 2023-01-18T15:37:15.628489550Z at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:196) 2023-01-18T15:37:15.628491943Z at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:127) 2023-01-18T15:37:15.628494141Z at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:192) 2023-01-18T15:37:15.628496283Z at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135) 2023-01-18T15:37:15.628498437Z at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:62) 2023-01-18T15:37:15.628500618Z at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:800) 2023-01-18T15:37:15.628502762Z at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:785) 2023-01-18T15:37:15.628505260Z at jdk.internal.reflect.GeneratedMethodAccessor208.invoke(Unknown Source) 2023-01-18T15:37:15.628507419Z at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 2023-01-18T15:37:15.628530292Z at java.base/java.lang.reflect.Method.invoke(Method.java:566) 2023-01-18T15:37:15.628538605Z at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:351) 2023-01-18T15:37:15.628541299Z at com.sun.proxy.$Proxy161.persist(Unknown Source)

What I also notice when this code runs is that the JVM consumes all the memory available to it, regardless of the binary we are trying to store. For example, I tried to persist a 1.2Gb binary, with 12Gb Xmx setting. Java consumed all 12Gb of memory, threw the above error, then ran out of memory:

java.lang.OutOfMemoryError: Direct buffer memory 2023-01-18T15:37:16.558363998Z at java.base/java.nio.Bits.reserveMemory(Bits.java:175) 2023-01-18T15:37:16.558396187Z at java.base/java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:118) 2023-01-18T15:37:16.558404639Z at java.base/java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:317) 2023-01-18T15:37:16.558409586Z at java.base/sun.nio.ch.Util.getTemporaryDirectBuffer(Util.java:242) 2023-01-18T15:37:16.558413618Z at java.base/sun.nio.ch.IOUtil.read(IOUtil.java:242) 2023-01-18T15:37:16.558423981Z at java.base/sun.nio.ch.FileChannelImpl.read(FileChannelImpl.java:223) 2023-01-18T15:37:16.558585642Z at java.base/sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:65) 2023-01-18T15:37:16.558603493Z at java.base/sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:107) 2023-01-18T15:37:16.558812494Z at java.base/sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:101) 2023-01-18T15:37:16.558826340Z at java.base/java.nio.file.Files.read(Files.java:3159) 2023-01-18T15:37:16.558836978Z at java.base/java.nio.file.Files.readAllBytes(Files.java:3213)

Any thoughts on next steps?

ben-gineer avatar Jan 18 '23 15:01 ben-gineer