You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Stacked Borrows violation in PushDecoderStreamState::transition #21662
Miri detects a Stacked Borrows violation in datafusion-datasource-parquet/src/opener.rs at line 1258:
self.decoder.push_ranges(ranges, data)?;
A Unique retag (mutable borrow) of the decoder is created, then invalidated by a SharedReadOnly retag at an .await point in the unfold-based stream. When the future resumes, the original Unique tag no longer exists in the borrow stack.
This was found while testing DataFusion 54.0 with Apache DataFusion Comet. Comet runs Miri in CI and caught this: CI run. DataFusion does not currently run Miri in its own CI.
To Reproduce
Run Miri against any test that exercises the PushDecoderStreamState parquet stream path. In our case it was triggered by a test that calls scan.execute(...).collect().await on a parquet scan.
Expected behavior
No undefined behavior under Miri's Stacked Borrows model.
Miri output
error: Undefined Behavior: trying to retag from <28128923> for SharedReadWrite permission at alloc8513101[0x8], but that tag does not exist in the borrow stack for this location
--> datafusion/datasource-parquet/src/opener.rs:1258:25
|
1258 | self.decoder.push_ranges(ranges, data)?;
| ^^^^^^^^^^^^ this error occurs as part of two-phase retag at alloc8513101[0x8..0x20]
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
help: <28128923> was created by a Unique retag at offsets [0x8..0x20]
help: <28128923> was later invalidated at offsets [0x0..0x138] by a SharedReadOnly retag
Additional context
The full backtrace points to PushDecoderStreamState::transition -> RowGroupsPrunedParquetOpen::build_stream closure -> futures::stream::Unfold poll. The aliasing violation occurs because the decoder is mutably re-borrowed across a yield point in the unfold stream.
Reopening — the fix in #21663 removed the nested async block but miri still reports a Stacked Borrows violation at the same location (opener.rs:1267). The inlined code still reborrows &mut self across the .await yield point in get_byte_ranges, which conflicts with the subsequent self.decoder.push_ranges() call. Miri sees these as overlapping reborrows of the same &mut self even though they access disjoint fields.
error: Undefined Behavior: trying to retag from <28193196> for SharedReadWrite permission at alloc8537353[0x8], but that tag does not exist in the borrow stack for this location
--> datafusion/datasource-parquet/src/opener.rs:1267:45
|
1267 | ... if let Err(e) = self.decoder.push_ranges(ranges, data) {
| ^^^^^^^^^^^^ this error occurs as part of two-phase retag at alloc8537353[0x8..0x20]
A possible fix would be to destructure self into its fields before the loop so that miri can see the disjoint borrows explicitly, e.g.:
letSelf{ reader, decoder, baseline_metrics, .. } = self;// then use reader, decoder, baseline_metrics directly
Activity
fix: Remove nested async block causing Stacked Borrows violation in P…
mbutrovich commentedon Apr 16, 2026
Reopening — the fix in #21663 removed the nested async block but miri still reports a Stacked Borrows violation at the same location (
opener.rs:1267). The inlined code still reborrows&mut selfacross the.awaityield point inget_byte_ranges, which conflicts with the subsequentself.decoder.push_ranges()call. Miri sees these as overlapping reborrows of the same&mut selfeven though they access disjoint fields.Reproducer: running Comet's miri tests against current DF main (commit 2ef0217) triggers this on
test_nested_types_extract_missing_struct_names_missing_field. CI run: https://github.com/apache/datafusion-comet/actions/runs/24518967597/job/71671004017?pr=3916A possible fix would be to destructure
selfinto its fields before the loop so that miri can see the disjoint borrows explicitly, e.g.:CC @Dandandan
mbutrovich commentedon Apr 16, 2026
Draft PR with a fix while I test in Comet CI:
#21680
apache/datafusion-comet#3960
fix: try again to fix Miri in ParquetOpener (#21680)
fix: Remove nested async block causing Stacked Borrows violation in P…
fix: try again to fix Miri in ParquetOpener (apache#21680)