mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-09-12 21:28:25 -04:00
rrsync restriction tests, rsync-ssl hostname/CA validation, write-batch quoting/ filter-injection, backup-incremental, delay-updates, variety and xrsync.
55 lines
2.2 KiB
Python
55 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
# Regression test: the generated --write-batch replay script must single-quote
|
|
# every argument -- including an arg that starts with '-' and contains '=' (the
|
|
# write_arg "--opt=" split) -- so shell metacharacters in a path (backtick or
|
|
# $(...) command substitution, redirection, newline, ...) cannot execute when
|
|
# the .sh is run.
|
|
|
|
import os
|
|
import subprocess
|
|
|
|
from rsyncfns import SCRATCHDIR, rmtree, run_rsync, test_fail
|
|
|
|
base = SCRATCHDIR / 'wb-quoting'
|
|
rmtree(base)
|
|
src = base / 'src'
|
|
src.mkdir(parents=True)
|
|
(src / 'f').write_text("hello\n")
|
|
|
|
# Relative paths so a fired substitution writes its sentinel here, where we run
|
|
# the generated replay script.
|
|
os.chdir(base)
|
|
|
|
|
|
def check(label, dest_arg, sentinel_name, *extra):
|
|
sentinel = base / sentinel_name
|
|
if sentinel.exists():
|
|
sentinel.unlink()
|
|
# check=False: a '-'-leading dest after '--' makes the transfer itself fail,
|
|
# but write-batch still emits the .sh (the artifact we care about).
|
|
run_rsync('-a', '--write-batch=B', 'src/', *extra, dest_arg, check=False)
|
|
batch_sh = base / 'B.sh'
|
|
if not batch_sh.exists():
|
|
test_fail(f"{label}: write-batch did not generate the replay script")
|
|
script = batch_sh.read_text()
|
|
# Command substitution in any unquoted token fires during shell word
|
|
# expansion, independent of whether rsync itself runs.
|
|
subprocess.run(['sh', 'B.sh'],
|
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
|
cwd=str(base), env=os.environ.copy())
|
|
if sentinel.exists():
|
|
test_fail(f"{label}: metacharacters executed when the replay script ran:\n{script}")
|
|
|
|
|
|
# Backtick command substitution in a bare path token (the value-quoting path).
|
|
# The body uses only `backtick` and `>` -- neither in the old quote-trigger set.
|
|
check("bare-path", 'd`>PWNED`x/', 'PWNED')
|
|
|
|
# Command substitution in the prefix before '=' of a '-'-leading destination,
|
|
# passed after '--' (exercises the write_arg "--opt=" split). Here `$(` and `)`
|
|
# would be caught by value-quoting, but the prefix bytes bypass it unless the
|
|
# whole arg is quoted.
|
|
check("dash-eq-prefix", '-x$(>PWNED2)=y/', 'PWNED2', '--')
|
|
|
|
print("write-batch-quoting: shell metacharacters in batch paths stay quoted")
|