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

Guard against overflow in codemap::span_to_lines. #25013

Merged
merged 2 commits into from
May 7, 2015

Conversation

pnkfelix
Copy link
Member

Guard against overflow in codemap::span_to_lines.

(Revised/expanded version of PR #24976)

Make span_to_lines to return a Result.

In diagnostic, catch Err from span_to_lines and print "(unprintable span)" instead.


There a number of recent issues that report the bug here. See e.g. #24761 and #24954.

This change might fix them. However, that is not its main goal. The main goals are:

  1. Make it possible for callers to recover from an error here, and
  2. Insert a more conservative check, in that we are also checking that the files match up.

As a drive-by, fix #24997 , which was causing my attempts to make check-stage1 on an --enable-debug build to fail.

@rust-highfive
Copy link
Collaborator

r? @sfackler

(rust_highfive has picked a reviewer for you, use r? to override)

@lilyball
Copy link
Contributor

Speaking of overflowing in slice, I think we still have other overflow possibilities. It appears as though slice was written to work properly in the case of zero-sized slices where s.as_ptr() + s.len() wrapped around (specifically, it doesn't seem to rely in the iterators that end > ptr, and it explicitly handles the case of wrapping around during iteration by always yielding &mut *(1 as *mut _) as the iterator value for zero-sized elements (because yielding null would be interpreted as None instead of as Some(_)). But all this code was written with wrapping arithmetic in mind. So there's code that does things like ptr as usize + len(), which might trigger an overflow check.

I'll file a ticket about it. (Update: Filed as #25016)

@pnkfelix
Copy link
Member Author

pnkfelix commented May 1, 2015

r? @huonw

@rust-highfive rust-highfive assigned huonw and unassigned sfackler May 1, 2015
@@ -643,6 +643,17 @@ macro_rules! slice_offset {
}};
}

macro_rules! slice_sub_offset {
Copy link
Member

Choose a reason for hiding this comment

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

Could you add a comment about why one can't just use slice_offset!/slice_add_offset! with -1?

Copy link
Member Author

Choose a reason for hiding this comment

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

will do.

@huonw
Copy link
Member

huonw commented May 1, 2015

This change will 'disguise' these bugs, won't it? (i.e. instead of an error/ICE, one will get (unprintable span))

Maybe it could be phrased as (internal error: invalid span) or something that suggests it's a bug more strongly?

@pnkfelix
Copy link
Member Author

pnkfelix commented May 3, 2015

@kballard wrote:

This could be done simpler just by using wrapping arithmetic.

By the way, I did see this feedback, and as a result, I considered doing this. But I think the formulation I came up with is more self-documenting, and should be just as efficient when compiled without -C debug-assertions.

(By "self-documenting," I guess I mean that this is not a case where modular arithmetic inherently applies -- instead, using wrapping_add would take advantage of one special property of the twos-complement representation, but other potential overflow bugs would then be masked...)

I just wanted to make sure I addressed this note. :)

@pnkfelix
Copy link
Member Author

pnkfelix commented May 3, 2015

@huonw wrote:

Maybe it could be phrased as (internal error: invalid span) or something that suggests it's a bug more strongly?

Yeah, I also had thought a stronger message would be warranted. (Should I go so far as to find some way to encode "please report this as a bug" into the output as well?)

@lilyball
Copy link
Contributor

lilyball commented May 3, 2015

What other potential overflow bugs would be masked? My understanding is this code is explicitly supposed to be tolerant of wrapping because it still maintains the desired invariants (namely, that the end can be reached from the start by incrementing the correct number of times). So it's not an accident that two's-complement works, it's explicit design.

@pnkfelix
Copy link
Member Author

pnkfelix commented May 3, 2015

@kballard

What other potential overflow bugs would be masked?

eh, the only examples I can think of offhand involve overflowing usize::MAX, but its really a weak strawman.

This overflow does not cause any problems; it just causes errors to be
signalled when compiling with `-C debug-assertions`.

Fix rust-lang#24997
@pnkfelix pnkfelix force-pushed the span_to_lines-oflo branch from 7ee72cb to 8b20251 Compare May 4, 2015 08:06
@pnkfelix
Copy link
Member Author

pnkfelix commented May 4, 2015

@huonw any further review feedback?

