[ 
https://issues.apache.org/jira/browse/AVRO-4268?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

ASF GitHub Bot updated AVRO-4268:
---------------------------------
    Labels: pull-request-available  (was: )

> BytesWritableConverter serializes unused capacity bytes
> -------------------------------------------------------
>
>                 Key: AVRO-4268
>                 URL: https://issues.apache.org/jira/browse/AVRO-4268
>             Project: Apache Avro
>          Issue Type: Bug
>          Components: java
>            Reporter: Ruiqi Dong
>            Priority: Major
>              Labels: pull-request-available
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> *Summary*
> `AvroDatumConverterFactory.BytesWritableConverter` converts Hadoop 
> `BytesWritable` to Avro `bytes` using `ByteBuffer.wrap(input.getBytes())`. 
> `BytesWritable.getBytes()` returns the backing array, whose length can be 
> larger than the logical value length reported by `getLength()`. The converter 
> therefore serializes stale or unused capacity bytes.
>  
> *Affected code*
> File: 
> `lang/java/mapred/src/main/java/org/apache/avro/hadoop/io/AvroDatumConverterFactory.java`
> {code:java}
> @Override
> public ByteBuffer convert(BytesWritable input) {
>   return ByteBuffer.wrap(input.getBytes());
> } {code}
> *Reproducer*
> Add this test to 
> `lang/java/mapred/src/test/java/org/apache/avro/hadoop/io/TestAvroDatumConverterFactory.java`
> {code:java}
> @Test
> void convertBytesWritableRespectsLogicalLength() {
>   AvroDatumConverter<BytesWritable, ByteBuffer> converter = 
> mFactory.create(BytesWritable.class);
>   BytesWritable writable = new BytesWritable(new byte[] { 1, 2, 3, 4, 5 });
>   writable.setSize(3);
>   ByteBuffer bytes = converter.convert(writable);
>   assertEquals(3, bytes.remaining());
>   assertEquals(1, bytes.get(0));
>   assertEquals(2, bytes.get(1));
>   assertEquals(3, bytes.get(2));
> } {code}
> Run:
> {code:java}
> MAVEN_SKIP_RC=true 
> JAVA_HOME=/opt/homebrew/Cellar/openjdk@21/21.0.6/libexec/openjdk.jdk/Contents/Home
>  \
> PATH=/opt/homebrew/Cellar/openjdk@21/21.0.6/libexec/openjdk.jdk/Contents/Home/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin
>  \
> /opt/homebrew/bin/mvn -q -t toolchains-local.xml -pl lang/java/mapred -am \
>   
> -Dtest=org.apache.avro.hadoop.io.TestAvroDatumConverterFactory#convertBytesWritableRespectsLogicalLength
>  \
>   -DfailIfNoTests=false -Dsurefire.failIfNoSpecifiedTests=false 
> -Dinvoker.skip=true -Drat.skip=true test
>  {code}
> *Observed behavior*
> The converted `ByteBuffer` has `remaining() == 5`.
> *Expected behavior*
> The converted `ByteBuffer` should have `remaining() == input.getLength()`, 
> which is `3` in the reproducer.
> Hadoop `BytesWritable` separates capacity from logical length. Avro `bytes` 
> should encode only the logical value, not unused backing-array capacity. The 
> likely fix is `ByteBuffer.wrap(input.copyBytes())` or 
> `ByteBuffer.wrap(input.getBytes(), 0, input.getLength())`.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to