Be more accepting in creating blobs from existing names

This is an additional fix for #768 aka
commit eac8ad8369
This commit is contained in:
Floris Bruynooghe
2019-10-31 09:53:20 +01:00
committed by holger krekel
parent 80d7e84e5d
commit b264d3be3c

View File

@@ -1,3 +1,4 @@
use std::ffi::OsStr;
use std::fmt; use std::fmt;
use std::fs; use std::fs;
use std::io::Write; use std::io::Write;
@@ -145,6 +146,9 @@ impl<'a> BlobObject<'a> {
.as_ref() .as_ref()
.strip_prefix(context.get_blobdir()) .strip_prefix(context.get_blobdir())
.map_err(|_| BlobError::new_wrong_blobdir(context.get_blobdir(), path.as_ref()))?; .map_err(|_| BlobError::new_wrong_blobdir(context.get_blobdir(), path.as_ref()))?;
if !BlobObject::is_acceptible_blob_name(&rel_path) {
return Err(BlobError::new_wrong_name(path.as_ref()));
}
let name = rel_path let name = rel_path
.to_str() .to_str()
.ok_or_else(|| BlobError::new_wrong_name(path.as_ref()))?; .ok_or_else(|| BlobError::new_wrong_name(path.as_ref()))?;
@@ -171,8 +175,7 @@ impl<'a> BlobObject<'a> {
true => name.splitn(2, '/').last().unwrap().to_string(), true => name.splitn(2, '/').last().unwrap().to_string(),
false => name, false => name,
}; };
let (stem, ext) = BlobObject::sanitise_name(name.clone()); if !BlobObject::is_acceptible_blob_name(&name) {
if format!("{}{}", stem, ext) != name.as_ref() {
return Err(BlobError::new_wrong_name(name)); return Err(BlobError::new_wrong_name(name));
} }
Ok(BlobObject { Ok(BlobObject {
@@ -266,6 +269,28 @@ impl<'a> BlobObject<'a> {
_ => (stem, format!(".{}", ext).to_lowercase()), _ => (stem, format!(".{}", ext).to_lowercase()),
} }
} }
/// Checks whether a name is a valid blob name.
///
/// This is slightly less strict than stanitise_name, presumably
/// someone already created a file with such a name so we just
/// ensure it's not actually a path in disguise is actually utf-8.
fn is_acceptible_blob_name(name: impl AsRef<OsStr>) -> bool {
let uname = match name.as_ref().to_str() {
Some(name) => name,
None => return false,
};
if uname.find('/').is_some() {
return false;
}
if uname.find('\\').is_some() {
return false;
}
if uname.find('\0').is_some() {
return false;
}
true
}
} }
impl<'a> fmt::Display for BlobObject<'a> { impl<'a> fmt::Display for BlobObject<'a> {
@@ -615,4 +640,14 @@ mod tests {
"$BLOBDIR/autocrypt-setup-message-4137848473.html" "$BLOBDIR/autocrypt-setup-message-4137848473.html"
); );
} }
#[test]
fn test_is_blob_name() {
assert!(BlobObject::is_acceptible_blob_name("foo"));
assert!(BlobObject::is_acceptible_blob_name("foo.txt"));
assert!(BlobObject::is_acceptible_blob_name("f".repeat(128)));
assert!(!BlobObject::is_acceptible_blob_name("foo/bar"));
assert!(!BlobObject::is_acceptible_blob_name("foo\\bar"));
assert!(!BlobObject::is_acceptible_blob_name("foo\x00bar"));
}
} }