refactor(bare): enhance security and performance optimizations

- Remove unnecessary sorting in advertise_refs for deterministic output
- Add path traversal detection and validation in bare_dir construction
- Implement symlink resolution checks to prevent security vulnerabilities
- Refactor cache system with CRC validation and improved metrics
- Integrate repo-specific cache invalidation using indexed keys
- Add comprehensive unit tests for commit operations and diff functionality
- Move configuration constants to centralized config module
- Optimize string operations in disk cache random value generation
- Enhance license detection algorithm with cleaner matching logic
- Streamline argument processing in various git operations
- Update dependencies including crc32fast and flate2 for performance
- Add signal handling capability to tokio runtime configuration
This commit is contained in:
zhenyi
2026-06-12 15:04:12 +08:00
parent e386f44ee2
commit 10a4398e81
41 changed files with 1373 additions and 365 deletions
+182 -5
View File
@@ -1,6 +1,5 @@
use gitks::sanitize::*;
// ==================== validate_ref_name tests ====================
#[test]
fn test_validate_ref_name_accepts_valid_names() {
@@ -69,7 +68,6 @@ fn test_validate_ref_name_rejects_too_long() {
assert!(validate_ref_name(&max_valid_name).is_ok());
}
// ==================== validate_revision tests ====================
#[test]
fn test_validate_revision_accepts_empty() {
@@ -149,7 +147,6 @@ fn test_validate_revision_accepts_valid_branch_names() {
assert!(validate_revision("v1.0.0").is_ok());
}
// ==================== validate_file_path tests ====================
#[test]
fn test_validate_file_path_accepts_valid_paths() {
@@ -216,7 +213,6 @@ fn test_validate_file_path_rejects_windows_reserved_names() {
assert!(validate_file_path("CON.txt").is_err());
}
// ==================== validate_relative_path tests ====================
#[test]
fn test_validate_relative_path_accepts_valid_paths() {
@@ -244,7 +240,6 @@ fn test_validate_relative_path_rejects_traversal() {
assert!(validate_relative_path("path/..").is_err());
}
// ==================== validate_config_key tests ====================
#[test]
fn test_validate_config_key_accepts_safe_keys() {
@@ -281,3 +276,185 @@ fn test_validate_config_key_rejects_invalid_chars() {
assert!(validate_config_key("key$(command)").is_err());
assert!(validate_config_key("key`command`").is_err());
}
/// Ensure no input causes panic in validate_ref_name.
#[test]
fn fuzz_validate_ref_name_no_panic() {
let long_name = "x".repeat(300);
let test_inputs: Vec<&str> = vec![
"",
"\0",
"\0\0\0",
"\x7f",
"\x01\x02\x03",
"~^:?*[]\\ ",
"../../../etc/passwd",
"a/b/c/d/e/f/g/h",
&long_name,
"branch@{upstream}",
"HEAD~99999999999",
"HEAD^99999999999",
"ref:HEAD",
"ref:refs/heads/main",
"; rm -rf /",
"$(echo pwned)",
"`echo pwned`",
"\n\r\t",
];
for input in test_inputs {
let _ = validate_ref_name(input);
}
}
/// Ensure no input causes panic in validate_revision.
#[test]
fn fuzz_validate_revision_no_panic() {
let test_inputs: Vec<&str> = vec![
"",
"HEAD",
"HEAD~0",
"HEAD~99999999",
"HEAD^0",
"HEAD^99999999",
"HEAD^{tree}",
"HEAD^{commit}",
"HEAD^{object}",
"abcdef01",
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
"0000",
"zzzz",
"ref:HEAD",
"ref:refs/heads/main",
"\0",
"branch~abc",
"branch^abc",
"branch~",
"branch^",
"a~10001",
"a^10001",
];
for input in test_inputs {
let _ = validate_revision(input);
}
}
/// Ensure no input causes panic in validate_file_path.
#[test]
fn fuzz_validate_file_path_no_panic() {
let long_path = "x".repeat(5000);
let medium_path = "a".repeat(100);
let test_inputs: Vec<&str> = vec![
"",
"/etc/passwd",
"../escape",
"a/../b",
".git",
".git/config",
"src/.git/HEAD",
"a/b/.git",
"\0",
"\0\0\0",
&long_path,
"path/with\x00null",
"path/with\nnewline",
"normal/path.txt",
&medium_path,
];
for input in test_inputs {
let _ = validate_file_path(input);
}
}
/// Ensure no input causes panic in validate_remote_url.
#[test]
fn fuzz_validate_remote_url_no_panic() {
let long_url = "x".repeat(5000);
let test_inputs: Vec<&str> = vec![
"",
"https://github.com/user/repo",
"http://localhost:3000/repo",
"ssh://git@host/repo",
"git://host/repo",
"git+ssh://git@host/repo",
"file:///etc/passwd",
"ext::sh -c 'rm -rf /'",
"ftp://host/repo",
"https://user:pass@host/repo",
"\0",
"https://host\0injection",
&long_url,
];
for input in test_inputs {
let _ = validate_remote_url(input);
}
}
/// Ensure no input causes panic in validate_oid_hex.
#[test]
fn fuzz_validate_oid_hex_no_panic() {
let long_hex = "x".repeat(65);
let exact_hex = "x".repeat(64);
let test_inputs: Vec<&str> = vec![
"",
"abc",
"abcd",
"0123456789abcdef",
"ZZZZ",
"g000",
"0000000000000000000000000000000000000000",
&long_hex,
&exact_hex,
"\0",
" ",
"\n",
];
for input in test_inputs {
let _ = validate_oid_hex(input);
}
}
/// Ensure no input causes panic in validate_relative_path.
#[test]
fn fuzz_validate_relative_path_no_panic() {
let long_path = "x".repeat(5000);
let test_inputs: Vec<&str> = vec![
"",
"/absolute",
"relative/path",
"../escape",
"path/../escape",
"\0",
&long_path,
".",
"..",
"...",
"a/b/c",
];
for input in test_inputs {
let _ = validate_relative_path(input);
}
}
/// Ensure no input causes panic in validate_refspec.
#[test]
fn fuzz_validate_refspec_no_panic() {
let long_refspec = "x".repeat(2000);
let test_inputs: Vec<&str> = vec![
"",
"+refs/heads/*:refs/heads/*",
"refs/heads/main",
"; rm -rf /",
"$(evil)",
"`evil`",
"| pipe",
"& bg",
"< redirect",
"> redirect",
"\0",
&long_refspec,
];
for input in test_inputs {
let _ = validate_refspec(input);
}
}