Skip to content

Commit 2ed4c9c

Browse files
committed
Add regression tests for CVE-2024-45720 (Subversion command line argument
injection on Windows platforms). * subversion/tests/cmdline/basic_tests.py (argv_with_best_fit_chars): Added git-svn-id: https://svn.apache.org/repos/asf/subversion/trunk@1921371 13f79535-47bb-0310-9956-ffa450edef68
1 parent b0fde6e commit 2ed4c9c

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

subversion/tests/cmdline/basic_tests.py

+55
Original file line numberDiff line numberDiff line change
@@ -3293,6 +3293,60 @@ def keep_local_reverted_properly(sbox):
32933293
svntest.actions.run_and_verify_status(wc_dir, expected_output)
32943294

32953295

3296+
@SkipUnless(svntest.main.is_os_windows)
3297+
def argv_with_best_fit_chars(sbox):
3298+
"""argv with best fit chars"""
3299+
3300+
import ctypes
3301+
from ctypes import windll, wintypes
3302+
3303+
CP_ACP = 0
3304+
kernel32 = windll.kernel32
3305+
WideCharToMultiByte = kernel32.WideCharToMultiByte
3306+
WideCharToMultiByte.argtypes = [
3307+
wintypes.UINT, wintypes.DWORD, wintypes.LPCWSTR, ctypes.c_int,
3308+
wintypes.LPSTR, ctypes.c_int, wintypes.LPCSTR, wintypes.LPBOOL,
3309+
]
3310+
WideCharToMultiByte.restype = ctypes.c_int
3311+
codepage = kernel32.GetACP()
3312+
3313+
def regexlines(*patterns):
3314+
return svntest.verify.RegexListOutput(list(patterns), match_all=True)
3315+
3316+
def iter_bestfit_chars():
3317+
chars = {b'"': 0, b'\\': 0, b' ': 0}
3318+
for c in range(0x80, 0x10000):
3319+
wcs = ctypes.create_unicode_buffer(chr(c))
3320+
mbcs = ctypes.create_string_buffer(8)
3321+
rc = WideCharToMultiByte(CP_ACP, 0, wcs, len(wcs), mbcs, len(mbcs), None,
3322+
None)
3323+
if rc == 0:
3324+
continue
3325+
mbcs = mbcs.value
3326+
if chars.get(mbcs) != 0:
3327+
continue
3328+
chars[mbcs] = c
3329+
yield chr(c), mbcs
3330+
3331+
count = 0
3332+
expected_stderr = svntest.verify.RegexListOutput(
3333+
[r'^"foo.+bar": unknown command\.\n$', '\n'], match_all=True)
3334+
for wc, mbcs in iter_bestfit_chars():
3335+
count += 1
3336+
logger.info('Code page %r - U+%04x -> 0x%s', codepage, ord(wc), mbcs.hex())
3337+
if mbcs == b'"':
3338+
svntest.actions.run_and_verify_svn2(None, expected_stderr, 0, 'help',
3339+
'foo{0} {0}bar'.format(wc))
3340+
elif mbcs == b'\\':
3341+
svntest.actions.run_and_verify_svn2(None, expected_stderr, 0, 'help',
3342+
'foo{0}" {0}"bar'.format(wc))
3343+
elif mbcs == b' ':
3344+
svntest.actions.run_and_verify_svn2(None, expected_stderr, 0, 'help',
3345+
'foo{0}bar'.format(wc))
3346+
if count == 0:
3347+
raise svntest.Skip('No best fit characters in code page %r' % codepage)
3348+
3349+
32963350
########################################################################
32973351
# Run the tests
32983352

@@ -3369,6 +3423,7 @@ def keep_local_reverted_properly(sbox):
33693423
null_prop_update_last_changed_revision,
33703424
filtered_ls_top_level_path,
33713425
keep_local_reverted_properly,
3426+
argv_with_best_fit_chars,
33723427
]
33733428

33743429
if __name__ == '__main__':

0 commit comments

Comments
 (0)