You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2010/03/03 15:28:38 UTC

svn commit: r918486 - /subversion/trunk/subversion/libsvn_client/patch.c

Author: stsp
Date: Wed Mar  3 14:28:37 2010
New Revision: 918486

URL: http://svn.apache.org/viewvc?rev=918486&view=rev
Log:
Fix various bugs in file seeking and EOF handling in 'svn patch'.

* subversion/libsvn_client/patch.c
  (read_line): Don't increment the current line counter past EOF.
  (seek_to_line): Don't attempt to seek past EOF, fixing an endless loop.
   If the EOF indicator was set before seeking backwards, clear it.
  (match_hunk, scan_for_match, get_hunk_info): Don't clear EOF indicator,
   seek_to_line() does this now. And don't seek past EOF.
  (apply_hunk): If seeking past the hunk's original length fails,
   reject the hunk. Note that since the hunk was already matched
   successfully, this failure is unlikely.
   Add a ### comment about an unrelated bug discovered recently.

Modified:
    subversion/trunk/subversion/libsvn_client/patch.c

Modified: subversion/trunk/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/patch.c?rev=918486&r1=918485&r2=918486&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/patch.c (original)
+++ subversion/trunk/subversion/libsvn_client/patch.c Wed Mar  3 14:28:37 2010
@@ -529,7 +529,8 @@
                                        target->eol_str, FALSE,
                                        target->keywords, FALSE,
                                        result_pool));
-  target->current_line++;
+  if (! target->eof)
+    target->current_line++;
 
   return SVN_NO_ERROR;
 }
@@ -542,11 +543,17 @@
 seek_to_line(patch_target_t *target, svn_linenum_t line,
              apr_pool_t *scratch_pool)
 {
+  svn_linenum_t saved_line;
+  svn_boolean_t saved_eof;
+
   SVN_ERR_ASSERT(line > 0);
 
   if (line == target->current_line)
     return SVN_NO_ERROR;
 
+  saved_line = target->current_line;
+  saved_eof = target->eof;
+
   if (line <= target->lines->nelts)
     {
       svn_stream_mark_t *mark;
@@ -560,7 +567,7 @@
       const char *dummy;
       apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
-      while (target->current_line < line)
+      while (! target->eof && target->current_line < line)
         {
           svn_pool_clear(iterpool);
           SVN_ERR(read_line(target, &dummy, iterpool, iterpool));
@@ -568,6 +575,10 @@
       svn_pool_destroy(iterpool);
     }
 
+  /* After seeking backwards from EOF position clear EOF indicator. */
+  if (saved_eof && saved_line > target->current_line)
+    target->eof = FALSE;
+
   return SVN_NO_ERROR;
 }
 
@@ -644,7 +655,6 @@
         *matched = FALSE;
     }
   SVN_ERR(seek_to_line(target, saved_line, iterpool));
-  target->eof = FALSE;
 
   svn_pool_destroy(iterpool);
 
@@ -705,7 +715,8 @@
             }
         }
 
-      SVN_ERR(seek_to_line(target, target->current_line + 1, iterpool));
+      if (! target->eof)
+        SVN_ERR(seek_to_line(target, target->current_line + 1, iterpool));
     }
   svn_pool_destroy(iterpool);
 
@@ -740,13 +751,19 @@
   else if (hunk->original_start > 0 && target->kind == svn_node_file)
     {
       svn_linenum_t saved_line = target->current_line;
-      svn_boolean_t saved_eof = target->eof;
 
       /* Scan for a match at the line where the hunk thinks it
        * should be going. */
       SVN_ERR(seek_to_line(target, hunk->original_start, scratch_pool));
-      SVN_ERR(scan_for_match(&matched_line, target, hunk, TRUE,
-                             hunk->original_start + 1, fuzz, scratch_pool));
+      if (target->current_line != hunk->original_start)
+        {
+          /* Seek failed. */
+          matched_line = 0;
+        }
+      else
+        SVN_ERR(scan_for_match(&matched_line, target, hunk, TRUE,
+                               hunk->original_start + 1, fuzz, scratch_pool));
+
       if (matched_line != hunk->original_start)
         {
           /* Scan the whole file again from the start. */
@@ -769,7 +786,6 @@
         }
 
       SVN_ERR(seek_to_line(target, saved_line, scratch_pool));
-      target->eof = saved_eof;
     }
   else
     {
@@ -894,6 +910,8 @@
 
   if (target->kind == svn_node_file)
     {
+      svn_linenum_t line;
+
       /* Move forward to the hunk's line, copying data as we go.
        * Also copy leading lines of context which matched with fuzz.
        * The target has changed on the fuzzy-matched lines,
@@ -903,9 +921,16 @@
 
       /* Skip the target's version of the hunk.
        * Don't skip trailing lines which matched with fuzz. */
-      SVN_ERR(seek_to_line(target, target->current_line +
-                             hi->hunk->original_length - (2 * hi->fuzz),
-                           pool));
+      /* ### What if current line is part of hunk context? */
+      line = target->current_line + hi->hunk->original_length - (2 * hi->fuzz);
+      SVN_ERR(seek_to_line(target, line, pool));
+      if (target->current_line != line)
+        {
+          /* Seek failed, reject this hunk. */
+          hi->rejected = TRUE;
+          SVN_ERR(reject_hunk(target, hi, pool));
+          return SVN_NO_ERROR;
+        }
     }
 
   /* Write the hunk's version to the patched result.