mirror of
https://github.com/storytold/deckcraft.git
synced 2026-11-05 01:49:41 -06:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3cebb96b6 |
@@ -415,6 +415,11 @@ impl CaptureScanner {
|
||||
}
|
||||
|
||||
fn read_parts(src: &(impl ByteSource + ?Sized), parts: &[(u64, u32)]) -> Result<Vec<u8>> {
|
||||
// Ranges come from a scan of some source; check them against this one before sizing a buffer.
|
||||
let len = src.len();
|
||||
if parts.iter().any(|&(o, n)| o.checked_add(u64::from(n)).is_none_or(|end| end > len)) {
|
||||
return Err(Error::Invalid("packet range lies outside the source".into()));
|
||||
}
|
||||
let mut v = Vec::with_capacity(parts.iter().map(|p| p.1 as usize).sum());
|
||||
for &(o, n) in parts {
|
||||
let a = v.len();
|
||||
|
||||
@@ -274,3 +274,13 @@ fn a_budget_too_small_to_search_is_spent() {
|
||||
let f = opus_file(6, 312, 0);
|
||||
assert_eq!(scanner.find(&f, 0, f.len() as u64).unwrap(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_packet_checks_its_ranges_against_the_source_before_allocating() {
|
||||
let f = opus_file(10, 312, 500);
|
||||
let o = open(&f).unwrap();
|
||||
let s = o.stream_of(Codec::Opus).unwrap();
|
||||
// The last packet lies past the end of a source cut short: an error, not a read of missing bytes.
|
||||
let short = &f[..f.len() / 2];
|
||||
assert!(matches!(o.read_packet(&short, s, 9), Err(Error::Invalid(_))));
|
||||
}
|
||||
|
||||
+7
-23
@@ -61,23 +61,16 @@ pub fn missing(files: &[String], assets_md: &str) -> Vec<String> {
|
||||
files.iter().filter(|f| is_asset(f) && !patterns.iter().any(|p| glob(p, f))).cloned().collect()
|
||||
}
|
||||
|
||||
/// `*` matches any run of characters except `/`; everything else literally. Matched with a
|
||||
/// table over the pattern, so a pattern with many `*` costs pattern length times name length
|
||||
/// rather than exploring every way to split the name.
|
||||
/// `*` matches any run of characters except `/`; everything else literally.
|
||||
fn glob(pat: &str, s: &str) -> bool {
|
||||
let t: Vec<char> = s.chars().collect();
|
||||
// `row[k]`: the pattern so far matches the first k characters of the name.
|
||||
let mut row = vec![false; t.len() + 1];
|
||||
row[0] = true;
|
||||
for pc in pat.chars() {
|
||||
let mut next = vec![false; t.len() + 1];
|
||||
next[0] = pc == '*' && row[0];
|
||||
for k in 1..=t.len() {
|
||||
next[k] = if pc == '*' { row[k] || (next[k - 1] && t[k - 1] != '/') } else { row[k - 1] && t[k - 1] == pc };
|
||||
match pat.split_once('*') {
|
||||
None => pat == s,
|
||||
Some((head, tail)) => {
|
||||
let Some(rest) = s.strip_prefix(head) else { return false };
|
||||
let ends = rest.char_indices().map(|(i, _)| i).chain(std::iter::once(rest.len()));
|
||||
ends.take_while(|&i| !rest[..i].contains('/')).any(|i| glob(tail, &rest[i..]))
|
||||
}
|
||||
row = next;
|
||||
}
|
||||
row[t.len()]
|
||||
}
|
||||
|
||||
/// Splits `git ls-files -z` output into real file names (no display quoting of Unicode or special characters).
|
||||
@@ -127,15 +120,6 @@ mod tests {
|
||||
assert_eq!(missing(&["assets/é.png".into()], "`assets/*.svg`"), vec!["assets/é.png".to_string()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn many_wildcards_on_a_failing_name_finish_at_once() {
|
||||
let pat = format!("{}b", "a*".repeat(40));
|
||||
assert!(!glob(&pat, &"a".repeat(60)));
|
||||
assert!(glob(&pat, &format!("{}b", "a".repeat(60))));
|
||||
assert!(!glob("a*b", "a/b"));
|
||||
assert!(glob("a*b", "ab"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ls_files_output_is_nul_separated_and_unquoted() {
|
||||
let names = parse_ls_files("assets/zażółć.png\0docs/images/a b\nc.png\0".as_bytes());
|
||||
|
||||
+7
-1
@@ -18,7 +18,13 @@ fn walk(dir: &Path, c: &mut Counts) {
|
||||
let p = e.path();
|
||||
let name = e.file_name();
|
||||
let name = name.to_string_lossy();
|
||||
if p.is_dir() {
|
||||
// `file_type` does not follow links, so a directory link is not walked (and aliases are
|
||||
// not counted twice).
|
||||
let Ok(kind) = e.file_type() else { continue };
|
||||
if kind.is_symlink() {
|
||||
continue;
|
||||
}
|
||||
if kind.is_dir() {
|
||||
// Nested fuzz workspaces and build output are not part of the crate.
|
||||
if name != "target" && name != "fuzz" && !name.starts_with('.') {
|
||||
walk(&p, c);
|
||||
|
||||
Reference in New Issue
Block a user