merge: resolve dev (quality refactor) into security-fixes
- file.c split layout retained; security-hardened secure-fs helpers (open_secure_parent/to_disk_secure/rename_secure/stat_secure) now live in file.c with file_ prefix and are shared with file_receive.c - file_receive.c takes the security branch's bounded allocations (receive_data_limited, data_decompress_limited, size checks) and STATUS_ERROR signaling - file_send.c gains the data consistency check on file->data - client_validation.c: stricter --tls requiring --ca, log_message style - utils.c: hardened openat/mkdirat mkdir_r from security branch
This commit is contained in:
+3
-3
@@ -11,7 +11,7 @@ static void test_file_operations() {
|
||||
char* test_content = "Hello, Chunk System!";
|
||||
unsigned long long test_len = strlen(test_content);
|
||||
|
||||
to_disk(test_path, test_content, test_len, false, false);
|
||||
file_write_to_disk(test_path, test_content, test_len, false, false);
|
||||
|
||||
File* f = file_create(test_path);
|
||||
EXPECT_NOT_NULL(f);
|
||||
@@ -43,8 +43,8 @@ static void test_chunk_operations() {
|
||||
char* content2 = "chunk item number 2";
|
||||
unsigned long long len2 = strlen(content2);
|
||||
|
||||
to_disk(path1, content1, len1, false, false);
|
||||
to_disk(path2, content2, len2, false, false);
|
||||
file_write_to_disk(path1, content1, len1, false, false);
|
||||
file_write_to_disk(path2, content2, len2, false, false);
|
||||
|
||||
struct stat st1, st2;
|
||||
stat(path1, &st1);
|
||||
|
||||
@@ -64,8 +64,8 @@ static void test_chunk_compress_decompress_roundtrip() {
|
||||
char* content2 = "chunk compression test file 2 with more data";
|
||||
unsigned long long len2 = strlen(content2);
|
||||
|
||||
to_disk(path1, content1, len1, false, false);
|
||||
to_disk(path2, content2, len2, false, false);
|
||||
file_write_to_disk(path1, content1, len1, false, false);
|
||||
file_write_to_disk(path2, content2, len2, false, false);
|
||||
|
||||
struct stat st1, st2;
|
||||
EXPECT_EQ_INT(stat(path1, &st1), 0);
|
||||
|
||||
+15
-15
@@ -244,26 +244,26 @@ static void test_config_receive_truncated() {
|
||||
close(p[1]);
|
||||
}
|
||||
|
||||
static void test_is_remote_dest() {
|
||||
static void test_config_is_remote_dest() {
|
||||
/* Valid SSH-style destinations */
|
||||
EXPECT_TRUE(is_remote_dest("user@host:/path"));
|
||||
EXPECT_TRUE(is_remote_dest("host:/path"));
|
||||
EXPECT_TRUE(is_remote_dest("user@192.168.1.1:/remote/path"));
|
||||
EXPECT_TRUE(config_is_remote_dest("user@host:/path"));
|
||||
EXPECT_TRUE(config_is_remote_dest("host:/path"));
|
||||
EXPECT_TRUE(config_is_remote_dest("user@192.168.1.1:/remote/path"));
|
||||
|
||||
/* Invalid destinations */
|
||||
EXPECT_FALSE(is_remote_dest(NULL));
|
||||
EXPECT_FALSE(is_remote_dest(""));
|
||||
EXPECT_FALSE(is_remote_dest(":"));
|
||||
EXPECT_FALSE(is_remote_dest("/local/path"));
|
||||
EXPECT_FALSE(is_remote_dest("relative/path"));
|
||||
EXPECT_FALSE(config_is_remote_dest(NULL));
|
||||
EXPECT_FALSE(config_is_remote_dest(""));
|
||||
EXPECT_FALSE(config_is_remote_dest(":"));
|
||||
EXPECT_FALSE(config_is_remote_dest("/local/path"));
|
||||
EXPECT_FALSE(config_is_remote_dest("relative/path"));
|
||||
/* C:/windows/path is treated as remote (colon with no preceding slash) */
|
||||
EXPECT_TRUE(is_remote_dest("C:/windows/path"));
|
||||
EXPECT_TRUE(config_is_remote_dest("C:/windows/path"));
|
||||
|
||||
/* Edge cases */
|
||||
EXPECT_FALSE(is_remote_dest("noslash"));
|
||||
EXPECT_FALSE(is_remote_dest("/"));
|
||||
EXPECT_TRUE(is_remote_dest("host:"));
|
||||
EXPECT_TRUE(is_remote_dest("user@host:"));
|
||||
EXPECT_FALSE(config_is_remote_dest("noslash"));
|
||||
EXPECT_FALSE(config_is_remote_dest("/"));
|
||||
EXPECT_TRUE(config_is_remote_dest("host:"));
|
||||
EXPECT_TRUE(config_is_remote_dest("user@host:"));
|
||||
}
|
||||
|
||||
void test_config() {
|
||||
@@ -278,5 +278,5 @@ void test_config() {
|
||||
test_config_send_receive_version_mismatch();
|
||||
test_config_receive_truncated();
|
||||
}
|
||||
test_is_remote_dest();
|
||||
test_config_is_remote_dest();
|
||||
}
|
||||
|
||||
+23
-20
@@ -34,7 +34,8 @@ static void test_file_destroy_normal() {
|
||||
|
||||
static void test_file_load_data() {
|
||||
const char* content = "Hello Load Test";
|
||||
EXPECT_TRUE(to_disk("test_file_load_data.txt", content, strlen(content), false, false));
|
||||
EXPECT_TRUE(
|
||||
file_write_to_disk("test_file_load_data.txt", content, strlen(content), false, false));
|
||||
|
||||
struct stat st;
|
||||
EXPECT_EQ_INT(stat("test_file_load_data.txt", &st), 0);
|
||||
@@ -87,15 +88,16 @@ static void test_file_save_to_disk() {
|
||||
rmdir("test_save_tmp");
|
||||
}
|
||||
|
||||
static void test_to_disk_basic() {
|
||||
const char* content = "Basic to_disk test";
|
||||
EXPECT_TRUE(to_disk("test_to_disk_basic.txt", content, strlen(content), false, false));
|
||||
static void test_file_write_to_disk_basic() {
|
||||
const char* content = "Basic file_write_to_disk test";
|
||||
EXPECT_TRUE(file_write_to_disk("test_file_write_to_disk_basic.txt", content, strlen(content),
|
||||
false, false));
|
||||
|
||||
struct stat st;
|
||||
EXPECT_EQ_INT(stat("test_to_disk_basic.txt", &st), 0);
|
||||
EXPECT_EQ_INT(stat("test_file_write_to_disk_basic.txt", &st), 0);
|
||||
EXPECT_EQ_INT((int)st.st_size, (int)strlen(content));
|
||||
|
||||
FILE* fp = fopen("test_to_disk_basic.txt", "rb");
|
||||
FILE* fp = fopen("test_file_write_to_disk_basic.txt", "rb");
|
||||
EXPECT_NOT_NULL(fp);
|
||||
char buf[100];
|
||||
size_t nread = fread(buf, 1, sizeof(buf), fp);
|
||||
@@ -103,12 +105,13 @@ static void test_to_disk_basic() {
|
||||
EXPECT_EQ_INT((int)nread, (int)strlen(content));
|
||||
EXPECT_EQ_INT(memcmp(buf, content, strlen(content)), 0);
|
||||
|
||||
unlink("test_to_disk_basic.txt");
|
||||
unlink("test_file_write_to_disk_basic.txt");
|
||||
}
|
||||
|
||||
static void test_to_disk_creates_dirs() {
|
||||
static void test_file_write_to_disk_creates_dirs() {
|
||||
const char* content = "Nested dir test";
|
||||
EXPECT_TRUE(to_disk("test_nested_tmp/nested/file.txt", content, strlen(content), false, false));
|
||||
EXPECT_TRUE(file_write_to_disk("test_nested_tmp/nested/file.txt", content, strlen(content), false,
|
||||
false));
|
||||
|
||||
struct stat st;
|
||||
EXPECT_EQ_INT(stat("test_nested_tmp/nested/file.txt", &st), 0);
|
||||
@@ -126,15 +129,15 @@ static void test_to_disk_creates_dirs() {
|
||||
rmdir("test_nested_tmp");
|
||||
}
|
||||
|
||||
static void test_to_disk_does_not_follow_symlink() {
|
||||
const char* outside = "test_to_disk_outside.txt";
|
||||
const char* link = "test_to_disk_link.txt";
|
||||
static void test_file_write_to_disk_does_not_follow_symlink() {
|
||||
const char* outside = "test_file_write_to_disk_outside.txt";
|
||||
const char* link = "test_file_write_to_disk_link.txt";
|
||||
const char* content = "confined";
|
||||
unlink(outside);
|
||||
unlink(link);
|
||||
EXPECT_TRUE(to_disk(outside, "outside", 7, false, false));
|
||||
EXPECT_TRUE(file_write_to_disk(outside, "outside", 7, false, false));
|
||||
EXPECT_EQ_INT(symlink(outside, link), 0);
|
||||
EXPECT_TRUE(to_disk(link, content, strlen(content), false, false));
|
||||
EXPECT_TRUE(file_write_to_disk(link, content, strlen(content), false, false));
|
||||
FILE* fp = fopen(outside, "rb");
|
||||
char buf[16] = {0};
|
||||
EXPECT_NOT_NULL(fp);
|
||||
@@ -151,7 +154,7 @@ static void test_to_disk_does_not_follow_symlink() {
|
||||
|
||||
static void test_file_content_to_buffer() {
|
||||
const char* content = "Buffer content test";
|
||||
EXPECT_TRUE(to_disk("test_buffer_file.txt", content, strlen(content), false, false));
|
||||
EXPECT_TRUE(file_write_to_disk("test_buffer_file.txt", content, strlen(content), false, false));
|
||||
|
||||
File* f = file_create("test_buffer_file.txt");
|
||||
EXPECT_NOT_NULL(f);
|
||||
@@ -273,7 +276,7 @@ static void test_file_send_no_path() {
|
||||
}
|
||||
|
||||
static void test_file_metadata_create() {
|
||||
EXPECT_TRUE(to_disk("test_meta_file.txt", "metadata test", 13, false, false));
|
||||
EXPECT_TRUE(file_write_to_disk("test_meta_file.txt", "metadata test", 13, false, false));
|
||||
struct stat st;
|
||||
EXPECT_EQ_INT(stat("test_meta_file.txt", &st), 0);
|
||||
|
||||
@@ -382,7 +385,7 @@ static void test_file_send_single_calls_metadata_and_path() {
|
||||
/* Create a real file on disk so we can have metadata */
|
||||
const char* content = "File with metadata";
|
||||
size_t len = strlen(content);
|
||||
EXPECT_TRUE(to_disk("test_meta_send.txt", content, len, false, false));
|
||||
EXPECT_TRUE(file_write_to_disk("test_meta_send.txt", content, len, false, false));
|
||||
|
||||
struct stat st;
|
||||
EXPECT_EQ_INT(stat("test_meta_send.txt", &st), 0);
|
||||
@@ -455,9 +458,9 @@ void test_file() {
|
||||
test_file_load_data();
|
||||
test_file_load_data_missing_file();
|
||||
test_file_save_to_disk();
|
||||
test_to_disk_basic();
|
||||
test_to_disk_creates_dirs();
|
||||
test_to_disk_does_not_follow_symlink();
|
||||
test_file_write_to_disk_basic();
|
||||
test_file_write_to_disk_creates_dirs();
|
||||
test_file_write_to_disk_does_not_follow_symlink();
|
||||
test_file_content_to_buffer();
|
||||
test_file_save_to_disk_path_traversal();
|
||||
test_file_save_to_disk_deep_traversal();
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
static void test_sendfile_basic() {
|
||||
const char* content = "Hello from sendfile test!";
|
||||
size_t len = strlen(content);
|
||||
EXPECT_TRUE(to_disk("test_sendfile_basic.txt", content, len, false, false));
|
||||
EXPECT_TRUE(file_write_to_disk("test_sendfile_basic.txt", content, len, false, false));
|
||||
|
||||
File* file = file_create("test_sendfile_basic.txt");
|
||||
EXPECT_NOT_NULL(file);
|
||||
@@ -77,7 +77,7 @@ static void test_sendfile_basic() {
|
||||
static void test_sendfile_empty_file() {
|
||||
const char* content = "";
|
||||
size_t len = 0;
|
||||
EXPECT_TRUE(to_disk("test_sendfile_empty.txt", content, len, false, false));
|
||||
EXPECT_TRUE(file_write_to_disk("test_sendfile_empty.txt", content, len, false, false));
|
||||
|
||||
File* file = file_create("test_sendfile_empty.txt");
|
||||
EXPECT_NOT_NULL(file);
|
||||
@@ -156,7 +156,7 @@ static void test_sendfile_missing_file() {
|
||||
static void test_sendfile_compression_fallback() {
|
||||
const char* content = "Compression fallback content";
|
||||
size_t len = strlen(content);
|
||||
EXPECT_TRUE(to_disk("test_sendfile_comp.txt", content, len, false, false));
|
||||
EXPECT_TRUE(file_write_to_disk("test_sendfile_comp.txt", content, len, false, false));
|
||||
|
||||
struct stat st;
|
||||
EXPECT_EQ_INT(stat("test_sendfile_comp.txt", &st), 0);
|
||||
@@ -222,7 +222,7 @@ static void test_sendfile_compression_fallback() {
|
||||
static void test_sendfile_no_path() {
|
||||
const char* content = "No path sendfile test";
|
||||
size_t len = strlen(content);
|
||||
EXPECT_TRUE(to_disk("test_sendfile_nopath.txt", content, len, false, false));
|
||||
EXPECT_TRUE(file_write_to_disk("test_sendfile_nopath.txt", content, len, false, false));
|
||||
|
||||
File* file = file_create("test_sendfile_nopath.txt");
|
||||
EXPECT_NOT_NULL(file);
|
||||
|
||||
@@ -101,7 +101,7 @@ static void test_fuzz_delta_deserialize() {
|
||||
/* Smoke test for metadata_from_buf fuzz target */
|
||||
static void test_fuzz_metadata_from_buf() {
|
||||
/* Create a real file to get metadata from */
|
||||
EXPECT_TRUE(to_disk("fuzz_meta_test.txt", "metadata test", 13, false, false));
|
||||
EXPECT_TRUE(file_write_to_disk("fuzz_meta_test.txt", "metadata test", 13, false, false));
|
||||
|
||||
struct stat st;
|
||||
EXPECT_EQ_INT(stat("fuzz_meta_test.txt", &st), 0);
|
||||
|
||||
@@ -125,7 +125,7 @@ static void test_metadata_rejects_invalid_values() {
|
||||
static void test_file_restore_metadata() {
|
||||
const char* path = "temp_meta_restore_test.txt";
|
||||
const char* content = "test content";
|
||||
EXPECT_TRUE(to_disk(path, content, strlen(content), false, false));
|
||||
EXPECT_TRUE(file_write_to_disk(path, content, strlen(content), false, false));
|
||||
|
||||
FileMetadata m;
|
||||
m.mode = 0644;
|
||||
|
||||
@@ -88,7 +88,7 @@ static void test_property_chunk_roundtrip() {
|
||||
for (int i = 0; i < content_len; i++)
|
||||
content[i] = (char)(rand() % 256);
|
||||
|
||||
to_disk(path, content, content_len, false, false);
|
||||
file_write_to_disk(path, content, content_len, false, false);
|
||||
|
||||
struct stat st;
|
||||
stat(path, &st);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
static void test_chunk_deserialize_truncated() {
|
||||
char* path = "test_rob_trunc.txt";
|
||||
char* content = "hello";
|
||||
to_disk(path, content, strlen(content), false, false);
|
||||
file_write_to_disk(path, content, strlen(content), false, false);
|
||||
|
||||
struct stat st;
|
||||
stat(path, &st);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
static void create_test_file(const char* path, const char* content) {
|
||||
(void)to_disk(path, content, strlen(content), false, false);
|
||||
(void)file_write_to_disk(path, content, strlen(content), false, false);
|
||||
}
|
||||
|
||||
static void test_scanner_single_file() {
|
||||
@@ -394,8 +394,9 @@ static void test_parallel_scanner_root_chunks_without_workers() {
|
||||
create_test_file(file1, "a");
|
||||
create_test_file(file2, "b");
|
||||
|
||||
ParallelScanner* scanner = parallel_scanner_create(dir, false, 1, NULL, 0, NULL, 0, 0, 0, 0, 0,
|
||||
false, false, false, false, false);
|
||||
ScannerOptions options = {false, 1, NULL, 0, NULL, 0, 0, 0,
|
||||
0, 0, false, false, false, false, false};
|
||||
ParallelScanner* scanner = parallel_scanner_create_with_options(dir, &options);
|
||||
EXPECT_NOT_NULL(scanner);
|
||||
|
||||
int total_files = 0;
|
||||
|
||||
Reference in New Issue
Block a user