Skip to content

Commit

Permalink
fix oob in get operation of list namespace
Browse files Browse the repository at this point in the history
  • Loading branch information
ritchie46 committed Feb 4, 2022
1 parent 3d5a865 commit 43d097d
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 6 deletions.
10 changes: 5 additions & 5 deletions polars/polars-arrow/src/index.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
pub(crate) trait IndexToUsize {
/// Translate the negative index to an offset.
fn to_usize(self, length: usize) -> Option<usize>;
fn negative_to_usize(self, index: usize) -> Option<usize>;
}

impl IndexToUsize for i64 {
fn to_usize(self, length: usize) -> Option<usize> {
if self >= 0 && (self as usize) < length {
fn negative_to_usize(self, index: usize) -> Option<usize> {
if self >= 0 && (self as usize) < index {
Some(self as usize)
} else {
let subtract = self.abs() as usize;
if subtract > length {
if subtract > index {
None
} else {
Some(length - subtract)
Some(index - subtract)
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion polars/polars-arrow/src/kernels/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ fn sublist_get_indexes(arr: &ListArray<i64>, index: i64) -> PrimitiveArray<u32>
let a: PrimitiveArray<u32> = iter
.map(|&offset| {
let len = offset - previous;
// make sure that empty lists don't get accessed
if len == 0 {
return None;
}
previous = offset;

let out = index
.to_usize(len as usize)
.negative_to_usize(len as usize)
.map(|idx| idx as u32 + cum_offset);
cum_offset += len as u32;
out
Expand Down
20 changes: 20 additions & 0 deletions py-polars/tests/test_lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,23 @@ def test_list_append() -> None:

out_s = df["a"].arr.concat(([4, 1]))
assert out_s[0].to_list() == [1, 2, 4, 1]


def test_list_arr_empty() -> None:
df = pl.DataFrame({"cars": [[1, 2, 3], [2, 3], [4], []]})

out = df.select(
[
pl.col("cars").arr.first().alias("cars_first"),
pl.when(pl.col("cars").arr.first() == 2)
.then(1)
.when(pl.col("cars").arr.contains(2))
.then(2)
.otherwise(3)
.alias("cars_literal"),
]
)
expected = pl.DataFrame(
{"cars_first": [1, 2, 4, None], "cars_literal": [2, 1, 3, 3]}
)
assert out.frame_equal(expected)

0 comments on commit 43d097d

Please sign in to comment.