From b6fd6ec3b764910c29b5e6d755d0d164eaba9069 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 19 Aug 2024 12:07:36 -0400 Subject: [PATCH 1/2] Reject an empty name Yep, just me testing more boundary conditions; this is another one that ends up with a corrupted erofs. Reject empty filenames in both the shared library and the C parser. Signed-off-by: Colin Walters --- libcomposefs/lcfs-writer.c | 7 ++++++- tests/assets/should-fail-empty-name.dump | 2 ++ tests/meson.build | 1 + tools/mkcomposefs.c | 3 +++ 4 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 tests/assets/should-fail-empty-name.dump diff --git a/libcomposefs/lcfs-writer.c b/libcomposefs/lcfs-writer.c index c63a10d..209781c 100644 --- a/libcomposefs/lcfs-writer.c +++ b/libcomposefs/lcfs-writer.c @@ -1132,7 +1132,12 @@ int lcfs_node_add_child(struct lcfs_node_s *parent, struct lcfs_node_s *child, return -1; } - if (strlen(name) > LCFS_MAX_NAME_LENGTH) { + const size_t namelen = strlen(name); + if (namelen == 0) { + errno = EINVAL; + return -1; + } + if (namelen > LCFS_MAX_NAME_LENGTH) { errno = ENAMETOOLONG; return -1; } diff --git a/tests/assets/should-fail-empty-name.dump b/tests/assets/should-fail-empty-name.dump new file mode 100644 index 0000000..0ef0bbe --- /dev/null +++ b/tests/assets/should-fail-empty-name.dump @@ -0,0 +1,2 @@ +/ 4096 40555 2 0 0 0 1633950376.0 - - - +// 4096 40555 2 0 0 0 1633950376.0 - - - diff --git a/tests/meson.build b/tests/meson.build index a1b6058..e7068b0 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -15,6 +15,7 @@ test_assets_should_fail = [ 'should-fail-long-xattr-key.dump', 'should-fail-long-xattr-value.dump', 'should-fail-no-ftype.dump', + 'should-fail-empty-name.dump', ] test_assets = test_assets_small + [ diff --git a/tools/mkcomposefs.c b/tools/mkcomposefs.c index 2832162..a8b096b 100644 --- a/tools/mkcomposefs.c +++ b/tools/mkcomposefs.c @@ -414,6 +414,9 @@ static char *tree_from_dump_line(dump_info *info, const char *line, size_t line_ fields[FIELD_PATH].data, fields[FIELD_PATH].len, NULL, &err); if (path == NULL && err) return err; + if (!*path) { + return make_error("Invalid empty path"); + } bool is_hardlink = false; /* First char in mode is @ if hardlink */ From 81f1d1ba57647d9d80356ed022cc8f984b25ca20 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 19 Aug 2024 14:25:29 -0400 Subject: [PATCH 2/2] rust: Reject empty name Corresponding to the C change. Signed-off-by: Colin Walters --- rust/composefs/src/dumpfile.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/rust/composefs/src/dumpfile.rs b/rust/composefs/src/dumpfile.rs index c0e99d9..595fb09 100644 --- a/rust/composefs/src/dumpfile.rs +++ b/rust/composefs/src/dumpfile.rs @@ -156,7 +156,13 @@ fn unescape_to_osstr(s: &str) -> Result> { /// Unescape a string into a Rust `Path` which is really just an alias for a byte array, /// although there is an implicit assumption that there are no embedded `NUL` bytes. fn unescape_to_path(s: &str) -> Result> { - let r = match unescape_to_osstr(s)? { + let v = unescape_to_osstr(s).and_then(|v| { + if v.is_empty() { + anyhow::bail!("Invalid empty path"); + } + Ok(v) + })?; + let r = match v { Cow::Borrowed(v) => Cow::Borrowed(Path::new(v)), Cow::Owned(v) => Cow::Owned(PathBuf::from(v)), }; @@ -433,6 +439,11 @@ mod tests { } } + #[test] + fn test_unescape_path() { + assert!(unescape_to_path("").is_err()); + } + #[test] fn test_parse() { const CONTENT: &str = include_str!("../../../tests/assets/special.dump");