Skip to content

fix(proto): check plan integer conversions across usize boundaries - #24483

Merged
adriangb merged 7 commits into
apache:mainfrom
buraksenn:24170-plan-serde
Aug 27, 2026
Merged

fix(proto): check plan integer conversions across usize boundaries#24483
adriangb merged 7 commits into
apache:mainfrom
buraksenn:24170-plan-serde

Conversation

@buraksenn

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

Several logical and physical plan protobuf paths convert wire integers to usize with unchecked casts. On 32-bit targets, values above u32::MAX silently truncate. For row limits, a fetch of 1 << 32 becomes 0, causing a plan that should return rows to return an empty result.

The reverse conversion can also truncate when a 64-bit usize does not fit the protobuf field.

What changes are included in this PR?

  • Add shared helpers for checked conversions between wire integers and usize, with errors identifying the plan node and field.
  • Apply checked conversions to limits, partition counts, batch sizes, capacities, and indexes across logical and physical plan serialization.
  • Preserve the documented -1 sentinel for limits without a fetch.
  • Reject invalid zero batch sizes while preserving proto3 defaults for older FilterExec payloads.
  • Treat out-of-range usize statistics as unknown rather than truncating them.

The protobuf wire format is unchanged.

Follow-up work will make common protobuf option and constraint conversions fallible.

Are these changes tested?

Yes. Added unit and protobuf roundtrip coverage for checked conversions, architecture-dependent integer boundaries, oversized encode/decode values, limits without a fetch, malformed zero-column Values nodes, and zero batch sizes.

Are there any user-facing changes?

Out-of-range plan integers now return a clear planning error instead of silently truncating. Invalid zero batch sizes are rejected, and out-of-range statistics become unknown. There are no breaking public API or protobuf wire-format changes.

@github-actions github-actions Bot added logical-expr Logical plan and expressions physical-expr Changes to the physical-expr crates common Related to common crate proto Related to proto crate functions Changes to functions implementation datasource Changes to the datasource crate physical-plan Changes to the physical-plan crate labels Aug 19, 2026
@codecov-commenter

codecov-commenter commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 73.86364% with 69 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.45%. Comparing base (872df4d) to head (7dcae9f).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
datafusion/expr/src/logical_plan/plan.rs 53.57% 8 Missing and 5 partials ⚠️
datafusion/proto/src/logical_plan/mod.rs 47.05% 5 Missing and 4 partials ⚠️
datafusion/physical-plan/src/filter.rs 77.14% 3 Missing and 5 partials ⚠️
...usion/physical-plan/src/windows/window_agg_exec.rs 0.00% 6 Missing ⚠️
datafusion/physical-plan/src/coalesce_batches.rs 70.58% 1 Missing and 4 partials ⚠️
datafusion/physical-plan/src/limit.rs 54.54% 0 Missing and 5 partials ⚠️
datafusion/proto/src/physical_plan/mod.rs 61.53% 3 Missing and 2 partials ⚠️
...atafusion/datasource/src/file_scan_config/proto.rs 84.21% 0 Missing and 3 partials ⚠️
datafusion/physical-expr/src/partitioning.rs 57.14% 0 Missing and 3 partials ⚠️
datafusion/datasource/src/memory.rs 81.81% 0 Missing and 2 partials ⚠️
... and 8 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #24483      +/-   ##
==========================================
- Coverage   81.45%   81.45%   -0.01%     
==========================================
  Files        1119     1120       +1     
  Lines      400411   401470    +1059     
  Branches   400411   401470    +1059     
==========================================
+ Hits       326144   327006     +862     
- Misses      55195    55308     +113     
- Partials    19072    19156      +84     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@buraksenn
buraksenn marked this pull request as draft August 19, 2026 21:48
@buraksenn
buraksenn marked this pull request as ready for review August 20, 2026 10:36
# Conflicts:
#	datafusion/physical-plan/src/joins/hash_join/exec.rs
@buraksenn

Copy link
Copy Markdown
Contributor Author

@adriangb can you review when you find time?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds checked usize/protobuf integer conversions across logical and physical plan serialization to prevent truncation on 32-bit targets.

Changes:

  • Introduces shared checked wire-conversion helpers.
  • Applies them to limits, sizes, capacities, partition counts, indexes, and statistics.
  • Adds boundary, malformed-input, sentinel, and zero-batch-size tests.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
