Skip to content

Commit a7644b3

Browse files
committed
Auto merge of #29297 - tbu-:pr_env_ignore_malformed, r=alexcrichton
Otherwise, the iterator and the functions for getting specific environment variables might disagree, for environments like FOOBAR
2 parents 9f49ea0 + 87243bc commit a7644b3

File tree

3 files changed

+63
-12
lines changed

3 files changed

+63
-12
lines changed

src/libstd/sys/unix/os.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -386,24 +386,33 @@ pub fn env() -> Env {
386386
let _g = ENV_LOCK.lock();
387387
return unsafe {
388388
let mut environ = *environ();
389-
if environ as usize == 0 {
389+
if environ == ptr::null() {
390390
panic!("os::env() failure getting env string from OS: {}",
391391
io::Error::last_os_error());
392392
}
393393
let mut result = Vec::new();
394394
while *environ != ptr::null() {
395-
result.push(parse(CStr::from_ptr(*environ).to_bytes()));
395+
if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
396+
result.push(key_value);
397+
}
396398
environ = environ.offset(1);
397399
}
398400
Env { iter: result.into_iter(), _dont_send_or_sync_me: ptr::null_mut() }
399401
};
400402

401-
fn parse(input: &[u8]) -> (OsString, OsString) {
402-
let mut it = input.splitn(2, |b| *b == b'=');
403-
let key = it.next().unwrap().to_vec();
404-
let default: &[u8] = &[];
405-
let val = it.next().unwrap_or(default).to_vec();
406-
(OsStringExt::from_vec(key), OsStringExt::from_vec(val))
403+
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
404+
// Strategy (copied from glibc): Variable name and value are separated
405+
// by an ASCII equals sign '='. Since a variable name must not be
406+
// empty, allow variable names starting with an equals sign. Skip all
407+
// malformed lines.
408+
if input.is_empty() {
409+
return None;
410+
}
411+
let pos = input[1..].iter().position(|&b| b == b'=').map(|p| p + 1);
412+
pos.map(|p| (
413+
OsStringExt::from_vec(input[..p].to_vec()),
414+
OsStringExt::from_vec(input[p+1..].to_vec()),
415+
))
407416
}
408417
}
409418

src/test/run-pass/env-funky-keys.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Ignore this test on Android, because it segfaults there.
12+
13+
// ignore-android
14+
// ignore-windows
15+
// no-prefer-dynamic
16+
17+
#![feature(convert)]
18+
#![feature(libc)]
19+
20+
extern crate libc;
21+
22+
use libc::c_char;
23+
use libc::execve;
24+
use std::env;
25+
use std::ffi::OsStr;
26+
use std::ptr;
27+
28+
fn main() {
29+
if env::args_os().next().is_none() {
30+
for (key, value) in env::vars_os() {
31+
panic!("found env value {:?} {:?}", key, value);
32+
}
33+
return;
34+
}
35+
36+
let current_exe = env::current_exe().unwrap().into_os_string().to_cstring().unwrap();
37+
let new_env_var = OsStr::new("FOOBAR").to_cstring().unwrap();
38+
let filename: *const c_char = current_exe.as_ptr();
39+
let argv: &[*const c_char] = &[ptr::null()];
40+
let envp: &[*const c_char] = &[new_env_var.as_ptr(), ptr::null()];
41+
unsafe {
42+
execve(filename, &argv[0], &envp[0]);
43+
}
44+
panic!("execve failed");
45+
}

src/test/run-pass/env-vars.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ use std::env::*;
1414
fn main() {
1515
for (k, v) in vars_os() {
1616
let v2 = var_os(&k);
17-
// MingW seems to set some funky environment variables like
18-
// "=C:=C:\MinGW\msys\1.0\bin" and "!::=::\" that are returned
19-
// from vars() but not visible from var().
20-
assert!(v2.is_none() || v2.as_ref().map(|s| &**s) == Some(&*v),
17+
assert!(v2.as_ref().map(|s| &**s) == Some(&*v),
2118
"bad vars->var transition: {:?} {:?} {:?}", k, v, v2);
2219
}
2320
}

0 commit comments

Comments
 (0)