Skip to content

Commit 86f0857

Browse files
committed
GH-1261: Reject out-of-range dictionary indices in decode
1 parent fa20039 commit 86f0857

2 files changed

Lines changed: 29 additions & 2 deletions

File tree

vector/src/main/java/org/apache/arrow/vector/dictionary/DictionaryEncoder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ static void retrieveIndexVector(
165165
for (int i = start; i < end; i++) {
166166
if (!indices.isNull(i)) {
167167
int indexAsInt = (int) indices.getValueAsLong(i);
168-
if (indexAsInt > dictionaryCount) {
168+
if (indexAsInt < 0 || indexAsInt >= dictionaryCount) {
169169
throw new IllegalArgumentException(
170170
"Provided dictionary does not contain value for index " + indexAsInt);
171171
}

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

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,33 @@ public void testNoMemoryLeak() {
942942
assertEquals(0, allocator.getAllocatedMemory(), "decode memory leak");
943943
}
944944

945+
@Test
946+
public void testDecodeIndexOutOfBounds() {
947+
// valid indices are 0..dictionaryCount-1; index == dictionaryCount and negative indices
948+
// must be rejected before dereferencing the dictionary vector.
949+
try (final IntVector indices = newVector(IntVector.class, "", Types.MinorType.INT, allocator);
950+
final VarCharVector dictionaryVector = newVarCharVector("dict", allocator)) {
951+
setVector(dictionaryVector, zero, one);
952+
Dictionary dictionary =
953+
new Dictionary(dictionaryVector, new DictionaryEncoding(1L, false, null));
954+
955+
setVector(indices, 2);
956+
try (final ValueVector decoded = DictionaryEncoder.decode(indices, dictionary, allocator)) {
957+
fail("There should be an exception when decoding an index equal to the dictionary size");
958+
} catch (IllegalArgumentException e) {
959+
assertEquals("Provided dictionary does not contain value for index 2", e.getMessage());
960+
}
961+
962+
setVector(indices, -1);
963+
try (final ValueVector decoded = DictionaryEncoder.decode(indices, dictionary, allocator)) {
964+
fail("There should be an exception when decoding a negative index");
965+
} catch (IllegalArgumentException e) {
966+
assertEquals("Provided dictionary does not contain value for index -1", e.getMessage());
967+
}
968+
}
969+
assertEquals(0, allocator.getAllocatedMemory(), "decode memory leak");
970+
}
971+
945972
@Test
946973
public void testListNoMemoryLeak() {
947974
// Create a new value vector
@@ -1053,7 +1080,7 @@ public void testStructNoMemoryLeak() {
10531080
NullableStructWriter writer = indices.getWriter();
10541081
writer.allocate();
10551082
writer.start();
1056-
writer.integer("f0").writeInt(1);
1083+
writer.integer("f0").writeInt(0);
10571084
writer.integer("f1").writeInt(3);
10581085
writer.end();
10591086
writer.setValueCount(1);

0 commit comments

Comments
 (0)