Comment

Comment by kazinator

I cannot reproduce this with an installation of GNU patch 2.7.6.

I could be doing something wrong or misunderstanding the bug.

Input files:

  $ cat patch-bug-test
  How
  now
  brown
  cow?
  Now
  is
  the
  time
  for
  all
  good
  men.

  $ cat patch-bug-test-2
  How
  now
  brown
  cow?
  Now
  is
  the
  time
  for
Context diff:

  $ diff -c patch-bug-test patch-bug-test-2
  *** patch-bug-test 2020-08-17 11:39:03.056723058 -0700
  --- patch-bug-test-2 2020-08-17 11:41:46.683095324 -0700
  ***************
  *** 7,12 ****
    the
    time
    for
  - all
  - good
  - men.
  --- 7,9 ----
Apply in reverse to copy of patch-bug-test-2:

  $ cp patch-bug-test-2 patch-bug-test-3
  $ diff -c patch-bug-test patch-bug-test-2 | patch -R patch-bug-test-3
  patching file patch-bug-test-3
The operation is successful and the reverse-patched is now identical to the original:

  $ diff patch-bug-test patch-bug-test-3 
  # no output
I did try it with different numbers of lines removed.

Looking at the code in the GNU version, the function is quite different. That block of code is found, with the comment intact, but there are differences. It looks like this in the GNU patch repository, as of this commit: http://git.savannah.gnu.org/cgit/patch.git/tree/src/pch.c?id...

     if (!chars_read) {
       if (repl_beginning && repl_could_be_missing) {
          repl_missing = true;
          goto hunk_done;
       }
       if (p_max - p_end < 4) {
         strcpy (buf, "  \n");  /* assume blank lines got chopped */
         chars_read = 3;
       } else {
         fatal ("unexpected end of file in patch");
       }
     }
The unpatched FreeBSD one referenced in the article:

   if (len == 0) {
     if (p_max - p_end < 4) {
       /* assume blank lines got chopped */
       strlcpy(buf, "  \n", buf_size);
     } else {
       if (repl_beginning && repl_could_be_missing) {
         repl_missing = true;
         goto hunk_done;
       }
       fatal("unexpected end of file in patch\n");
     }
   }
The order of the tests is reversed, which could make a difference (though obviously only in the case when repl_beginng and repl_could_be_missing are true and the goto is taken). In the oldest baseline that is in the GNU patch repo (2009-dated), it is already this way, so to find the commit which affected this code we would have to look to earlier GNU patch sources.
parent kazinator 6 years ago

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton