-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Create empty buffer for a buffer specified in the C Data Interface with length zero #8009
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fee27e9
61ae752
95f3159
a946370
27ab028
72429fd
568746f
f7e4bdd
b6da8d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -408,7 +408,17 @@ impl ImportedArrowArray<'_> { | |
| .map(|index| { | ||
| let len = self.buffer_len(index, variadic_buffer_lens, &self.data_type)?; | ||
| match unsafe { create_buffer(self.owner.clone(), self.array, index, len) } { | ||
| Some(buf) => Ok(buf), | ||
| Some(buf) => { | ||
| // External libraries may use a dangling pointer for a buffer with length 0. | ||
| // We respect the array length specified in the C Data Interface. Actually, | ||
| // if the length is incorrect, we cannot create a correct buffer even if | ||
| // the pointer is valid. | ||
| if buf.is_empty() { | ||
| Ok(MutableBuffer::new(0).into()) | ||
| } else { | ||
| Ok(buf) | ||
| } | ||
| } | ||
| None if len == 0 => { | ||
| // Null data buffer, which Rust doesn't allow. So create | ||
| // an empty buffer. | ||
|
|
@@ -1296,9 +1306,15 @@ mod tests_to_then_from_ffi { | |
|
|
||
| #[cfg(test)] | ||
| mod tests_from_ffi { | ||
| #[cfg(not(feature = "force_validate"))] | ||
| use std::ptr::NonNull; | ||
| use std::sync::Arc; | ||
|
|
||
| #[cfg(feature = "force_validate")] | ||
| use arrow_buffer::{bit_util, buffer::Buffer}; | ||
| #[cfg(not(feature = "force_validate"))] | ||
| use arrow_buffer::{bit_util, buffer::Buffer, ScalarBuffer}; | ||
|
|
||
| use arrow_data::transform::MutableArrayData; | ||
| use arrow_data::ArrayData; | ||
| use arrow_schema::{DataType, Field}; | ||
|
|
@@ -1660,6 +1676,25 @@ mod tests_from_ffi { | |
| } | ||
| } | ||
|
|
||
| #[test] | ||
| #[cfg(not(feature = "force_validate"))] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand why this can't work with I ran the test without this line and it seems to work fine: diff --git a/arrow-array/src/ffi.rs b/arrow-array/src/ffi.rs
index 2ee2fd379e..5b05bcd81d 100644
--- a/arrow-array/src/ffi.rs
+++ b/arrow-array/src/ffi.rs
@@ -621,7 +621,6 @@ mod tests_to_then_from_ffi {
}
#[test]
- #[cfg(not(feature = "force_validate"))]
fn test_decimal_round_trip() -> Result<()> {
// create an array natively
let original_array = [Some(12345_i128), Some(-12345_i128), None]
@@ -1523,7 +1522,6 @@ mod tests_from_ffi {
}
#[test]
- #[cfg(not(feature = "force_validate"))]
fn test_empty_string_with_non_zero_offset() -> Result<()> {
use super::ImportedArrowArray;
use arrow_buffer::{MutableBuffer, OffsetBuffer};
@@ -1677,7 +1675,6 @@ mod tests_from_ffi {
}
#[test]
- #[cfg(not(feature = "force_validate"))]
fn test_utf8_view_ffi_from_dangling_pointer() {
let empty = GenericByteViewBuilder::<StringViewType>::new().finish();
let buffers = empty.data_buffers().to_vec();cargo test -p arrow-array --features=ffi
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Because
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Right, so
Isn't that same? The test works when force_validate is not enabled 😕
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ? Yea, the test works when
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, did you want to ask why I added
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry I was confused |
||
| fn test_utf8_view_ffi_from_dangling_pointer() { | ||
| let empty = GenericByteViewBuilder::<StringViewType>::new().finish(); | ||
| let buffers = empty.data_buffers().to_vec(); | ||
| let nulls = empty.nulls().cloned(); | ||
|
|
||
| // Create a dangling pointer to a view buffer with zero length. | ||
| let alloc = Arc::new(1); | ||
| let buffer = unsafe { Buffer::from_custom_allocation(NonNull::<u8>::dangling(), 0, alloc) }; | ||
| let views = unsafe { ScalarBuffer::new_unchecked(buffer) }; | ||
|
|
||
| let str_view: GenericByteViewArray<StringViewType> = | ||
| unsafe { GenericByteViewArray::new_unchecked(views, buffers, nulls) }; | ||
| let imported = roundtrip_byte_view_array(str_view); | ||
| assert_eq!(imported.len(), 0); | ||
| assert_eq!(&imported, &empty); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_round_trip_byte_view() { | ||
| fn test_case<T>() | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this comment. I guess in my mind "if the length is incorrect we can't make a good buffer" is "obvious" but maybe it is not for other readers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just wanted to say that if there is a question on if the length is zero, but the pointer isn't a dangling pointer. Previously we simply take any non-null pointer as valid one and didn't consider the length. We ignored the possibility of a dangling pointer.