Skip to content

Commit 3a1a049

Browse files
committed
---
yaml --- r: 232763 b: refs/heads/try c: 7723550 h: refs/heads/master i: 232761: dd319dc 232759: 097901a v: v3
1 parent b1a9e4f commit 3a1a049

File tree

3 files changed

+36
-17
lines changed

3 files changed

+36
-17
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: edeb4f1c86cbf6af8ef9874d4b3af50f721ea1b8
33
refs/heads/snap-stage3: 1af31d4974e33027a68126fa5a5a3c2c6491824f
4-
refs/heads/try: 4ff44ff8faabb7e0545dfefa96b0d601f0f17b94
4+
refs/heads/try: 7723550fdd7fe29bee9dcbd45bdef4f209a7e1f1
55
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
66
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
77
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try/src/libstd/sys/unix/fs.rs

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -376,13 +376,19 @@ impl fmt::Debug for File {
376376

377377
#[cfg(target_os = "macos")]
378378
fn get_path(fd: c_int) -> Option<PathBuf> {
379+
// FIXME: The use of PATH_MAX is generally not encouraged, but it
380+
// is inevitable in this case because OS X defines `fcntl` with
381+
// `F_GETPATH` in terms of `MAXPATHLEN`, and there are no
382+
// alternatives. If a better method is invented, it should be used
383+
// instead.
379384
let mut buf = vec![0;libc::PATH_MAX as usize];
380385
let n = unsafe { libc::fcntl(fd, libc::F_GETPATH, buf.as_ptr()) };
381386
if n == -1 {
382387
return None;
383388
}
384389
let l = buf.iter().position(|&c| c == 0).unwrap();
385390
buf.truncate(l as usize);
391+
buf.shrink_to_fit();
386392
Some(PathBuf::from(OsString::from_vec(buf)))
387393
}
388394

@@ -466,18 +472,27 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
466472
pub fn readlink(p: &Path) -> io::Result<PathBuf> {
467473
let c_path = try!(cstr(p));
468474
let p = c_path.as_ptr();
469-
let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) };
470-
if len < 0 {
471-
len = 1024; // FIXME: read PATH_MAX from C ffi?
472-
}
473-
let mut buf: Vec<u8> = Vec::with_capacity(len as usize);
474-
unsafe {
475-
let n = try!(cvt({
476-
libc::readlink(p, buf.as_ptr() as *mut c_char, len as size_t)
477-
}));
478-
buf.set_len(n as usize);
475+
476+
let mut buf = Vec::with_capacity(256);
477+
478+
loop {
479+
let buf_read = try!(cvt(unsafe {
480+
libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity() as libc::size_t)
481+
})) as usize;
482+
483+
unsafe { buf.set_len(buf_read); }
484+
485+
if buf_read != buf.capacity() {
486+
buf.shrink_to_fit();
487+
488+
return Ok(PathBuf::from(OsString::from_vec(buf)));
489+
}
490+
491+
// Trigger the internal buffer resizing logic of `Vec` by requiring
492+
// more space than the current capacity. The length is guaranteed to be
493+
// the same as the capacity due to the if statement above.
494+
buf.reserve(1);
479495
}
480-
Ok(PathBuf::from(OsString::from_vec(buf)))
481496
}
482497

483498
pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
@@ -514,15 +529,15 @@ pub fn lstat(p: &Path) -> io::Result<FileAttr> {
514529

515530
pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
516531
let path = try!(CString::new(p.as_os_str().as_bytes()));
517-
let mut buf = vec![0u8; 16 * 1024];
532+
let buf;
518533
unsafe {
519-
let r = c::realpath(path.as_ptr(), buf.as_mut_ptr() as *mut _);
534+
let r = c::realpath(path.as_ptr(), ptr::null_mut());
520535
if r.is_null() {
521536
return Err(io::Error::last_os_error())
522537
}
538+
buf = CStr::from_ptr(r).to_bytes().to_vec();
539+
libc::free(r as *mut _);
523540
}
524-
let p = buf.iter().position(|i| *i == 0).unwrap();
525-
buf.truncate(p);
526541
Ok(PathBuf::from(OsString::from_vec(buf)))
527542
}
528543

branches/try/src/rt/rust_builtin.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,11 @@ const char * rust_current_exe()
341341
char **paths;
342342
size_t sz;
343343
int i;
344-
char buf[2*PATH_MAX], exe[2*PATH_MAX];
344+
/* If `PATH_MAX` is defined on the platform, `realpath` will truncate the
345+
* resolved path up to `PATH_MAX`. While this can make the resolution fail if
346+
* the executable is placed in a deep path, the usage of a buffer whose
347+
* length depends on `PATH_MAX` is still memory safe. */
348+
char buf[2*PATH_MAX], exe[PATH_MAX];
345349

346350
if (self != NULL)
347351
return self;

0 commit comments

Comments
 (0)