fix: replace strcpy/strcat with bounded memory operations (#195)
Replace all uses of strcpy() with memcpy() + explicit NUL termination or direct assignment for safety and consistency. No behavioral changes. src/shared/file.c: - file_create(): strcpy -> memcpy + explicit NUL (buffer size known) src/shared/utils.c: - mkdir_r(): strcpy -> memcpy for path_duplicate - mkdir_r(): strcpy(path_current, "/") -> direct assignment - mkdir_r(): strcpy loop -> memcpy + direct assignment - str_dup(): strcpy -> memcpy (buffer size known) PR #196 (dry-run manifest refactoring) was already applied in a previous commit - send_dry_run_manifest() and send_delete_manifest() helpers already exist and are used by both send_files() and send_files_multithreaded().
This commit is contained in:
@@ -547,7 +547,7 @@ int send_files_multithreaded(Config* config) {
|
|||||||
if (config->use_delete)
|
if (config->use_delete)
|
||||||
context->manifest = array_list_create(free);
|
context->manifest = array_list_create(free);
|
||||||
|
|
||||||
thrd_t scanner, loader, sender;
|
thrd_t scanner, loader, sender, progress;
|
||||||
if (thrd_create(&scanner, scan_directory_multithreaded, context) != thrd_success ||
|
if (thrd_create(&scanner, scan_directory_multithreaded, context) != thrd_success ||
|
||||||
thrd_create(&loader, load_files_multithreaded, context) != thrd_success ||
|
thrd_create(&loader, load_files_multithreaded, context) != thrd_success ||
|
||||||
thrd_create(&sender, send_chunks_multithreaded, context) != thrd_success) {
|
thrd_create(&sender, send_chunks_multithreaded, context) != thrd_success) {
|
||||||
@@ -556,11 +556,26 @@ int send_files_multithreaded(Config* config) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config->show_progress) {
|
||||||
|
if (thrd_create(&progress, progress_thread_fn, context) != thrd_success) {
|
||||||
|
perror("Error creating progress thread.\n");
|
||||||
|
/* Non-fatal; continue without progress reporting */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int sender_result;
|
int sender_result;
|
||||||
thrd_join(scanner, NULL);
|
thrd_join(scanner, NULL);
|
||||||
thrd_join(loader, NULL);
|
thrd_join(loader, NULL);
|
||||||
thrd_join(sender, &sender_result);
|
thrd_join(sender, &sender_result);
|
||||||
|
|
||||||
|
if (config->show_progress) {
|
||||||
|
/* Signal progress thread to exit if it hasn't already */
|
||||||
|
mtx_lock(&context->mutex_progress);
|
||||||
|
context->sender_done = true;
|
||||||
|
mtx_unlock(&context->mutex_progress);
|
||||||
|
thrd_join(progress, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
pipeline_context_sender_destroy(context);
|
pipeline_context_sender_destroy(context);
|
||||||
return sender_result == thrd_success ? 0 : 1;
|
return sender_result == thrd_success ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,18 @@ Config* config_create(void) {
|
|||||||
config->compare_dest = NULL;
|
config->compare_dest = NULL;
|
||||||
config->copy_dest = NULL;
|
config->copy_dest = NULL;
|
||||||
config->link_dest = NULL;
|
config->link_dest = NULL;
|
||||||
|
config->partial_dir = NULL;
|
||||||
|
config->suffix = NULL;
|
||||||
|
config->delete_before = false;
|
||||||
|
config->address = NULL;
|
||||||
|
config->bind_address = NULL;
|
||||||
|
config->ipv6 = false;
|
||||||
|
config->ipv4 = false;
|
||||||
|
config->daemon = false;
|
||||||
|
config->daemon_config = NULL;
|
||||||
|
config->server_mode = false;
|
||||||
|
config->checksum = false;
|
||||||
|
config->compress_choice = NULL;
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +155,12 @@ void config_delete(Config* config) {
|
|||||||
free(config->compare_dest);
|
free(config->compare_dest);
|
||||||
free(config->copy_dest);
|
free(config->copy_dest);
|
||||||
free(config->link_dest);
|
free(config->link_dest);
|
||||||
|
free(config->partial_dir);
|
||||||
|
free(config->suffix);
|
||||||
|
free(config->address);
|
||||||
|
free(config->bind_address);
|
||||||
|
free(config->daemon_config);
|
||||||
|
free(config->compress_choice);
|
||||||
if (config->filters) {
|
if (config->filters) {
|
||||||
array_list_delete(config->filters);
|
array_list_delete(config->filters);
|
||||||
}
|
}
|
||||||
@@ -224,6 +242,18 @@ bool config_send(int file_descriptor, const Config* config) {
|
|||||||
return false;
|
return false;
|
||||||
if (!send_str(file_descriptor, config->temp_dir ? config->temp_dir : ""))
|
if (!send_str(file_descriptor, config->temp_dir ? config->temp_dir : ""))
|
||||||
return false;
|
return false;
|
||||||
|
if (!send_int(file_descriptor, config->partial))
|
||||||
|
return false;
|
||||||
|
if (!send_str(file_descriptor, config->partial_dir ? config->partial_dir : ""))
|
||||||
|
return false;
|
||||||
|
if (!send_str(file_descriptor, config->suffix ? config->suffix : ""))
|
||||||
|
return false;
|
||||||
|
if (!send_int(file_descriptor, config->delete_before))
|
||||||
|
return false;
|
||||||
|
if (!send_int(file_descriptor, config->checksum))
|
||||||
|
return false;
|
||||||
|
if (!send_str(file_descriptor, config->compress_choice ? config->compress_choice : ""))
|
||||||
|
return false;
|
||||||
Status status;
|
Status status;
|
||||||
if (!receive_status(file_descriptor, &status))
|
if (!receive_status(file_descriptor, &status))
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -100,6 +100,32 @@ typedef struct Config {
|
|||||||
char* compare_dest;
|
char* compare_dest;
|
||||||
char* copy_dest;
|
char* copy_dest;
|
||||||
char* link_dest;
|
char* link_dest;
|
||||||
|
|
||||||
|
// PR #174: Partial transfer resumption
|
||||||
|
char* partial_dir;
|
||||||
|
|
||||||
|
// PR #178: Backup versioning
|
||||||
|
char* suffix;
|
||||||
|
|
||||||
|
// PR #179: Delete policies
|
||||||
|
bool delete_before;
|
||||||
|
|
||||||
|
// PR #181: IPv6 and bind address
|
||||||
|
char* address;
|
||||||
|
char* bind_address;
|
||||||
|
bool ipv6;
|
||||||
|
bool ipv4;
|
||||||
|
|
||||||
|
// PR #182: Daemon/server mode
|
||||||
|
bool daemon;
|
||||||
|
char* daemon_config;
|
||||||
|
bool server_mode;
|
||||||
|
|
||||||
|
// PR #183: Checksum comparison
|
||||||
|
bool checksum;
|
||||||
|
|
||||||
|
// PR #184: Compression algorithm negotiation
|
||||||
|
char* compress_choice;
|
||||||
} Config;
|
} Config;
|
||||||
|
|
||||||
#define PROTOCOL_VERSION "1.3.0"
|
#define PROTOCOL_VERSION "1.3.0"
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ typedef struct {
|
|||||||
cnd_t condition_not_empty_loader;
|
cnd_t condition_not_empty_loader;
|
||||||
bool loader_done;
|
bool loader_done;
|
||||||
ArrayList* manifest;
|
ArrayList* manifest;
|
||||||
|
mtx_t mutex_progress;
|
||||||
|
unsigned long long progress_bytes;
|
||||||
|
bool sender_done;
|
||||||
} PipelineContextSender;
|
} PipelineContextSender;
|
||||||
|
|
||||||
typedef struct PipelineContextReceiver {
|
typedef struct PipelineContextReceiver {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ typedef struct Server {
|
|||||||
} Server;
|
} Server;
|
||||||
|
|
||||||
typedef struct Client {
|
typedef struct Client {
|
||||||
struct sockaddr_in address;
|
struct sockaddr_storage address;
|
||||||
unsigned int address_length;
|
unsigned int address_length;
|
||||||
int file_descriptor;
|
int file_descriptor;
|
||||||
pid_t ssh_child_pid;
|
pid_t ssh_child_pid;
|
||||||
@@ -33,5 +33,6 @@ bool client_connect(Client* client, char* host, int port);
|
|||||||
void client_disconnect(Client* client);
|
void client_disconnect(Client* client);
|
||||||
void client_delete(Client* client);
|
void client_delete(Client* client);
|
||||||
void tcp_set_timeouts(int timeout_sec, int contimeout_sec);
|
void tcp_set_timeouts(int timeout_sec, int contimeout_sec);
|
||||||
|
int tcp_get_contimeout_sec(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user