On Mon, May 20, 2024 at 7:03 AM Nathan Hartman <hartman.nat...@gmail.com> wrote: > > On Sun, May 19, 2024 at 4:09 PM Timofey Zhakov <t...@chemodax.net> wrote: > > > > Hi, > > > > I found a little bug in parsing a change revision: If the number, > > given to the --change argument, starts with a double minus or with > > `-r-`, the command aborts. This patch fixes this bug. > > > > Steps to reproduce: > > > > $ svn diff https://svn.apache.org/repos/asf -c --123 > > svn: E235000: In file '..\..\..\subversion\libsvn_client\ra.c' line > > 692: assertion failed (SVN_IS_VALID_REVNUM(start_revnum)) > > > > Or... > > > > $ svn diff https://svn.apache.org/repos/asf -c -r-123 > > svn: E235000: In file '..\..\..\subversion\libsvn_client\ra.c' line > > 692: assertion failed (SVN_IS_VALID_REVNUM(start_revnum)) > > > > The same would happen if the svn diff command is invoked from a > > working copy, without URL. > > > > [[[ > > Fix bug: check the change argument for a double minus at the start. > > > > If changeno is negative and is_negative is TRUE, raise > > SVN_ERR_CL_ARG_PARSING_ERROR, because string with a double minus is > > not a valid number. > > > > * subversion/svn/svn.c > > (sub_main): If changeno is negative and is_negative is TRUE, raise > > SVN_ERR_CL_ARG_PARSING_ERROR. > > * subversion/tests/cmdline/diff_tests.py > > (diff_invalid_change_arg): New test. > > (test_list): Run new test. > > ]]] > > > > Best regards, > > Timofei Zhakov > > > Good catch! I agree we should issue a proper error and not assert. > > While studying this change, I noticed a second similar bug if we are > given a range and the second value is negative. > > In other words, this works correctly: > > $ svn diff -c r1917671-1917672 > http://svn.apache.org/repos/asf/subversion/trunk > > But this doesn't; notice the double minus signs: > > $ svn diff -c r1917671--1917672 > http://svn.apache.org/repos/asf/subversion/trunk > svn: E235000: In file 'subversion/libsvn_client/ra.c' line 682: > assertion failed (SVN_IS_VALID_REVNUM(start_revnum)) > Abort trap: 6 > > The first minus sign is correctly interpreted to indicate a range, but > the second minus sign is read by strtol(). That's several lines above > your change in svn.c (line 2379 on trunk@1917826). We are doing: > > changeno_end = strtol(s, &end, 10); > > but we are not checking if 'changeno_end' is negative (which it isn't > allowed to be). > > I'm okay to commit this patch now and handle the second bug in a > follow-up, or handle both bugs together. Let me know what you prefer. > > Cheers, > Nathan
Thank you for your response! I didn't notice the second bug. I think it would be better to commit them together, so I fixed and added it to the new patch. The patch is in the attachments. Here is an updated log message: [[[ Fix bug: check the change argument for a double minus. If the changeno is negative and is_negative is TRUE, raise SVN_ERR_CL_ARG_PARSING_ERROR, because string with a double minus is not a valid number. Do the same if the changeno_end is negative. * subversion/svn/svn.c (sub_main): If the changeno is negative and is_negative is TRUE, raise SVN_ERR_CL_ARG_PARSING_ERROR. Do the same if the changeno_end is negative. * subversion/tests/cmdline/diff_tests.py (diff_invalid_change_arg): New test. (test_list): Run new test. ]]] Additionally, I am thinking about moving the code, which parses a change revision, into a function in the opt.c file, like svn_opt_parse_revision_to_range. Thanks!
Index: subversion/svn/svn.c =================================================================== --- subversion/svn/svn.c (revision 1917823) +++ subversion/svn/svn.c (working copy) @@ -2377,6 +2377,15 @@ sub_main(int *exit_code, int argc, const char *arg while (*s == 'r') s++; changeno_end = strtol(s, &end, 10); + + if (changeno_end < 0) + { + return svn_error_createf( + SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("Negative number in range (%s)" + " not supported with -c"), + change_str); + } } if (end == change_str || *end != '\0') { @@ -2391,6 +2400,14 @@ sub_main(int *exit_code, int argc, const char *arg _("There is no change 0")); } + /* The revision number cannot contain a double minus */ + if (changeno < 0 && is_negative) + { + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("Non-numeric change argument " + "(%s) given to -c"), change_str); + } + if (is_negative) changeno = -changeno; Index: subversion/tests/cmdline/diff_tests.py =================================================================== --- subversion/tests/cmdline/diff_tests.py (revision 1917823) +++ subversion/tests/cmdline/diff_tests.py (working copy) @@ -5329,7 +5329,37 @@ def diff_nonexistent_in_wc(sbox): svntest.actions.run_and_verify_svn(expected_output_head_base, [], 'diff', '-r', '1') +def diff_invalid_change_arg(sbox): + "invalid change argument" + sbox.build() + + svntest.actions.run_and_verify_svn( + None, + (r'.*svn: E205000: Non-numeric change argument \(--1\) given to -c'), + 'diff', sbox.wc_dir, '-c', '--1') + + svntest.actions.run_and_verify_svn( + None, + (r'.*svn: E205000: Non-numeric change argument \(-r-1\) given to -c'), + 'diff', sbox.wc_dir, '-c', '-r-1') + + svntest.actions.run_and_verify_svn( + None, + (r'.*svn: E205000: Negative number in range \(1--3\) not supported with -c'), + 'diff', sbox.wc_dir, '-c', '1--3') + + # 'r' is not a number + svntest.actions.run_and_verify_svn( + None, + (r'.*svn: E205000: Non-numeric change argument \(r1--r3\) given to -c'), + 'diff', sbox.wc_dir, '-c', 'r1--r3') + + svntest.actions.run_and_verify_svn( + None, + (r'.*svn: E205000: Negative number in range \(r1-r-3\) not supported with -c'), + 'diff', sbox.wc_dir, '-c', 'r1-r-3') + ######################################################################## #Run the tests @@ -5431,6 +5461,7 @@ test_list = [ None, diff_file_replaced_by_symlink, diff_git_format_copy, diff_nonexistent_in_wc, + diff_invalid_change_arg, ] if __name__ == '__main__':