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

sema: add compile error for OOB by-length slice of array #18410

Merged
merged 2 commits into from
Jan 2, 2024

Conversation

dweiller
Copy link
Contributor

@dweiller dweiller commented Dec 30, 2023

Fixes #18382.

This change introduces a compile error when a by-length (i.e. buf[a..][0..len]) slice of an array with length comptime-known to be less than len is performed. Previously this case would compile and not even insert a runtime safety check in safe build modes.

An example of the new compile error is:

failing.zig:6:23: error: length 5 array cannot be sliced to length 10
    _ = slice[a..][0..10];
                      ^~

which is generated by this test:

test {
    var buf: [5]u8 = undefined;
    const slice = &buf;
    var a: u32 = 6;
    _ = &a;
    _ = slice[a..][0..10];
}

@Rexicon226
Copy link
Contributor

could you add a test case for the double runtime case?

i.e

test {
    var buf: [5]u8 = undefined;
    const slice = &buf;
    var a: u32 = 6;
    _ = &a;
    _ = buf[a..][0..a];
    _ = slice[a..][0..a];
}

@dweiller
Copy link
Contributor Author

I'm not sure about the workaround I've added in lib/std/json/static.zig to prevent the compile error being hit. I'm not familiar with the new json parser and not 100% sure that these situations are in fact unreachable - but it did get the tests passing for me locally. The other option would be to return error.LengthMismatch rather than hitting unreachable. Some input from @thejoshwolfe would be appreciated.

src/Sema.zig Show resolved Hide resolved
Copy link
Contributor

@thejoshwolfe thejoshwolfe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a small fix suggestion, otherwise looks good from me.

lib/std/json/static.zig Outdated Show resolved Hide resolved
@dweiller dweiller force-pushed the by-length-slice-bug branch from 83c0bee to 5af5d9f Compare December 31, 2023 04:25
@dweiller dweiller force-pushed the by-length-slice-bug branch from 5af5d9f to 41d5aa1 Compare December 31, 2023 04:37
@dweiller dweiller requested a review from Vexu December 31, 2023 04:37
@dweiller
Copy link
Contributor Author

dweiller commented Dec 31, 2023

could you add a test case for the double runtime case?

i.e

test {
    var buf: [5]u8 = undefined;
    const slice = &buf;
    var a: u32 = 6;
    _ = &a;
    _ = buf[a..][0..a];
    _ = slice[a..][0..a];
}

Done.

@Vexu Vexu merged commit d9d840a into ziglang:master Jan 2, 2024
10 checks passed
@dweiller dweiller deleted the by-length-slice-bug branch January 3, 2024 03:36
andrewrk added a commit that referenced this pull request Jan 14, 2024
This reverts commit d9d840a, reversing
changes made to a04d433.

This is not an adequate implementation of the missing safety check, as
evidenced by the changes to std.json that are reverted in this commit.

Reopens #18382
Closes #18510
@andrewrk
Copy link
Member

Reverted in bd46410.

@dweiller
Copy link
Contributor Author

Reverted in bd46410.

Would you rather a runtime safety check? I don't think it will be possible to have a compile error to prevent out-of-bounds length slicing without either the kind of workaround that was introduced in std.json, or much more sophisticated comptime analysis of integers/integer ranges.

@andrewrk
Copy link
Member

Yes, it should emit a compile error if illegal behavior is detected at compile-time. There must be no false positives (the problem of this implementation). If it cannot be detected at compile-time correctly then it should be detected at runtime.

@dweiller
Copy link
Contributor Author

dweiller commented Jan 15, 2024

Yes, it should emit a compile error if illegal behavior is detected at compile-time. There must be no false positives (the problem of this implementation). If it cannot be detected at compile-time correctly then it should be detected at runtime.

The analogous compile error for slicing an array normally (i.e. not 'by-length') has the same kind of false-positive, i.e. this test:

test {
    const array = [_]u8{ 0, 1, 2, 3, 4, 5 };
    var start: usize = 0;
    _ = &start;
    const end = array.len + 1;
    if (start + end < start + array.len) {
        _ = array[start..end];
    }
}

results in

t.zig:7:26: error: end index 7 out of bounds for array of length 6
        _ = array[start..end];
                         ^~~

despite never attempting an out-of-bounds access. Should this compile error also be moved to a runtime check?

bilaliscarioth pushed a commit to bilaliscarioth/zig that referenced this pull request Jan 27, 2024
…e-bug"

This reverts commit d9d840a, reversing
changes made to a04d433.

This is not an adequate implementation of the missing safety check, as
evidenced by the changes to std.json that are reverted in this commit.

Reopens ziglang#18382
Closes ziglang#18510
TUSF pushed a commit to TUSF/zig that referenced this pull request May 9, 2024
…e-bug"

This reverts commit d9d840a, reversing
changes made to a04d433.

This is not an adequate implementation of the missing safety check, as
evidenced by the changes to std.json that are reverted in this commit.

Reopens ziglang#18382
Closes ziglang#18510
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.

no bounds checking when slicing s[start..][0..len] arrays and array pointers in certain cases
5 participants