Author: rinrab Date: Thu Aug 27 21:10:27 2026 New Revision: 1937538 Log: Fix a potential memory corruption in utf.c:convert_to_stringbuf().
It was decided privatly by the PMC not to treat this as a security issue because this bug is not exploitable in a resonable setup [1]. The only way to actually crash the program would be by something like: [[[ $ python -c 'print( "\x86" * 100000 )' > commit $ svn ci --encoding windows-1251 -F commit # should segfault ]]] The reason be that convert_to_stringbuf allocates twice the amount of memory for dest buffer than src, but it has a retry loop in case the conversion failed which updates the length but does not expand the buffer. This will cause the program to segfault with encodings, in which certain 3-byte wide characters are represented by a single byte. This code has been broken 18 years ago since r869736 (in which svn_stringbuf_ensure() call was removed). * subversion/libsvn_subr/utf.c (convert_to_stringbuf): Call svn_stringbuf_ensure() * subversion/tests/libsvn_subr/utf-test.c (test_utf_cstring_to_utf8_ex2_CVE): New test. (test_funcs): Run new test. [1] https://lists.apache.org/thread/56qkrznbco93ymg1n4lmgzz99bhx0kx9 (private, requires login) Modified: subversion/trunk/subversion/libsvn_subr/utf.c subversion/trunk/subversion/tests/libsvn_subr/utf-test.c Modified: subversion/trunk/subversion/libsvn_subr/utf.c ============================================================================== --- subversion/trunk/subversion/libsvn_subr/utf.c Thu Aug 27 20:39:05 2026 (r1937537) +++ subversion/trunk/subversion/libsvn_subr/utf.c Thu Aug 27 21:10:27 2026 (r1937538) @@ -545,6 +545,7 @@ convert_to_stringbuf(xlate_handle_node_t for all characters in the buffer, 4 is maximum character size (currently) */ + svn_stringbuf_ensure(*dest, buflen); } while (apr_err == APR_SUCCESS && srclen != 0); #endif Modified: subversion/trunk/subversion/tests/libsvn_subr/utf-test.c ============================================================================== --- subversion/trunk/subversion/tests/libsvn_subr/utf-test.c Thu Aug 27 20:39:05 2026 (r1937537) +++ subversion/trunk/subversion/tests/libsvn_subr/utf-test.c Thu Aug 27 21:10:27 2026 (r1937538) @@ -256,6 +256,27 @@ test_utf_cstring_to_utf8_ex2(apr_pool_t return SVN_NO_ERROR; } +static svn_error_t * +test_utf_cstring_to_utf8_ex2_CVE(apr_pool_t *pool) +{ + apr_size_t i; + svn_stringbuf_t *src = svn_stringbuf_create_empty(pool); + svn_stringbuf_t *expected = svn_stringbuf_create_empty(pool); + const char *dest; + + for (i = 0; i < 10000; i++) + { + svn_stringbuf_appendcstr(src, "\xfb"); + svn_stringbuf_appendcstr(expected, "\xe2\x88\x9a"); + } + + SVN_ERR(svn_utf_cstring_to_utf8_ex2(&dest, src->data, "cp866", pool)); + + SVN_TEST_ASSERT(strcmp(dest, expected->data) == 0); + + return SVN_NO_ERROR; +} + /* Test conversion to different codepages from utf8. */ static svn_error_t * test_utf_cstring_from_utf8_ex2(apr_pool_t *pool) @@ -1318,6 +1339,8 @@ test_utf8_align(apr_pool_t *pool) return SVN_NO_ERROR; } + + /* The test table. */ @@ -1332,6 +1355,8 @@ static struct svn_test_descriptor_t test "test last_valid/last_valid2"), SVN_TEST_PASS2(test_utf_cstring_to_utf8_ex2, "test svn_utf_cstring_to_utf8_ex2"), + SVN_TEST_PASS2(test_utf_cstring_to_utf8_ex2_CVE, + "test svn_utf_cstring_to_utf8_ex2 CVE"), SVN_TEST_PASS2(test_utf_cstring_from_utf8_ex2, "test svn_utf_cstring_from_utf8_ex2"), SVN_TEST_PASS2(test_utf_collated_compare,
