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

arr! unsoundness #98

Closed
jswrenn opened this issue Apr 9, 2020 · 6 comments
Closed

arr! unsoundness #98

jswrenn opened this issue Apr 9, 2020 · 6 comments

Comments

@jswrenn
Copy link

jswrenn commented Apr 9, 2020

The arr! macro silently and unsoundly extends arbitrary lifetimes to 'static (playground):

fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
  arr![&A; a][0]
}
@novacrazy
Copy link
Collaborator

Hmm. This is more problematic than I expected.

What's happening is that &A being sent into a macro is not turned into a concrete type until the macro has generated the code. For the above, it generates this code:

unsafe { transmute::<[&A; 1], GenericArray<&A, 1>>([a]) }

and then the lifetimes are filled in on either side of the transmute using 'a and 'static via lifetime elusion, but transmuting does allow it to be changed incorrectly.

What I need to figure out is how to ensure &'_ A == &'_ A without disrupting lifetime elusion entirely.

For example,

type T = $T;
unsafe { transmute::<[T; 1], GenericArray<T, 1>>([a]) }

ensures that the input and output element types are the exact same, including lifetimes. However, it disables lifetime elusion entirely, so no structs with lifetimes can be passed unless the type includes the (often anonymous) lifetime. So that's a no-go.

Furthermore, because const-generics aren't a thing yet, or else this library wouldn't still be used, I cannot perform the transmute within a closed-form function that would otherwise ensure the input and output element types are the same.

@Shnatsel
Copy link

Shnatsel commented Mar 1, 2021

Heads up: this issue has been included in the RustSec advisory database. It will be surfaced by tools such as cargo-audit or cargo-deny from now on for affected versions of this crate.

This was referenced Mar 1, 2021
@greyblake
Copy link

@Shnatsel
FYI, @fizyk20 just released patched old versions:

  • 0.12.4
  • 0.13.3
  • 0.11.2
  • 0.10.1
  • 0.9.1

See:

@fizyk20
Copy link
Owner

fizyk20 commented Mar 2, 2021

Still working on 0.8.4 (0.8.3 is also vulnerable), but it looks like crates.io is having some DNS issues (can't resolve static.crates.io... or is it just me?).

EDIT: Nevermind, looks like it was just me. I switched to different DNS servers and managed to push 0.8.4, too.

@greyblake
Copy link

@fizyk20 Looks good to me!
image

Thank you!
I opened PR to RustSec: rustsec/advisory-db#789

@mbrubeck
Copy link

mbrubeck commented Mar 2, 2021

PSA: Now that the fix has been backported to all affected release branches, anyone affected by this can fix it by running:

cargo update -p generic-array

If your dependencies use multiple versions of generic-array, you may need to specify the exact version that you want to upgrade from. For example:

cargo update -p generic-array:0.12.3

bors bot added a commit to nervosnetwork/ckb that referenced this issue Mar 3, 2021
2601: chore(deps): bump generic-array from 0.12.3 to 0.12.4 to fix RUSTSEC-2020-0146 r=quake,zhangsoledad a=yangby-cryptape

### References

- [RUSTSEC-2020-0146: generic-array: arr! macro erases lifetimes](https://rustsec.org/advisories/RUSTSEC-2020-0146)
- [`generic-array` Issue-98: `arr!` unsoundness](fizyk20/generic-array#98)
- [ChangeLog for `generic-array` from 0.12.3 to 0.12.4](fizyk20/generic-array@1e96864...42843cd)

Co-authored-by: Boyu Yang <yangby@cryptape.com>
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

No branches or pull requests

6 participants