($ptr:expr, $by:expr) => {{
let ptr = $ptr;
if size_from_ptr(ptr) == 0 {
transmute(ptr as usize - $by)
Copy link
Contributor

Choose a reason for hiding this comment

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

GitHub seems to have lost my previous comment about this. It may have been a commit comment instead of a diff comment but I thought GitHub still preserved those. In the interests of making the discussion actually make sense, what I had suggested was that we don't need a separate macro at all, we just need wrapping arithmetic, like

macro_rules! slice_offset {
    ($ptr:expr, $by:expr) => {{
        let ptr = $ptr;
        if size_from_ptr(ptr) == 0 {
            transmute((ptr as isize).wrapping_add($by))
        } else {
            ptr.offset($by)
        }
    }};
}

And FWIW I still believe this is the better approach. It more closely mimics the actual pointer arithmetic used for non-zero-sized types, it means none of the callers of the macro have to be updated, and it more closely matches the required changes for #25016 (I think we need to use wrapping addition in more places in this module in order to restore the pre-overflow-check behavior).

Copy link
Member Author

Choose a reason for hiding this comment

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

I have kept the changes in the form presented here because I still believe this code is easier to read than that change that you suggest. (It is an entirely subjective opinion.)

I freely admit that I have not done the full review of the core::slice code, and thus I have no argument against the point you make about hypothetical fixes to #25016. If it comes to that, then we can revert back to a macro of the form you suggest when #25016 gets fixed.

For now, however, my main concern is getting make check working again on --enable-debug builds, and this was the most obviously correct way for me to go about doing it.

Make `span_to_lines` to return a `Result`.
(This is better than just asserting internally, since it allows caller
to decide if they can recover from the problem.)

Added type alias for `FileLinesResult` returned by `span_to_lines`.

Update embedded unit test to reflect `span_to_lines` signature change.

In diagnostic, catch `Err` from `span_to_lines` and print
`"(internal compiler error: unprintable span)"` instead.

----

There a number of recent issues that report the bug here.  See
e.g. rust-lang#24761 and rust-lang#24954.

This change *might* fix them. However, that is not its main goal.
The main goals are:

 1. Make it possible for callers to recover from an error here, and

 2. Insert a more conservative check, in that we are
    also checking that the files match up.
@pnkfelix pnkfelix force-pushed the span_to_lines-oflo branch from 8b20251 to 909e1d6 Compare May 5, 2015 10:51
@pnkfelix
Copy link
Member Author

pnkfelix commented May 7, 2015

@huonw review ping; I have now addressed your comments. Was there anything else you wanted here?

@huonw
Copy link
Member

huonw commented May 7, 2015

@bors r+

@bors
Copy link
Contributor

bors commented May 7, 2015

📌 Commit 909e1d6 has been approved by huonw

@bors
Copy link
Contributor

bors commented May 7, 2015

⌛ Testing commit 909e1d6 with merge 5858b66...

@bors
Copy link
Contributor

bors commented May 7, 2015

⛄ The build was interrupted to prioritize another pull request.

@bors
Copy link
Contributor

bors commented May 7, 2015

⌛ Testing commit 909e1d6 with merge cbc8a1c...

bors added a commit that referenced this pull request May 7, 2015
Guard against overflow in `codemap::span_to_lines`.

(Revised/expanded version of PR #24976)

Make `span_to_lines` to return a `Result`.

In `diagnostic`, catch `Err` from `span_to_lines` and print `"(unprintable span)"` instead.

----

There a number of recent issues that report the bug here.  See e.g. #24761 and #24954.

This change *might* fix them. However, that is *not* its main goal. The main goals are:

 1. Make it possible for callers to recover from an error here, and

 2. Insert a more conservative check, in that we are also checking that the files match up.

----

As a drive-by, fix #24997 , which was causing my attempts to `make check-stage1` on an `--enable-debug` build to fail.
@bors
Copy link
Contributor

bors commented May 7, 2015

💔 Test failed - auto-mac-64-opt

@pnkfelix pnkfelix force-pushed the span_to_lines-oflo branch from 909e1d6 to 939e4c9 Compare May 7, 2015 14:37
@pnkfelix
Copy link
Member Author

pnkfelix commented May 7, 2015

sigh, my attempt to add an assertion to a test broke make check-pretty. I have now just removed that commit; the assertion (in commit 909e1d6 )wasn't that important.

@pnkfelix
Copy link
Member Author

pnkfelix commented May 7, 2015

@bors r=huonw 939e4c9

bors added a commit that referenced this pull request May 7, 2015
Guard against overflow in `codemap::span_to_lines`.

(Revised/expanded version of PR #24976)

Make `span_to_lines` to return a `Result`.

In `diagnostic`, catch `Err` from `span_to_lines` and print `"(unprintable span)"` instead.

----

There a number of recent issues that report the bug here.  See e.g. #24761 and #24954.

This change *might* fix them. However, that is *not* its main goal. The main goals are:

 1. Make it possible for callers to recover from an error here, and

 2. Insert a more conservative check, in that we are also checking that the files match up.

----

As a drive-by, fix #24997 , which was causing my attempts to `make check-stage1` on an `--enable-debug` build to fail.
@bors
Copy link
Contributor

bors commented May 7, 2015

⌛ Testing commit 939e4c9 with merge a39d4fc...

@bors bors merged commit 939e4c9 into rust-lang:master May 7, 2015
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.

vec::test_drain_range exposes overflow "bug" in slice code
6 participants