Change:
<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --<!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Simplified. The other malformed-looking bytes don't matter, do they?
You are right, they don't. I should have simplified it before submit.
Going to have a go at this. If I can't figure it out, I'll either ask for help or unassign myself. claim
Still working on this, but I figured an update may be helpful. My research indicates that the two characters that are potentially problematic are and . The work that needs to be done consists of 1) updating the macro expansion functions in to error in these cases; and 2) updating the macro documentation in to mention the new errors. Edit: It just occurred to me that I also need to add UI tests. Haven't figured out where to do that yet, but I will.
Assigning priority as discussed in the of the Prioritization Working Group. label -I-prioritize +P-medium
I don't think just adding a check to raise error in these cases would be enough. The function shouldn't really panic (from the internals discussion). Another problem is when the OS supports this kind of environment variable. e.g. as key. would deny it while it can be valid i.e. a false positive. You should still keep your work though (and eventually open a PR) as this must be changes to which would take a while.
If this is going to be fixed upstream in in even the mid-term future, I'm not sure fixing it here makes sense. Sure, it generates an ICE, but the ICE has an unusually helpful error message.
Actually, simple solution: I'll do the fix. Working on that now.
Was this fuzzer output? If so, which fuzzer were you using
Yes, I am using kira, a work-in-progress fuzzing tool
Have you considered sorry using structure-aware fuzzing? That could help find bugs not just in the lexer and parser, but also in the middle and back ends.
Yes, actually kira is structure-aware.

Discussion:
/// /// # Errors /// <del> /// Errors if the environment variable is not present. /// Errors if the environment variable is not valid Unicode. If this is not desired, consider using /// [`var_os`]. /// /// # Panics /// /// This function may panic if `key` is empty, contains an ASCII equals sign /// `'='` or the NUL character `'0'`, or when the value contains the NUL /// character. </del> <ins> /// Returns `[None]` if the environment variable isn't set. /// Returns `[None]` if the environment variable is not valid Unicode. If this is not /// desired, consider using [`var_os`]. </ins> /// /// # Examples ///

} /// Fetches the environment variable `key` from the current process, returning <del> /// [`None`] if the variable isn't set. /// /// # Panics /// /// This function may panic if `key` is empty, contains an ASCII equals sign /// `'='` or the NUL character `'0'`, or when the value contains the NUL /// character. </del> <ins> /// [`None`] if the variable isn't set or there's another error. </ins> /// /// Note that the method will not check if the environment variable /// is valid Unicode. If you want to have an error on invalid UTF-8, /// use the [`var`] function instead. /// <ins> /// # Errors /// /// Returns `[None]` if the variable isn't set. /// May return `[None]` if the variable value contains the NUL character. /// </ins> /// # Examples /// /// ```

fn _var_os(key: &OsStr) -> Option<OsString> { os_imp::getenv(key) <del> .unwrap_or_else(|e| panic!("failed to get environment variable `{:?}`: {}", key, e)) </del> } /// The error type for operations interacting with environment variables.

} } <del> pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> { unsafe { match ENV.as_ref().unwrap().lock().unwrap().get_mut(k) { Some(value) => Ok(Some(value.clone())), None => Ok(None), } } </del> <ins> pub fn getenv(k: &OsStr) -> Option<OsString> { unsafe { ENV.as_ref().unwrap().lock().unwrap().get_mut(k).cloned() } </ins> } pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {

get_env_store().map(|env| clone_to_vec(&env.lock().unwrap())).unwrap_or_default().into_iter() } <del> pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> { Ok(get_env_store().and_then(|s| s.lock().unwrap().get(k).cloned())) </del> <ins> pub fn getenv(k: &OsStr) -> Option<OsString> { get_env_store().and_then(|s| s.lock().unwrap().get(k).cloned()) </ins> } pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {

} } <del> pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> { </del> <ins> pub fn getenv(k: &OsStr) -> Option<OsString> { </ins> // environment variables with a nul byte can't be set, so their value is // always None as well <del> let k = CString::new(k.as_bytes())?; </del> <ins> let k = CString::new(k.as_bytes()).ok()?; </ins> unsafe { let _guard = env_read_lock(); let s = libc::getenv(k.as_ptr()) as *const libc::c_char; <del> let ret = if s.is_null() { </del> <ins> if s.is_null() { </ins> None } else { Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec())) <del> }; Ok(ret) </del> <ins> } </ins> } }

panic!("not supported on this platform") } <del> pub fn getenv(_: &OsStr) -> io::Result<Option<OsString>> { Ok(None) </del> <ins> pub fn getenv(_: &OsStr) -> Option<OsString> { None </ins> } pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {

} } <del> pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> { let k = CString::new(k.as_bytes())?; </del> <ins> pub fn getenv(k: &OsStr) -> Option<OsString> { let k = CString::new(k.as_bytes()).ok()?; </ins> unsafe { let _guard = env_lock(); let s = libc::getenv(k.as_ptr()) as *const libc::c_char; <del> let ret = if s.is_null() { </del> <ins> if s.is_null() { </ins> None } else { Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec())) <del> }; Ok(ret) </del> <ins> } </ins> } }

cvt(unsafe { c::SetCurrentDirectoryW(p.as_ptr()) }).map(drop) } <del> pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> { let k = to_u16s(k)?; let res = super::fill_utf16_buf( </del> <ins> pub fn getenv(k: &OsStr) -> Option<OsString> { let k = to_u16s(k).ok()?; super::fill_utf16_buf( </ins> |buf, sz| unsafe { c::GetEnvironmentVariableW(k.as_ptr(), buf, sz) }, |buf| OsStringExt::from_wide(buf), <del> ); match res { Ok(value) => Ok(Some(value)), Err(e) => { if e.raw_os_error() == Some(c::ERROR_ENVVAR_NOT_FOUND as i32) { Ok(None) } else { Err(e) } } } </del> <ins> ) .ok() </ins> } pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {

<ins> // check-pass // // Regression test for issue #86082 // // Checks that option_env! does not panic on receiving an invalid // environment variable name. fn main() { option_env!("0="); } </ins>