jaideeppyne commented on code in PR #11136:
URL: https://github.com/apache/arrow-rs/pull/11136#discussion_r4514998393


##########
parquet/tests/arrow_reader/bad_data.rs:
##########
@@ -149,6 +155,56 @@ fn test_arrow_gh_47662() {
     );
 }
 
+#[test]
+fn test_byte_stream_split_truncated_page() {

Review Comment:
   Done in 0e75fbd. The 487 byte file is now checked in as 
`parquet/tests/arrow_reader/ARROW-RS-GH-11136-bss-truncated.parquet` (byte for 
byte the reproducer linked in the description) and the test reads it with 
`include_bytes!`, the same way `bigdelta.parquet` is used. The writer and 
header patching code is gone.
   



##########
parquet/src/column/reader/decoder.rs:
##########
@@ -684,8 +684,49 @@ impl RepetitionLevelDecoder for RepetitionLevelDecoderImpl 
{
 #[cfg(test)]
 mod tests {
     use super::*;
+    use crate::data_type::DoubleType;
     use crate::encodings::rle::RleEncoder;
+    use crate::schema::types::{ColumnDescriptor, ColumnPath, Type as 
SchemaType};
     use rand::{prelude::*, rng};
+    use std::sync::Arc;
+
+    #[test]
+    fn test_byte_stream_split_v1_nulls_use_encoded_len() {

Review Comment:
   Not enough to justify it, so I removed it in 0e75fbd.
   
   The case it pinned is a V1 nullable page where the level count is larger 
than the number of encoded values. That is already covered end to end: when I 
temporarily made `set_data` require `num_values == data.len() / type_size`, 
`arrow::arrow_reader::tests::column_reader::test_primitive_single_column_reader_test`
 and `arrow::arrow_writer::tests::statistics_null_counts_only_nulls` both 
failed. The corrupt count case is covered by the checked-in file.
   



##########
parquet/src/encodings/decoding/byte_stream_split_decoder.rs:
##########
@@ -86,9 +86,18 @@ fn join_streams_variable(
 }
 
 impl<T: DataType> Decoder<T> for ByteStreamSplitDecoder<T> {
-    fn set_data(&mut self, data: Bytes, num_values: usize) -> Result<()> {
+    fn set_data(&mut self, data: Bytes, _num_values: usize) -> Result<()> {

Review Comment:
   Good point, ignoring it entirely was too loose. In 0e75fbd both decoders now 
check it as an upper bound: `set_data` returns an error if the page holds more 
encoded values than `num_values`.
   
   It can't be strict equality. `ColumnValueDecoderImpl::set_data` passes 
`num_values.unwrap_or(num_levels)`. For V2 pages that is the non-null count, 
but for V1 pages it is the level count, which includes nulls (and for repeated 
columns every level), while only non-null values are encoded. With an equality 
check, reading ordinary nullable V1 pages fails; the two existing tests 
mentioned in the other thread fail that way.
   
   The other direction, fewer encoded values than `num_values`, is the #11121 
case. Since `values_left()` now comes from the encoded length, `get` and `skip` 
stop at the end of the streams and the column reader returns `insufficient 
values read from column`, instead of `join_streams_const` indexing past the 
buffer. That is also why a separate length check in `get` (the other option 
@jhorstmann mentioned) isn't needed.
   



##########
parquet/src/encodings/decoding/byte_stream_split_decoder.rs:
##########
@@ -164,7 +173,7 @@ impl<T: DataType> VariableWidthByteStreamSplitDecoder<T> {
 }
 
 impl<T: DataType> Decoder<T> for VariableWidthByteStreamSplitDecoder<T> {
-    fn set_data(&mut self, data: Bytes, num_values: usize) -> Result<()> {
+    fn set_data(&mut self, data: Bytes, _num_values: usize) -> Result<()> {

Review Comment:
   Same change here: `VariableWidthByteStreamSplitDecoder::set_data` uses the 
same upper bound check through a shared `check_encoded_value_count` helper, and 
`test_byte_stream_split_rejects_more_values_than_expected` covers both decoders.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to