Skip to content

Type validation mistreats layout errors #71353

@Michael-F-Bryan

Description

@Michael-F-Bryan

The original problem got fixed by avoiding the broken code paths; this issue now tracks fixing those code paths.

Original issue

In the ffi_helpers crate we have a Nullable trait which gives you a generic way to do null pointer checks.

pub trait Nullable {
    const NULL: Self;

    fn is_null(&self) -> bool;
}

A user recently reported that the crate no longer compiles on nightly (Michael-F-Bryan/ffi_helpers#2) because type validation detects that std::ptr::null() and std::ptr::null_mut() create uninitialized raw pointers.

  Compiling playground v0.0.1 (/playground)
error[E0080]: it is undefined behavior to use this value
  --> src/lib.rs:17:5
   |
17 |     const NULL: Self = std::ptr::null_mut();
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized raw pointer
   |
   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.

error: aborting due to previous error

For more information about this error, try `rustc --explain E0080`.
error: could not compile `playground`.

I can reproduce this on the playground with the latest nightly, 1.44.0-nightly (2020-04-19 dbf8b6bf116c7bece298).

Is the use shown in that playground example (*self == Self::NULL on a *mut T) actually UB?

Also, I noticed that calling the is_null() method defined on a raw pointer with <*const T>::is_null(*self) doesn't trigger this error, implying that the problem isn't with declaring a constant that contains a null pointer (const NULL: Self = std::ptr::null_mut()), but the fact that we're using it for a comparison. Was this intended, or is it just an oversight in the error detection code?

Full example with output
pub trait Nullable {
    const NULL: Self;

    fn is_null(&self) -> bool;
}

impl<T> Nullable for *const T {
    const NULL: Self = std::ptr::null();

    #[inline]
    fn is_null(&self) -> bool {
        <*const T>::is_null(*self)
    }
}

impl<T> Nullable for *mut T {
    const NULL: Self = std::ptr::null_mut();

    #[inline]
    fn is_null(&self) -> bool {
        *self == Self::NULL
    }
}
Compiling playground v0.0.1 (/playground)
error[E0080]: it is undefined behavior to use this value
  --> src/lib.rs:17:5
   |
17 |     const NULL: Self = std::ptr::null_mut();
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized raw pointer
   |
   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.

error: aborting due to previous error

For more information about this error, try `rustc --explain E0080`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.

CC: @RalfJung because it looks like they were the last person to touch that error message (9ee4d1a).

This issue has been assigned to @jumbatm via this comment.

Activity

added
A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)
C-bugCategory: This is a bug.
I-prioritizeIssue: Indicates that prioritization has been requested for this issue.
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Apr 20, 2020
RalfJung

RalfJung commented on Apr 20, 2020

@RalfJung
Member

Cc @rust-lang/wg-const-eval

This is definitely not intended, that example you gave is entirely safe code and should compile just fine.

The odd thing is, I am indeed responsible for the error but that was back in #66147 which has long arrived on stable -- so the error itself cannot be the source of the regression. Would be good to get the regression narrowed down a bit more.

I also don't understand why == seems to be needed to trigger this. Might be some interaction with promotion?

The error message is probably (hopefully!) just wrong, I doubt the pointer is actually uninitialized. We just show that error when anything goes wrong in this line:

let place = try_validation!(
self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?),
"uninitialized raw pointer",
self.path
);

Likely ref_to_mplace really doesn't like that the pointer is NULL. The thing is, this code works fine, and that just makes no sense:

fn main() {
    const NULL: *mut i32 = std::ptr::null_mut();
    println!("{:?}", NULL);
}
added
E-needs-bisectionCall for participation: This issue needs bisection: https://github.com/rust-lang/cargo-bisect-rustc
on Apr 20, 2020
jonas-schievink

jonas-schievink commented on Apr 20, 2020

@jonas-schievink
Contributor

@rustbot ping bisect

rustbot