datafusion/common/src/utils/mod.rs Adds shared checked conversion helpers.
datafusion/expr/src/logical_plan/plan.rs Checks SQL limit and offset conversions.
datafusion/functions-table/src/generate_series.rs Rejects zero batch sizes.
datafusion/proto/src/logical_plan/mod.rs Checks logical-plan integer conversions and limit sentinels.
datafusion/proto/src/physical_plan/mod.rs Checks generate-series batch sizes.
datafusion/proto-common/src/from_proto/mod.rs Treats oversized statistics as unknown.
datafusion/physical-expr/src/partitioning.rs Checks partition-count conversions.
datafusion/physical-expr/src/scalar_subquery.rs Checks scalar-subquery index encoding.
datafusion/physical-plan/src/aggregates/mod.rs Checks aggregate limits.
datafusion/physical-plan/src/buffer.rs Checks buffer capacity decoding.
datafusion/physical-plan/src/coalesce_batches.rs Checks sizes and rejects zero batches.
datafusion/physical-plan/src/coalesce_partitions.rs Checks fetch conversions.
datafusion/physical-plan/src/empty.rs Checks partition-count encoding.
datafusion/physical-plan/src/filter.rs Checks sizes and validates batch sizes.
datafusion/physical-plan/src/joins/hash_join/exec.rs Uses shared checked fetch decoding.
datafusion/physical-plan/src/limit.rs Checks global and local limits.
datafusion/physical-plan/src/placeholder_row.rs Checks partition-count encoding.
datafusion/physical-plan/src/sorts/sort.rs Checks sort fetch conversions.
datafusion/physical-plan/src/sorts/sort_preserving_merge.rs Checks merge fetch conversions.
datafusion/physical-plan/src/unnest.rs Checks struct-column indexes.
datafusion/physical-plan/src/windows/window_agg_exec.rs Checks window-column indexes.
datafusion/datasource/src/file_scan_config/proto.rs Checks scan limits and batch sizes.
datafusion/datasource/src/memory.rs Checks memory-scan fetch values.
datafusion/proto/tests/cases/plans/leaves.rs Tests oversized partition counts.
datafusion/proto/tests/cases/plans/limits.rs Tests limit boundaries and zero batches.
datafusion/proto/tests/cases/plans/misc.rs Updates partitioning error assertions.
datafusion/proto/tests/cases/roundtrip_logical_plan.rs Tests logical limits and malformed values.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread datafusion/datasource/src/file_scan_config/proto.rs

@adriangb adriangb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than the public API question this seems like a good change! Without having counted I'm going to say that if making these pub(crate) would require duplicating in 3 or more places (not counting tests) then we should keep it pub as is. If it's 2 or less places lets just duplicate it. I hope that's a fair unbiased opinion 😄

Comment on lines +1149 to +1161
pub fn usize_from_wire<T>(value: T, context: &str, field: &str) -> Result<usize>
where
T: TryInto<usize> + std::fmt::Display + Copy,
{
value.try_into().map_err(|_| {
_plan_datafusion_err!(
"{context}: {field} wire value {value} is out of range for usize"
)
})
}

/// Converts a `usize` to a wire integer, rejecting out-of-range values.
pub fn usize_to_wire<T: TryFrom<usize>>(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these need to be public in this crate, or is there a version where they're private and close the the callers? I'd almost prefer to duplicate a small helper like this in 2 crates than expose it to the public API.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've checked and counted these helpers are used in 4 crates in this PR. Moreover, I've a followup work on this issue to wrap it up and will use helpers there as well. Thus, keeping them public as you've advised

@adriangb
adriangb added this pull request to the merge queue Aug 27, 2026
Merged via the queue into apache:main with commit 2a7a1e3 Aug 27, 2026
41 checks passed
@buraksenn
buraksenn deleted the 24170-plan-serde branch August 27, 2026 13:22
@buraksenn

Copy link
Copy Markdown
Contributor Author

I've opened the followup to wrapup the issue in #24726 cc @adriangb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

common Related to common crate datasource Changes to the datasource crate functions Changes to functions implementation logical-expr Logical plan and expressions physical-expr Changes to the physical-expr crates physical-plan Changes to the physical-plan crate proto Related to proto crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants