range-check int and uint widths in unifyInt#484
Conversation
|
Tests seem to fail on 32bit CI? 32bit systems are not all that common any more, but added that some years ago as people reported problems on 32bit systems, so it seems some people are still using it. |
|
Good catch. The decode.go change itself is fine, it was the new test that was wrong. I'd reused MaxInt32+1 for both the int and the uint case, but that value (2147483648) still fits inside a 32-bit uint, whose ceiling is MaxUint32 (4294967295). So OverflowUint correctly returns false and the uint assertion tripped, which is exactly the line that failed in the 386 log. The signed int case was right because MaxInt32+1 does cross the int32 boundary. Pushed a fix that uses MaxUint32+1 for the uint case, so it actually overflows a 32-bit uint while staying within int64. I can't run 386 locally (no qemu on this machine), but the test binary cross-compiles clean under GOARCH=386 GOOS=linux and the threshold is now correct per kind, so the 32bit job should go green. |
|
I copy/pasted your test to the current |
|
Right, that's the gate doing its job rather than the test being wrong. The only path this PR changes behaviour on is the platform-sized reflect.Int/reflect.Uint kinds, and those are only narrower than int64 on a 32-bit build. On a 64-bit host int/uint are 64 bits wide, so MaxInt32+1 and MaxUint32+1 both fit, master and the branch decode them identically with no error, and the two assertions sit behind the strconv.IntSize == 32 gate so they're a no-op for you. The root cause is that master's hand-rolled checks only named Int8/16/32 and Uint8/16/32 explicitly; reflect.Int and reflect.Uint fell straight through to SetInt/SetUint, which don't range-check at all. To see it actually go red on master, run it under the 386 job, the same one that flagged my earlier MaxInt32-for-uint slip: |
b9a91f9 to
1265ec4
Compare
|
Cheers, thanks |
unifyInt only range-checks the fixed-width int and uint kinds; reflect.Int and reflect.Uint fall through unchecked, so on a 32-bit build a value above 2^31-1 decoded into an int or uint field is silently truncated instead of rejected. Spotted it reading the range checks next to the uint fix. Swapped the hand-rolled per-width comparisons for rv.OverflowInt and rv.OverflowUint, which are width-aware and also cover the platform-sized kinds. The num < 0 guard stays so negatives into unsigned still error.