Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible bitshifting footgun #21311

Closed
lawrence-laz opened this issue Sep 5, 2024 · 4 comments · Fixed by #21320
Closed

Possible bitshifting footgun #21311

lawrence-laz opened this issue Sep 5, 2024 · 4 comments · Fixed by #21320
Labels
bug Observed behavior contradicts documented or intended behavior standard library This issue involves writing Zig code for the standard library.
Milestone

Comments

@lawrence-laz
Copy link

Depending on whether a is modified or not (const or var) the bitshift operator produces different results.

test "fails" {
    const a: i16 = -32767;
    try std.testing.expectEqual(-2048, a >> 4); // ● expected -2048, found -2047
}

test "passes" {
    var a: i16 = -32766;
    a -= 1;
    try std.testing.expectEqual(-2048, a >> 4);
}

Not sure if this could be regarded as a bug, but it does feel a bit dangerous

@rohlem
Copy link
Contributor

rohlem commented Sep 5, 2024

Not sure if this could be regarded as a bug

Afaik the arithmetic operators are defined in terms of values, regardless where they may come from,
so the same values in the same operation leading to different results is definitely a bug.

ianprime0509 added a commit to ianprime0509/zig that referenced this issue Sep 6, 2024
Closes ziglang#21311

The sign of the result `r` needs to be initialized before the correction
`r.addScalar(r.toConst(), -1)`, or the intended end result could be off
by 2 (depending on the original sign of `r`).
ianprime0509 added a commit to ianprime0509/zig that referenced this issue Sep 6, 2024
Closes ziglang#21311

The sign of the result `r` needs to be initialized before the correction
`r.addScalar(r.toConst(), -1)`, or the intended end result could be off
by 2 (depending on the original sign of `r`).
@ianprime0509
Copy link
Contributor

Just to confirm, is the result of the shift in the first test -2047 or -2046 for you? When I run the test, I get "expected -2048, found -2046", which aligns with the analysis of the fix in #21320 (off by 2).

Currently, a release compiler reproduces this issue for me, while a debug compiler does not. With #21320 applied, the test also passes under a release compiler. (The difference between debug and release has to do with the undefined here:

zig/src/Value.zig

Line 2779 in 3929cac

.positive = undefined,
)

@weskoerber
Copy link
Contributor

It looks like the behavior here is slightly different between 0.14 and 0.13: 0.14 gives -2046, but 0.13 gives -2047.

❯ zvm use 0.13.0

❯ zig version
0.13.0

❯ zig test shift.zig
expected -2048, found -2047
1/2 shift.test.fails...FAIL (TestExpectedEqual)
/home/wes/.local/share/zvm/0.13.0/lib/std/testing.zig:93:17: 0x103cfe2 in expectEqualInner__anon_1014 (test)
                return error.TestExpectedEqual;
                ^
/home/wes/shift.zig:3:5: 0x103d121 in test.fails (test)
    try std.testing.expectEqual(-2048, a >> 4);
    ^
1 passed; 0 skipped; 1 failed.
error: the following test command failed with exit code 1:
/home/wes/.cache/zig/o/04383ca2a7673a2ec41206dc968a03a1/test

❯ zvm use 0.14.0-dev.1472+3929cac15

❯ zig version
0.14.0-dev.1472+3929cac15

❯ zig test shift.zig
expected -2048, found -2046
1/2 shift.test.fails...FAIL (TestExpectedEqual)
/home/wes/.local/share/zvm/0.14.0-dev.1472+3929cac15/lib/std/testing.zig:97:17: 0x1040772 in expectEqualInner__anon_150 (test)
                return error.TestExpectedEqual;
                ^
/home/wes/shift.zig:3:5: 0x10408b1 in test.fails (test)
    try std.testing.expectEqual(-2048, a >> 4);
    ^
1 passed; 0 skipped; 1 failed.
error: the following test command failed with exit code 1:
/home/wes/.cache/zig/o/cb855978d9e6144d0f1b922565e8e9e9/test --seed=0x49c54965

@ianprime0509
Copy link
Contributor

Ah, that makes sense, I only tested on master. The difference between 0.13 and master is most likely explained by the changes done in #20585 (which fixed an off-by-one error present before that change).

@Vexu Vexu added bug Observed behavior contradicts documented or intended behavior standard library This issue involves writing Zig code for the standard library. labels Sep 6, 2024
@Vexu Vexu added this to the 0.14.0 milestone Sep 6, 2024
DivergentClouds pushed a commit to DivergentClouds/zig that referenced this issue Sep 24, 2024
Closes ziglang#21311

The sign of the result `r` needs to be initialized before the correction
`r.addScalar(r.toConst(), -1)`, or the intended end result could be off
by 2 (depending on the original sign of `r`).
richerfu pushed a commit to richerfu/zig that referenced this issue Oct 28, 2024
Closes ziglang#21311

The sign of the result `r` needs to be initialized before the correction
`r.addScalar(r.toConst(), -1)`, or the intended end result could be off
by 2 (depending on the original sign of `r`).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior standard library This issue involves writing Zig code for the standard library.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants