Skip to content

Add upper bound validation for DQ block_size in MatMulNBits fusion - #31678

Open
apsonawane wants to merge 1 commit into
mainfrom
fix/matmulnbits-blocksize-upper-bound
Open

Add upper bound validation for DQ block_size in MatMulNBits fusion#31678
apsonawane wants to merge 1 commit into
mainfrom
fix/matmulnbits-blocksize-upper-bound

Conversation

@apsonawane

Copy link
Copy Markdown
Contributor

This pull request introduces additional validation and safety checks for the block_size attribute in quantization-related code to prevent unsafe values from causing runtime errors. The main changes ensure that block_size is always within the safe range supported by the underlying MLAS kernel, avoiding potential divide-by-zero errors.

Validation and safety improvements for block_size:

  • Added a maximum block size guard (kMaxBlockSize = 256) in GetEffectiveBlockSize to cap user-supplied values and prevent unsafe block sizes from reaching the MLAS kernel, mirroring existing checks elsewhere.
  • Updated the validation logic in ValidateDQForMatMulNBits to require that block_size is a power of two in the range [16, 256], explicitly rejecting values above 256 to avoid integer overflow and possible divide-by-zero errors.

The DQ->MatMulNBits blockwise fusion selector now rejects models with
block_size > 256, mirroring the existing [16, 256] range enforced by
ComputeEffectiveBlockSize for the session-option path.

Without this cap, a model-supplied block_size >= 2^32 truncates to 0
via static_cast<int> in the MLAS transpose kernel, causing an integer
divide-by-zero (SIGFPE) at CreateSession time before any inference.

Changes:
- qdq_selectors.cc: extend the existing power-of-two check to also
  reject block_size > 256; invalid models skip the fusion cleanly.
- qdq_actions.cc: GetEffectiveBlockSize caps the raw model attribute
  at kMaxBlockSize (256) as defense-in-depth, so no oversized value
  can reach the MLAS kernel even if the selector is bypassed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@apsonawane
apsonawane requested a lite review from Copilot August 5, 2026 21:18

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

This PR hardens MatMulNBits fusion in the QDQ transformer by tightening validation of the DequantizeLinear block_size attribute so that only kernel-supported values reach the MLAS transpose path, preventing session-creation crashes from unsafe attributes.

Changes:

  • Enforced block_size to be a power-of-two within [16, 256] in MatMulNBits fusion eligibility checks.
  • Added an additional “safety guard” in block size computation to avoid unsafe values reaching the MLAS transpose call.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
onnxruntime/core/optimizer/qdq_transformer/selectors_actions/qdq_selectors.cc Tightens selector validation for blockwise DQ block_size and documents the safety rationale.
onnxruntime/core/optimizer/qdq_transformer/selectors_actions/qdq_actions.cc Adds extra guarding when deriving the effective block size used by the fusion action/MLAS transpose.

Comment on lines +779 to +781
// Must be a power-of-two in [16, 256]. Values beyond 256 would overflow int32 in the
// MLAS transpose kernel (static_cast<int>(block_size) == 0 for block_size >= 2^32),
// causing a divide-by-zero (SIGFPE) at CreateSession time.
Comment on lines +90 to +96
// Mirror the kMaxBlockSize guard from ComputeEffectiveBlockSize. Without this cap, a
// model-supplied block_size >= 2^32 truncates to 0 in the MLAS int32 transpose argument,
// causing a divide-by-zero at CreateSession. The selector rejects such models, but guard
// here too so any future selector bypass cannot reach MLAS with an unsafe value.
constexpr int64_t kMaxBlockSize = 256;
const int64_t block_size = bs_iter->second.i();
return (block_size <= kMaxBlockSize) ? block_size : kMaxBlockSize;
Comment on lines +782 to 783
if (block_size < 16 || block_size > 256 || ((block_size - 1) & block_size)) {
return false;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants