Skip to content

Fix BitShift UB when shift amount >= bit width#28272

Open
Copilot wants to merge 3 commits intomainfrom
copilot/fix-onnx-runtime-bitshift-issue
Open

Fix BitShift UB when shift amount >= bit width#28272
Copilot wants to merge 3 commits intomainfrom
copilot/fix-onnx-runtime-bitshift-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 29, 2026

Description

Shifting by >= the bit width of an unsigned type is undefined behavior in C++. On x86-64, the hardware masks 64-bit shift amounts to 6 bits, so x >> 64 silently becomes x >> 0, returning the original value instead of 0.

Added SafeShiftLeft/SafeShiftRight helpers that return 0 when shift >= sizeof(T) * 8, applied across all three broadcast code paths (scalar-X, scalar-Y, element-wise).

template <typename T>
inline T SafeShiftRight(T value, T shift) {
  return shift >= sizeof(T) * 8 ? T{0} : value >> shift;
}

Added tests covering:

  • Shift by exact bit width (32, 64) for uint32_t and uint64_t
  • Shift by more than bit width (65, 128)
  • All three broadcast paths (scalar-X, scalar-Y, element-wise)
  • New tests are excluded for DirectML EP, which has the same hardware-level shift masking behavior

Motivation and Context

BitShift with direction="RIGHT" on uint64 inputs with shift amount 64 returns the original values instead of zeros. Reproduces with CPUExecutionProvider and ORT_DISABLE_ALL (constant folding masks the bug under ORT_ENABLE_ALL).

Shifting by >= the bit width of an unsigned integer type is undefined
behavior in C++. On x86, 64-bit shifts mask the shift amount to 6 bits,
so shifting uint64 by 64 effectively shifts by 0, returning the original
value instead of 0.

Add SafeShiftLeft/SafeShiftRight helpers that return 0 when the shift
amount >= the bit width, and use them in all three BitShift broadcast
code paths (scalar-X, scalar-Y, and element-wise).

Agent-Logs-Url: https://github.com/microsoft/onnxruntime/sessions/784db8bc-a08a-4d19-abcc-84a8421b4d05

Co-authored-by: tianleiwu <30328909+tianleiwu@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix ONNX Runtime CPU BitShift for uint64 shift amount of 64 Fix BitShift UB when shift amount >= bit width Apr 29, 2026
Copilot AI requested a review from tianleiwu April 29, 2026 17:13
@tianleiwu
Copy link
Copy Markdown
Contributor

@copilot, DirectML CI pipeline failed:
[ FAILED ] BitShiftOpTest.LeftShiftByBitWidth_Uint64
[ FAILED ] BitShiftOpTest.RightShiftByBitWidth_Uint32
[ FAILED ] BitShiftOpTest.ScalarLeftShiftByBitWidth_Uint64
Please skip those tests for DirectML EP.

DirectML has the same hardware-level shift masking behavior as the
original CPU issue, so these tests are not applicable to DML.

Agent-Logs-Url: https://github.com/microsoft/onnxruntime/sessions/92da631d-7a7f-4868-af90-510f7575710c

Co-authored-by: tianleiwu <30328909+tianleiwu@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 2, 2026

@copilot, DirectML CI pipeline failed:
[ FAILED ] BitShiftOpTest.LeftShiftByBitWidth_Uint64
[ FAILED ] BitShiftOpTest.RightShiftByBitWidth_Uint32
...

Excluded kDmlExecutionProvider from all six new BitShift shift-by-bit-width tests in commit 878dded.

@tianleiwu tianleiwu marked this pull request as ready for review May 2, 2026 06:32
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.

ONNX Runtime CPU BitShift incorrectly handles uint64 shift amount == 64

2 participants