f Better handling of `relative_path`
[rust-lightning] / lightning-persister / src / fs_store.rs
index cd3e9dda5c6e5bc2a213ee3af039d197f856f384..c29f0fb05f54a86d559005ccbacc79a4a659eb7a 100644 (file)
@@ -1,5 +1,6 @@
 //! Objects related to [`FilesystemStore`] live here.
 use lightning::util::persist::KVStore;
+use lightning::util::string::PrintableString;
 
 use std::collections::HashMap;
 use std::fs;
@@ -53,7 +54,17 @@ impl KVStore for FilesystemStore {
 
        fn read(&self, namespace: &str, key: &str) -> std::io::Result<Self::Reader> {
                if key.is_empty() {
-                       let msg = format!("Failed to read {}/{}: key may not be empty.", namespace, key);
+                       let msg = format!("Failed to read {}/{}: key may not be empty.",
+                               PrintableString(namespace), PrintableString(key));
+                       return Err(std::io::Error::new(std::io::ErrorKind::Other, msg));
+               }
+
+               if namespace.chars().any(|c| !c.is_ascii() || c.is_control()) ||
+                       key.chars().any(|c| !c.is_ascii() || c.is_control()) {
+                       debug_assert!(false, "Failed to read {}/{}: namespace and key must be valid ASCII
+                               strings.", PrintableString(namespace), PrintableString(key));
+                       let msg = format!("Failed to read {}/{}: namespace and key must be valid ASCII strings.",
+                               PrintableString(namespace), PrintableString(key));
                        return Err(std::io::Error::new(std::io::ErrorKind::Other, msg));
                }
 
@@ -69,7 +80,17 @@ impl KVStore for FilesystemStore {
 
        fn write(&self, namespace: &str, key: &str, buf: &[u8]) -> std::io::Result<()> {
                if key.is_empty() {
-                       let msg = format!("Failed to write {}/{}: key may not be empty.", namespace, key);
+                       let msg = format!("Failed to write {}/{}: key may not be empty.",
+                               PrintableString(namespace), PrintableString(key));
+                       return Err(std::io::Error::new(std::io::ErrorKind::Other, msg));
+               }
+
+               if namespace.chars().any(|c| !c.is_ascii() || c.is_control()) ||
+                       key.chars().any(|c| !c.is_ascii() || c.is_control()) {
+                       debug_assert!(false, "Failed to write {}/{}: namespace and key must be valid ASCII
+                               strings.", PrintableString(namespace), PrintableString(key));
+                       let msg = format!("Failed to write {}/{}: namespace and key must be valid ASCII strings.",
+                               PrintableString(namespace), PrintableString(key));
                        return Err(std::io::Error::new(std::io::ErrorKind::Other, msg));
                }
 
@@ -144,7 +165,17 @@ impl KVStore for FilesystemStore {
 
        fn remove(&self, namespace: &str, key: &str) -> std::io::Result<()> {
                if key.is_empty() {
-                       let msg = format!("Failed to remove {}/{}: key may not be empty.", namespace, key);
+                       let msg = format!("Failed to remove {}/{}: key may not be empty.",
+                               PrintableString(namespace), PrintableString(key));
+                       return Err(std::io::Error::new(std::io::ErrorKind::Other, msg));
+               }
+
+               if namespace.chars().any(|c| !c.is_ascii() || c.is_control()) ||
+                       key.chars().any(|c| !c.is_ascii() || c.is_control()) {
+                       debug_assert!(false, "Failed to remove {}/{}: namespace and key must be valid ASCII
+                               strings.", PrintableString(namespace), PrintableString(key));
+                       let msg = format!("Failed to remove {}/{}: namespace and key must be valid ASCII strings.",
+                               PrintableString(namespace), PrintableString(key));
                        return Err(std::io::Error::new(std::io::ErrorKind::Other, msg));
                }
 
@@ -228,8 +259,11 @@ impl KVStore for FilesystemStore {
                                }
                        }
 
-                       if let Ok(relative_path) = p.strip_prefix(&prefixed_dest) {
-                               keys.push(relative_path.display().to_string())
+                       if let Some(relative_path) = p.strip_prefix(&prefixed_dest).ok()
+                               .and_then(|p| p.to_str()) {
+                                       if relative_path.chars().all(|c| c.is_ascii() && !c.is_control()) {
+                                               keys.push(relative_path.to_string())
+                                       }
                        }
                }