fixedpoint: avoid signed-overflow UB in scalar Neg - #219
Open
EylonKrause wants to merge 1 commit into
Open
Conversation
The scalar `Neg` primitive computed `-a`, which is undefined behavior when `a` is the most negative representable value (e.g. -2147483648 for int32). This is reachable from the public `tanh()` and `logistic()` functions: both compute `SelectUsingMask(mask, a, -a)`, and C++ evaluates the `-a` argument unconditionally, so `Neg(INT_MIN)` runs for the minimum-valued FixedPoint input even though its result is then masked out. Building the existing test/test_fixedpoint.cc under UBSan reports: fixedpoint.h:113:11: runtime error: negation of -2147483648 cannot be represented in type 'int' Negate through the unsigned counterpart type instead, where the operation is well-defined and wraps back to the same value. This matches every SIMD implementation of Neg (vnegq_s32, _mm_sign_epi32, _mm256_sign_epi32, MSA subv, wasm_i32x4_neg), which negate in hardware without UB, and follows the UB-avoidance policy already documented on ShiftLeft. No functional change: the wrapped result is bit-identical to the previous in-practice behavior, and test_fixedpoint now passes cleanly under -fsanitize=address,undefined.
|
这是来自QQ邮箱的假期自动回复邮件。你好,我最近正在休假中,无法亲自回复你的邮件。我将在假期结束后,尽快给你回复。
|
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.
Problem
The scalar
Negprimitive infixedpoint/fixedpoint.hcomputes-a, which issigned-integer overflow (undefined behavior) when
ais the most negativerepresentable value (
-2147483648forint32,-32768forint16).It is reachable from the public
tanh()andlogistic()functions. Bothcompute
SelectUsingMask(mask_if_..., a, -a); because C++ evaluates functionarguments unconditionally,
-a(henceNeg(INT_MIN)) is always executed — evenfor the minimum-valued
FixedPointinput, whose negated value is then maskedaway.
Building the existing
test/test_fixedpoint.ccwith UBSan reproduces it:Fix
Negate through the unsigned counterpart type, where the operation is well
defined, then convert back:
This:
back to the same most-negative value, exactly as the previous code did in
practice);
Neg(vnegq_s32,_mm_sign_epi32,_mm256_sign_epi32, MSAsubv,wasm_i32x4_neg), which already negatewithout UB;
ShiftLeftin the samefile ("no Undefined Behavior, but the results are implementation-defined").
The unsigned→signed conversion back is implementation-defined (not UB) in
C++11/14/17 and well-defined in C++20; the same in-practice-consistent behavior
is already relied on by
ShiftLeftandShiftRightin this file.Testing
test/test_fixedpoint.ccnow passes cleanly under-fsanitize=address,undefined(previously it aborted on the UBSan error above):PASS (Scalar int32)/PASS (Scalar int16). Outputs for the minimum inputare unchanged and match their float references, e.g.
tanh(-1.0) ≈ -0.7616,logistic(-1.0) ≈ 0.2689.Disclosure: this contribution was authored with an AI coding assistant (Claude) and reviewed before submission.