rustbot commented on Apr 20, 2020

@rustbot
Collaborator

Hey Cleanup Crew ICE-breakers! This bug has been identified as a good
"Cleanup ICE-breaking candidate". In case it's useful, here are some
instructions for tackling these sorts of bugs. Maybe take a look?
Thanks! <3

cc @AminArria @chrissimpkins @contrun @DutchGhost @elshize @ethanboxx @h-michael @HallerPatrick @hdhoang @hellow554 @imtsuki @jakevossen5 @kanru @KarlK90 @LeSeulArtichaut @MAdrianMattocks @matheus-consoli @mental32 @nmccarty @Noah-Kennedy @pard68 @PeytonT @pierreN @Redblueflame @RobbieClarken @RobertoSnap @robjtede @SarthakSingh31 @senden9 @shekohex @sinato @spastorino @turboladen @woshilapin @yerke

RalfJung

RalfJung commented on Apr 20, 2020

@RalfJung
Member

It's not an ICE, but if ICE-breakers also help with other bisects then yes this would be awesome. :)

Michael-F-Bryan

Michael-F-Bryan commented on Apr 20, 2020

@Michael-F-Bryan
Author

If it helps pinpoint when the error was introduced, my rustc is usually within a couple days of the latest nightly and I made a release of that crate on 2020-04-07 without hitting any compilation errors.

senden9

senden9 commented on Apr 20, 2020

@senden9

Regression in nightly-2020-04-17. Looking currently for regression commit between 2020-04-17 and 2020-04-16.

searched nightlies: from nightly-2020-04-07 to nightly-2020-04-19
regressed nightly: nightly-2020-04-17
searched commits: from d223029 to 7f3df57
regressed commit: 7f3df57

Full Log:

root@ubuntu-c-32-64gib-fra1-01:~# cargo bisect-rustc --preserve --test-dir=foo --start=2020-04-07 --end=2020-04-19installing nightly-2020-04-07
testing...
RESULT: nightly-2020-04-07, ===> No

installing nightly-2020-04-19
testing...
RESULT: nightly-2020-04-19, ===> Yes

installing nightly-2020-04-13
testing...
RESULT: nightly-2020-04-13, ===> No

installing nightly-2020-04-16
testing...
RESULT: nightly-2020-04-16, ===> No

installing nightly-2020-04-17
testing...
RESULT: nightly-2020-04-17, ===> Yes

searched toolchains nightly-2020-04-07 through nightly-2020-04-19
regression in nightly-2020-04-17
fetching https://static.rust-lang.org/dist/2020-04-17/channel-rust-nightly-git-commit-hash.txt
converted 2020-04-17 to 7f3df5772439eee1c512ed2eb540beef1124d236
fetching https://static.rust-lang.org/dist/2020-04-16/channel-rust-nightly-git-commit-hash.txt
converted 2020-04-16 to d2230290f7220e740ec08f4d844bf5951e1b74b8
looking for regression commit between 2020-04-17 and 2020-04-16
opening existing repository at "rust.git"
refreshing repository
fetching (via local git) commits from d2230290f7220e740ec08f4d844bf5951e1b74b8 to 7f3df5772439eee1c512ed2eb540beef1124d236
opening existing repository at "rust.git"
refreshing repository
looking up first commit
looking up second commit
checking that commits are by bors and thus have ci artifacts...
finding bors merge commits
found 7 bors merge commits in the specified range
  commit[0] 2020-04-15UTC: Auto merge of #71139 - matthiaskrgr:submodule_upd, r=Dylan-DPC
  commit[1] 2020-04-15UTC: Auto merge of #71180 - Dylan-DPC:rollup-pscpg6q, r=Dylan-DPC
  commit[2] 2020-04-16UTC: Auto merge of #71159 - topecongiro:rustfmt-1.4.14, r=Dylan-DPC
  commit[3] 2020-04-16UTC: Auto merge of #71173 - RalfJung:miri, r=RalfJung
  commit[4] 2020-04-16UTC: Auto merge of #70831 - sfackler:shrink-future-stack, r=matthewjasper
  commit[5] 2020-04-16UTC: Auto merge of #70755 - wesleywiser:simplify_locals_2_electric_boogaloo, r=oli-obk
  commit[6] 2020-04-16UTC: Auto merge of #71201 - Dylan-DPC:rollup-23202uf, r=Dylan-DPC
