On Mon, May 20, 2024 at 7:03 AM Nathan Hartman <[email protected]> wrote:
>
> On Sun, May 19, 2024 at 4:09 PM Timofey Zhakov <[email protected]> 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__':