Skip to content

Commit

Permalink
rafs: fix a possible bug in v6_dirent_size()
Browse files Browse the repository at this point in the history
Function Node::v6_dirent_size() may return wrong result when "." and
".." are not at the first and second entries in the sorted dirent array.

Signed-off-by: Jiang Liu <gerry@linux.alibaba.com>
  • Loading branch information
jiangliu committed Apr 14, 2023
1 parent ef2033c commit 84c64bd
Showing 1 changed file with 37 additions and 13 deletions.
50 changes: 37 additions & 13 deletions src/bin/nydus-image/core/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1101,20 +1101,44 @@ impl Node {

pub fn v6_dir_d_size(&self, tree: &Tree) -> Result<u64> {
ensure!(self.is_dir(), "{} is not a directory", self);
// Use length in byte, instead of length in character.
let mut d_size: u64 = (".".as_bytes().len()
+ size_of::<RafsV6Dirent>()
+ "..".as_bytes().len()
+ size_of::<RafsV6Dirent>()) as u64;

// Safe as we have check tree above.
for child in tree.children.iter() {
let len = child.node.name().as_bytes().len() + size_of::<RafsV6Dirent>();
// erofs disk format requires dirent to be aligned with 4096.
if (d_size % EROFS_BLOCK_SIZE) + len as u64 > EROFS_BLOCK_SIZE {
d_size = div_round_up(d_size as u64, EROFS_BLOCK_SIZE) * EROFS_BLOCK_SIZE;
let mut d_size = 0;

// Sort all children if "." and ".." are not at the head after sorting.
if !tree.children.is_empty() && tree.children[0].node.name() < ".." {
let mut children = Vec::with_capacity(tree.children.len() + 2);
let dot = OsString::from(".");
let dotdot = OsString::from("..");
children.push(dot.as_os_str());
children.push(dotdot.as_os_str());
for child in tree.children.iter() {
children.push(child.node.name());
}
children.sort_unstable();

for c in children {
// Use length in byte, instead of length in character.
let len = c.as_bytes().len() + size_of::<RafsV6Dirent>();
// erofs disk format requires dirent to be aligned to block size.
if (d_size % EROFS_BLOCK_SIZE) + len as u64 > EROFS_BLOCK_SIZE {
d_size = round_up(d_size as u64, EROFS_BLOCK_SIZE);
}
d_size += len as u64;
}
} else {
// Avoid sorting again if "." and ".." are at the head after sorting due to that
// `tree.children` has already been sorted.
d_size = (".".as_bytes().len()
+ size_of::<RafsV6Dirent>()
+ "..".as_bytes().len()
+ size_of::<RafsV6Dirent>()) as u64;
for child in tree.children.iter() {
let len = child.node.name().as_bytes().len() + size_of::<RafsV6Dirent>();
// erofs disk format requires dirent to be aligned to block size.
if (d_size % EROFS_BLOCK_SIZE) + len as u64 > EROFS_BLOCK_SIZE {
d_size = round_up(d_size as u64, EROFS_BLOCK_SIZE);
}
d_size += len as u64;
}
d_size += len as u64;
}

Ok(d_size)
Expand Down

0 comments on commit 84c64bd

Please sign in to comment.