validated commits found, specifying toolchains
installing d2230290f7220e740ec08f4d844bf5951e1b74b8
testing...
RESULT: d2230290f7220e740ec08f4d844bf5951e1b74b8, ===> No

installing 7f3df5772439eee1c512ed2eb540beef1124d236
testing...
RESULT: 7f3df5772439eee1c512ed2eb540beef1124d236, ===> Yes

installing 534a41a32952d36ec73656357777ebbea707aeb4
testing...
RESULT: 534a41a32952d36ec73656357777ebbea707aeb4, ===> No

installing 4e4d49d60fd696c4036d438292673a2d7fd34519
testing...
RESULT: 4e4d49d60fd696c4036d438292673a2d7fd34519, ===> No

installing 7fb5187d0423f4cd0441526571b8cd61927123c9
testing...
RESULT: 7fb5187d0423f4cd0441526571b8cd61927123c9, ===> No

searched toolchains d2230290f7220e740ec08f4d844bf5951e1b74b8 through 7f3df5772439eee1c512ed2eb540beef1124d236
installing 7f3df5772439eee1c512ed2eb540beef1124d236
testing...
regression in 7f3df5772439eee1c512ed2eb540beef1124d236


searched nightlies: from nightly-2020-04-07 to nightly-2020-04-19
regressed nightly: nightly-2020-04-17
searched commits: from https://github.com/rust-lang/rust/commit/d2230290f7220e740ec08f4d844bf5951e1b74b8 to https://github.com/rust-lang/rust/commit/7f3df5772439eee1c512ed2eb540beef1124d236
regressed commit: https://github.com/rust-lang/rust/commit/7f3df5772439eee1c512ed2eb540beef1124d236
source code: URL OF A REPOSITORY THAT REPRODUCES THE ERROR

35 remaining items

added and removed
I-prioritizeIssue: Indicates that prioritization has been requested for this issue.
on Apr 27, 2020
added a commit that references this issue on May 3, 2020

Rollup merge of rust-lang#71663 - jumbatm:caller-handles-validation-e…

5b17290
LeSeulArtichaut

LeSeulArtichaut commented on May 3, 2020

@LeSeulArtichaut
Contributor

@Mark-Simulacrum As this problem raised in the Crater run, should #71663 be nominated to be backported to beta?

Mark-Simulacrum

Mark-Simulacrum commented on May 3, 2020

@Mark-Simulacrum
Member

My understanding is that #71441 was the intended fix for beta and we expect #71663 to go with the trains, i.e. there is no need for a backport. But if I'm wrong, we should indeed nominate it.

LeSeulArtichaut

LeSeulArtichaut commented on May 3, 2020

@LeSeulArtichaut
Contributor

Oh right, I re-read #71353 (comment)

RalfJung

RalfJung commented on May 3, 2020

@RalfJung
Member

Indeed, the beta fix was to revert the original incorrect PR. This PR that just landed now just fixed #69021, which doesn't need backporting.

However, I am going to re-open this issue because validation still swallows layout errors in many cases -- just this one particular case got fixed.

added a commit that references this issue on May 6, 2020

Rollup merge of rust-lang#71950 - RalfJung:try-validation-cleanup, r=…

066eb08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)C-cleanupCategory: PRs that clean code up or issues documenting cleanup.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Participants

    @spastorino@pnkfelix@RalfJung@wesleywiser@senden9

    Issue actions

      Type validation mistreats layout errors · Issue #71353 · rust-lang/rust