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

Formatting code is in conflict with unnamed_addr #58320

Open
RalfJung opened this Issue Feb 9, 2019 · 6 comments

Comments

Projects
None yet
4 participants
@RalfJung
Copy link
Member

RalfJung commented Feb 9, 2019

The code for passing arguments into format strings relies on equality of function pointers. This is in conflict with the fact that we set unnamed_addr on all functions.

Global variables can be marked with unnamed_addr which indicates that the address is not significant, only the content. Constants marked like this can be merged with other constants if they have the same initializer.

rust/src/libcore/fmt/mod.rs

Lines 295 to 301 in 618f5a0

fn as_usize(&self) -> Option<usize> {
if self.formatter as usize == ArgumentV1::show_usize as usize {
Some(unsafe { *(self.value as *const _ as *const usize) })
} else {
None
}
}

It might be possible for a user to write a function that gets merged with ArgumentV1::show_usize, and then cause bugs in the above code.

@oli-obk @eddyb

@oli-obk

This comment has been minimized.

Copy link
Contributor

oli-obk commented Feb 10, 2019

These uses are impossible to abuse for users (this is an Argument internal API that is only used if it's a usize anyway). The invariants that make this possible are very subtle though, and we should totally document this better

pietroalbini added a commit to pietroalbini/rust that referenced this issue Feb 10, 2019

Rollup merge of rust-lang#58324 - RalfJung:fn-ptr-eq, r=oli-obk
miri: give non-generic functions a stable address

This makes Miri correctly handle format string parameters despite rust-lang#58320.

Matching Miri PR: rust-lang/miri#626

r? @oli-obk

Mark-Simulacrum added a commit to Mark-Simulacrum/rust that referenced this issue Feb 10, 2019

Rollup merge of rust-lang#58324 - RalfJung:fn-ptr-eq, r=oli-obk
miri: give non-generic functions a stable address

This makes Miri correctly handle format string parameters despite rust-lang#58320.

Matching Miri PR: rust-lang/miri#626

r? @oli-obk

GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Feb 10, 2019

Rollup merge of rust-lang#58324 - RalfJung:fn-ptr-eq, r=oli-obk
miri: give non-generic functions a stable address

This makes Miri correctly handle format string parameters despite rust-lang#58320.

Matching Miri PR: rust-lang/miri#626

r? @oli-obk
@RalfJung

This comment has been minimized.

Copy link
Member Author

RalfJung commented Feb 11, 2019

The invariants that make this possible are very subtle though, and we should totally document this better

I wonder which invariant you had in mind here?

@oli-obk

This comment has been minimized.

Copy link
Contributor

oli-obk commented Feb 11, 2019

We are only using the as_usize method in getcount, which is only used for the width and the precision fields. These must be usize anyway, so the as_usize function essentially double checks whether we are doing this for usize.

@RalfJung

This comment has been minimized.

Copy link
Member Author

RalfJung commented Feb 12, 2019

So you are saying format_args! actually ensures that width/precision fields are always created with from_usize?

@oli-obk

This comment has been minimized.

Copy link
Contributor

oli-obk commented Feb 12, 2019

That's my reading of the code, but I might have missed some stuff. The formatting code is very... frameworky

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Feb 13, 2019

Yeah, from_usize is used by format_args! in all cases as_usize will be called, the behavior of the latter for non-usize formatting arguments is impossible to observe without going through the unstable API.

But maybe we should benchmark (cc @anp) the cost of using an enum that relies on the null pointer optimization, i.e. Option where Some(fn_ptr) indicates formatting-only, while None indicates usize, which can be formatted (or not?), but also extracted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.