@@ -61,9 +61,14 @@ public void applyDelta() {
61
61
target .bitsPerMapPointer = delta .bitsPerMapPointer ;
62
62
target .bitsPerMapSizeValue = delta .bitsPerMapSizeValue ;
63
63
target .bitsPerKeyElement = delta .bitsPerKeyElement ;
64
- target .bitsPerValueElement = delta .bitsPerValueElement ;
64
+ // Prior to Jan 2025, the producer was able to generate blobs where it reserved 0 bits for the
65
+ // Map value element when all keys stored records referencing ordinal 0. In this case, when reading
66
+ // the value of the last bucket, the code would trigger ArrayIndexOutOfBoundsException since there
67
+ // no space reserved for the value element. This is a workaround to avoid the exception when
68
+ // transitioning from one of these bad blobs.
69
+ target .bitsPerValueElement = delta .bitsPerValueElement == 0 ? 1 : delta .bitsPerValueElement ;
65
70
target .bitsPerFixedLengthMapPortion = delta .bitsPerFixedLengthMapPortion ;
66
- target .bitsPerMapEntry = delta . bitsPerMapEntry ;
71
+ target .bitsPerMapEntry = target . bitsPerKeyElement + target . bitsPerValueElement ;
67
72
target .emptyBucketKeyValue = delta .emptyBucketKeyValue ;
68
73
target .totalNumberOfBuckets = delta .totalNumberOfBuckets ;
69
74
@@ -143,7 +148,15 @@ private void mergeOrdinal(int ordinal) {
143
148
if (!removeData ) {
144
149
for (long bucketIdx =currentFromStateStartBucket ; bucketIdx <fromDataEndBucket ; bucketIdx ++) {
145
150
long bucketKey = from .entryData .getElementValue (bucketIdx * from .bitsPerMapEntry , from .bitsPerKeyElement );
146
- long bucketValue = from .entryData .getElementValue (bucketIdx * from .bitsPerMapEntry + from .bitsPerKeyElement , from .bitsPerValueElement );
151
+ // Prior to Jan 2025, the producer was able to generate blobs where it reserved 0 bits for the
152
+ // Map value element when all keys stored records referencing ordinal 0. In this case, when reading
153
+ // the value of the last bucket, the code would trigger ArrayIndexOutOfBoundsException since there
154
+ // no space reserved for the value element. This is a workaround to avoid the exception when
155
+ // transitioning from one of these bad blobs.
156
+ long bucketValue =
157
+ from .bitsPerValueElement == 0
158
+ ? 0
159
+ : from .entryData .getElementValue (bucketIdx * from .bitsPerMapEntry + from .bitsPerKeyElement , from .bitsPerValueElement );
147
160
if (bucketKey == from .emptyBucketKeyValue )
148
161
bucketKey = target .emptyBucketKeyValue ;
149
162
long currentWriteStartBucketBit = currentWriteStartBucket * target .bitsPerMapEntry ;
0 commit comments