THRIFT-6106: Decode fixed-width values without undefined shifts#3647
Merged
Conversation
Client: rb Co-Authored-By: OpenAI Codex (GPT-5.4) <codex@openai.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes undefined behavior in the native Ruby protocol C accelerators when decoding fixed-width integers and doubles, by assembling values using correctly sized unsigned intermediates and converting to signed only after the full value is formed. It also adds regression specs to ensure edge byte patterns (including high-bit cases and negative zero) are preserved as expected.
Changes:
- Rework fixed-width integer decoding in
binary_protocol_accelerated.cto use unsigned assembly plus explicit unsigned→signed conversion helpers. - Rework compact protocol double decoding to assemble into a
uint64_tto avoid undefined shifts and preserve bit patterns. - Add Ruby specs covering signed edge byte patterns and double edge byte patterns.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| lib/rb/spec/compact_protocol_spec.rb | Adds regression spec to ensure compact double decoding preserves edge-case byte patterns. |
| lib/rb/spec/binary_protocol_spec_shared.rb | Adds regression spec for fixed-width signed integer edge byte patterns across i16/i32/i64. |
| lib/rb/ext/compact_protocol.c | Avoids undefined shifts and signed conversions by assembling doubles via uint64_t byte-wise. |
| lib/rb/ext/binary_protocol_accelerated.c | Avoids undefined shifts by assembling integers/doubles via unsigned intermediates and explicit conversions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Native Ruby protocol readers previously assembled fixed-width values through shifts on promoted signed integers. On common builds, those reads can appear to return the expected values, but UBSan exposes the undefined operation for high-bit byte patterns.
Before this change, building and running the focused examples from
lib/rbwith:reports:
This change builds the binary and compact protocol values with correctly sized unsigned intermediates, then converts to signed values only after assembly. It also preserves double bit patterns when the high bit is set.
[skip ci]anywhere in the commit message to free up build resources.