Skip to content

Commit b04380d

Browse files
committed
GH-1098: [Java][Vector] Fix always-true precondition check in LargeListVector.setValueCount
1 parent e54681b commit b04380d

2 files changed

Lines changed: 88 additions & 1 deletion

File tree

vector/src/main/java/org/apache/arrow/vector/complex/LargeListVector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ public void setValueCount(int valueCount) {
10411041
* TODO: revisit when 64-bit vectors are supported
10421042
*/
10431043
Preconditions.checkArgument(
1044-
childValueCount <= Integer.MAX_VALUE || childValueCount >= Integer.MIN_VALUE,
1044+
childValueCount <= Integer.MAX_VALUE && childValueCount >= 0,
10451045
"LargeListVector doesn't yet support 64-bit allocations: %s",
10461046
childValueCount);
10471047
vector.setValueCount((int) childValueCount);

vector/src/test/java/org/apache/arrow/vector/TestLargeListVector.java

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static org.junit.jupiter.api.Assertions.assertFalse;
2222
import static org.junit.jupiter.api.Assertions.assertNull;
2323
import static org.junit.jupiter.api.Assertions.assertSame;
24+
import static org.junit.jupiter.api.Assertions.assertThrows;
2425
import static org.junit.jupiter.api.Assertions.assertTrue;
2526

2627
import java.util.ArrayList;
@@ -1127,4 +1128,90 @@ private void writeIntValues(UnionLargeListWriter writer, int[] values) {
11271128
}
11281129
writer.endList();
11291130
}
1131+
1132+
@Test
1133+
public void testSetValueCountRejectsNegativeChildValueCount() {
1134+
try (final LargeListVector vector = LargeListVector.empty("list", allocator)) {
1135+
vector.addOrGetVector(FieldType.nullable(MinorType.INT.getType()));
1136+
vector.allocateNew();
1137+
1138+
// Write a negative value into the offset buffer to simulate a corrupted offset.
1139+
// The Preconditions check should reject any negative childValueCount.
1140+
vector.getOffsetBuffer().setLong(LargeListVector.OFFSET_WIDTH, -1L);
1141+
vector.setLastSet(0);
1142+
1143+
assertThrows(
1144+
IllegalArgumentException.class,
1145+
() -> vector.setValueCount(1),
1146+
"setValueCount should reject negative childValueCount");
1147+
}
1148+
}
1149+
1150+
@Test
1151+
public void testSetValueCountRejectsOverflowChildValueCount() {
1152+
try (final LargeListVector vector = LargeListVector.empty("list", allocator)) {
1153+
vector.addOrGetVector(FieldType.nullable(MinorType.INT.getType()));
1154+
vector.allocateNew();
1155+
1156+
// Write a value exceeding Integer.MAX_VALUE into the offset buffer
1157+
vector.getOffsetBuffer().setLong(LargeListVector.OFFSET_WIDTH, (long) Integer.MAX_VALUE + 1L);
1158+
vector.setLastSet(0);
1159+
1160+
assertThrows(
1161+
IllegalArgumentException.class,
1162+
() -> vector.setValueCount(1),
1163+
"setValueCount should reject childValueCount exceeding Integer.MAX_VALUE");
1164+
}
1165+
}
1166+
1167+
@Test
1168+
public void testSetValueCountAcceptsZeroChildValueCount() {
1169+
try (final LargeListVector vector = LargeListVector.empty("list", allocator)) {
1170+
vector.addOrGetVector(FieldType.nullable(MinorType.INT.getType()));
1171+
vector.allocateNew();
1172+
1173+
// childValueCount = 0 when valueCount = 0 (no elements)
1174+
vector.setValueCount(0);
1175+
assertEquals(0, vector.getValueCount());
1176+
}
1177+
}
1178+
1179+
@Test
1180+
public void testSetValueCountAcceptsValidChildValueCount() {
1181+
try (final LargeListVector vector = LargeListVector.empty("list", allocator)) {
1182+
vector.addOrGetVector(FieldType.nullable(MinorType.INT.getType()));
1183+
vector.allocateNew();
1184+
1185+
// Write a valid childValueCount (5) into the offset buffer
1186+
vector.getOffsetBuffer().setLong(LargeListVector.OFFSET_WIDTH, 5L);
1187+
vector.setLastSet(0);
1188+
vector.setValueCount(1);
1189+
assertEquals(1, vector.getValueCount());
1190+
}
1191+
}
1192+
1193+
@Test
1194+
public void testSetValueCountAcceptsMaxIntChildValueCount() {
1195+
try (final LargeListVector vector = LargeListVector.empty("list", allocator)) {
1196+
vector.addOrGetVector(FieldType.nullable(MinorType.INT.getType()));
1197+
vector.allocateNew();
1198+
1199+
// Write Integer.MAX_VALUE into the offset buffer to verify the upper boundary is inclusive.
1200+
// The Preconditions check should accept this value (not throw IllegalArgumentException).
1201+
// The child vector may throw OversizedAllocationException due to memory limits,
1202+
// which is expected and unrelated to the precondition validation.
1203+
vector.getOffsetBuffer().setLong(LargeListVector.OFFSET_WIDTH, (long) Integer.MAX_VALUE);
1204+
vector.setLastSet(0);
1205+
try {
1206+
vector.setValueCount(1);
1207+
} catch (IllegalArgumentException e) {
1208+
throw new AssertionError(
1209+
"setValueCount should not reject childValueCount = Integer.MAX_VALUE", e);
1210+
} catch (Exception e) {
1211+
// OversizedAllocationException or other allocation errors are expected
1212+
// when trying to allocate Integer.MAX_VALUE elements — this is fine,
1213+
// the precondition check itself passed.
1214+
}
1215+
}
1216+
}
11301217
}

0 commit comments

Comments
 (0)