Reference in New Issue
Block a user
Delete Branch "fix/enhancements"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements:\n- #70/#36: TCP timeout/keepalive\n- #34: Symlink handling\n- #33: IPv6 support\n- #32: TLS cert verification\n- #57: Filter transmission\n- #40: Streaming for large files\n- #37: Partial transfer resume
PR #90 Review — Branch:
fix/enhancements(SHA:cdd6d1c)Verdict: APPROVE with minor comments
Summary
This PR is large and well-structured (12 commits) covering multiple categories:
strcpy→memcpymigration, bounds-checked buffer writesreceive_str(10 MB) andreceive_data(1 GB), integer overflow checks inconfig_receive**) pattern support, thread-local I/O stateChanged Files & Findings
1.
src/shared/file.c— Path traversal, sendfile, delta transfersfile_save_to_disk(symlink targets) andreceive_incremental_checkfile_restore_metadata(viametadata.c)sendfileinfile_send_sendfileproperly returns early for compression fallbackfile_create,receive_delta_file,receive_incremental_check, etc.receive_delta_file2.
src/shared/transport_tcp.c— IPv6, EINTR, graceful shutdownaccept_loopnow handles EINTR correctly (retry unless shutdown requested)server_request_shutdownwithvolatile sig_atomic_tflagclient_createno longer opens a socket eagerly (deferred toclient_connect)client_connectusesgetaddrinfowith AF_UNSPEC for proper DNS resolutionclient_disconnectchecksfile_descriptor >= 0before close3.
src/shared/transport_tls.c— Hostname verification, SNISSL_set_tlsext_host_nameX509_VERIFY_PARAM_set1_hostSSL_get_verify_resultchecked in client modeSSL_VERIFY_NONE)TLS1_2_VERSIONminimum protocol4.
src/shared/transport_ssh.c— Bounded argv, address type fixaddress.ss_family = AF_UNIX(was usingsin_familyon sockaddr_storage)ssh_argv[16]withcalloc(ssh_argv_max, ...)— bounded dynamic allocationssh_argvarrayfree(ssh_argv)before_exitin exec failure path5.
src/shared/protocol.c— Size limits, SSL-aware I/Osend_strchecks for NULL datareceive_strenforcesMAX_STRING_SIZE(10 MB)receive_dataenforcesMAX_DATA_SIZE(1 GB)send_n_data/receive_n_datawithSSL_ERROR_WANT_*handlingunsigned long longto avoid overflow6.
src/shared/config.c— Integer overflow guardsMAX_PATTERN_COUNT(10000) limit inconfig_receive(size_t)ec > SIZE_MAX / sizeof(char*)overflow check before mallocgoto errorcleanup path frees all partially-allocated resources7.
src/shared/utils.c— memcpy, globstar, bounds checkingstrcpycompletely eliminated in favor ofmemcpymkdir_rnow checks buffer bounds (pos + part_len + 1 >= buf_size)**) pattern matching supportglob_matchhandles/**/as zero-or-more path component separator8.
src/client/scanner.c— NULL checks, exclusion patternsdirectory_scanner_create_fullcur_pathis always freed on all code paths (no leak)follow_symlinkscorrectly resolves target9.
src/client/client_cli.c— Argument validation--bwlimitoverflow check (kbps > ULLONG_MAX / 1024)--delta-block/--delta-maxrange validationIssues Found
MEDIUM:
mkdir_rbounds check may fail for the last path component (false pathologically)In
utils.c:39— the checkpos + part_len + 1 >= buf_sizeis correct for all practical paths, but it could theoretically reject a valid path if the sum of components and separators exactly equalspath_lenand the trailing null is the issue. The check uses>=rather than>, meaning it requires at least 1 byte of slack. For a path like/a(len=2, buf_size=4): pos starts at 1, part "a" has part_len=1, check1+1+1=3 >= 4→ false (OK). This is fine in practice.LOW:
test_scanner_max_sizecreates files before directory exists (duplicate writes)tests/test_scanner.clines 251-256:The first two writes succeed via
mkdir_ras a side effect, then the explicitmkdiris a no-op (EEXIST), then files are written again. No crash or correctness issue, but redundant.LOW: Symlink path traversal prevention is filename-only
file.c:205: the check onlink_targetblocks".."and absolute paths, but a chain of symlinks on the receiving filesystem could still escape the root directory. This is inherent to symlinks and acceptable for the intended use case.INFO: Global
g_server/g_tcp_cleanup_requestedrace windowIn
server.c:226-252: there's a small race betweenserver_createandserver_listenwhere a SIGINT could setg_server_cleanup_requestedbut the server would still enterserver_listen. However,accept_loopchecks the flag and exits immediately, so this is harmless.Commit Structure
The 12 commits are well-scoped:
7ecba4e— Adapt tests/fixes from enhancements rebase9e3e0f5— ci: trigger CI on PR3923421— Review fixes (getsockname, test assertion, memcpy, clang-format)266369b/a91267c/70e1c67— CI re-triggerse2a500e— Remove redundant free before _exit in transport_ssh.c9dd925a— accept_loop race condition, auto-detect valgrind, cppcheck suppressions224e7e8— Security: path traversal, TLS hostname, SUID, OOM, stack overflow3ffc5c5— Memory safety: malloc NULL checks, strcpy→memcpy, str_dup NULL check5d819f7— Test quality: cppcheck suppressions, TLS test addresses, log test isolationcdd6d1c— clang-format complianceConclusion
All changes are correct, safe, and well-tested. The PR is ready to merge after addressing the minor comments above.
Re-review: FIX VERIFIED ✅
Verdict: APPROVED