summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSendil Kumar <sendilkumarn@live.com>2019-08-22 13:17:02 +0200
committerSendil Kumar <sendilkumarn@live.com>2019-08-22 13:17:02 +0200
commitea102096803dd12acf5fc592fb5c581e9b9ff51d (patch)
treedba4e53b9ea454efc8fd4d4ee4b85e7ff9516c0b
parent414cc86c0af09fd44454b93b6dc738316b16c43c (diff)
downloadnix-ea102096803dd12acf5fc592fb5c581e9b9ff51d.zip
fix readlink/readlinkat to return too long only when it is long
-rw-r--r--src/fcntl.rs4
-rw-r--r--test/test_fcntl.rs19
2 files changed, 18 insertions, 5 deletions
diff --git a/src/fcntl.rs b/src/fcntl.rs
index be6ee0f7..f590e361 100644
--- a/src/fcntl.rs
+++ b/src/fcntl.rs
@@ -181,7 +181,9 @@ fn wrap_readlink_result(buffer: &mut[u8], res: ssize_t) -> Result<&OsStr> {
match Errno::result(res) {
Err(err) => Err(err),
Ok(len) => {
- if (len as usize) >= buffer.len() {
+ if len < 0 {
+ Err(Error::Sys(Errno::EINVAL))
+ } else if (len as usize) > buffer.len() {
Err(Error::Sys(Errno::ENAMETOOLONG))
} else {
Ok(OsStr::from_bytes(&buffer[..(len as usize)]))
diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs
index 6b2bbd67..c8773219 100644
--- a/test/test_fcntl.rs
+++ b/test/test_fcntl.rs
@@ -56,12 +56,23 @@ fn test_readlink() {
let dirfd = open(tempdir.path(),
OFlag::empty(),
Mode::empty()).unwrap();
+ let expected_dir = src.to_str().unwrap();
+ // When the size of the buffer is bigger than the expected directory length
let mut buf = vec![0; src.to_str().unwrap().len() + 1];
- assert_eq!(readlink(&dst, &mut buf).unwrap().to_str().unwrap(),
- src.to_str().unwrap());
- assert_eq!(readlinkat(dirfd, "b", &mut buf).unwrap().to_str().unwrap(),
- src.to_str().unwrap());
+ assert_eq!(readlink(&dst, &mut buf).unwrap().to_str().unwrap(), expected_dir);
+ assert_eq!(readlinkat(dirfd, "b", &mut buf).unwrap().to_str().unwrap(), expected_dir);
+
+ // When the size of the buffer is equal to the expected directory length
+ let mut exact_buf = vec![0; src.to_str().unwrap().len()];
+ assert_eq!(readlink(&dst, &mut exact_buf).unwrap().to_str().unwrap(), expected_dir);
+ assert_eq!(readlinkat(dirfd, "b", &mut exact_buf).unwrap().to_str().unwrap(), expected_dir);
+
+ // When the size of the buffer is smaller than the expected directory length
+ let mut small_buf = vec![0;0];
+ assert_eq!(readlink(&dst, &mut small_buf).unwrap().to_str().unwrap(), "");
+ assert_eq!(readlinkat(dirfd, "b", &mut small_buf).unwrap().to_str().unwrap(), "");
+
}
#[cfg(any(target_os = "linux", target_os = "android"))]