Thread (6 messages) 6 messages, 3 authors, 2018-04-26

Re: [PATCH v3] blame: prevent error if range ends past end of file

From: Isabella Stephens <hidden>
Date: 2017-10-27 06:18:31

Possibly related (same subject, not in this thread)

On 27/10/17 12:58 pm, Junio C Hamano wrote:
Isabella Stephens [off-list ref] writes:
quoted
diff --git a/builtin/blame.c b/builtin/blame.c
index 67adaef4d..b5b9db147 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -878,13 +878,13 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 				    nth_line_cb, &sb, lno, anchor,
 				    &bottom, &top, sb.path))
 			usage(blame_usage);
-		if (lno < top || ((lno || bottom) && lno < bottom))
+		if ((lno || bottom) && lno < bottom)
 			die(Q_("file %s has only %lu line",
 			       "file %s has only %lu lines",
 			       lno), path, lno);
 		if (bottom < 1)
 			bottom = 1;
-		if (top < 1)
+		if (top < 1 || lno < top)
 			top = lno;
This section sanity-checks first and then tweaks the values it
allowed to pass the check.  Because it wants to later fix up an
overly large "top" by capping to "lno" (i.e. total line number), the
patch needs to loosen the early sanity-check.  And the "fixed up"
values are never checked if they are sane.

For example, with an empty file (i.e. lno == 0), you can ask "git
blame -L1,-4 ("i.e. "at most four lines, ending at line #1") and the
code silently accepts the input without noticing that the request is
an utter nonsense; "file X has only 0 lines" error is given a chance
to kick in.

There should be an "is the range sensible?" check after all the
tweaking to bottom and top are done, I think.
My mistake. I missed that case. I think this section of code is a little
hard to read because it avoids treating an empty file as a special case. 
Why not do something like this:

  for (range_i = 0; range_i < range_list.nr; ++range_i) {
          long bottom, top;
          if (!lno)
                  die(_("file is empty"));
          if (parse_range_arg(range_list.items[range_i].string,
                              nth_line_cb, &sb, lno, anchor,
                              &bottom, &top, sb.path))
                  usage(blame_usage);
          if (bottom < 1)
                  bottom = 1;
          if (lno < top)
                  top = lno;
          if (top < 0 || lno < bottom)
                   die(Q_("file %s has only %lu line",
                         "file %s has only %lu lines",
                         lno), path, lno);
          bottom--;
          range_set_append_unsafe(&ranges, bottom, top);
          anchor = top + 1;

We'd also need to change parse_range_arg to always make bottom less than top:

-       if (*begin && *end && *end < *begin) {
+       if (*end < *begin) {
                SWAP(*end, *begin);
        }

This also fixes the case where the given range is n,-(n+1) (e.g. -L1,-2). At
the moment that will blame from n to the end of the file. My suggested change
would instead blame the first n lines, which makes a lot more sense IMO.

Happy to leave as is if you aren't happy with this suggestion, however.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help