From: Geoffrey T. D. <da...@us...> - 2001-02-07 18:34:51
|
Update of /cvsroot/phpwiki/phpwiki/lib In directory usw-pr-cvs1:/tmp/cvs-serv16614/lib Modified Files: diff.php Log Message: Fix bug #131372: diff hangs. The problem had to do with subtleties introduced by the code cleanups to remove the PHP4 warnings. I've now added several assert()'s (only active under PHP4) to perform further sanity checks. Index: diff.php =================================================================== RCS file: /cvsroot/phpwiki/phpwiki/lib/diff.php,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -r1.4 -r1.5 *** diff.php 2000/11/01 11:31:41 1.4 --- diff.php 2001/02/07 18:35:09 1.5 *************** *** 9,12 **** --- 9,18 ---- // + // FIXME: possibly remove assert()'s for production version? + + // PHP3 does not have assert() + define('USE_ASSERTS', function_exists('assert')); + + /** * Class used internally by WikiDiff to actually compute the diffs. *************** *** 35,38 **** --- 41,45 ---- $n_from = sizeof($from_lines); $n_to = sizeof($to_lines); + $endskip = 0; // Ignore trailing and leading matching lines. *************** *** 72,82 **** $xlines[] = $line; if ( ($this->xchanged[$x] = empty($yhash[$line])) ) ! continue; // fixme? what happens to yhash/xhash when ! // there are two identical lines?? $this->xv[] = $line; $this->xind[] = $x; } - // Find the LCS. $this->_compareseq(0, sizeof($this->xv), 0, sizeof($this->yv)); --- 79,87 ---- $xlines[] = $line; if ( ($this->xchanged[$x] = empty($yhash[$line])) ) ! continue; $this->xv[] = $line; $this->xind[] = $x; } // Find the LCS. $this->_compareseq(0, sizeof($this->xv), 0, sizeof($this->yv)); *************** *** 95,107 **** while ($x < $n_from || $y < $n_to) { ! /* ! if ( ($y == $n_to && !$this->xchanged[$x]) ! || ($x == $n_from && !$this->ychanged[$y]) ) ! die("assertion error"); ! */ // Skip matching "snake". $x0 = $x; $ncopy = 0; while ( $x < $n_from && $y < $n_to && !$this->xchanged[$x] && !$this->ychanged[$y]) --- 100,110 ---- while ($x < $n_from || $y < $n_to) { ! USE_ASSERTS && assert($y < $n_to || $this->xchanged[$x]); ! USE_ASSERTS && assert($x < $n_from || $this->ychanged[$y]); // Skip matching "snake". $x0 = $x; $ncopy = 0; + while ( $x < $n_from && $y < $n_to && !$this->xchanged[$x] && !$this->ychanged[$y]) *************** *** 134,138 **** } } ! if (!empty($endskip)) $this->edits[] = $endskip; } --- 137,141 ---- } } ! if ($endskip != 0) $this->edits[] = $endskip; } *************** *** 196,200 **** { $k = $this->_lcs_pos($y); ! //if (!$k) die('assertion "!$k" failed'); $ymids[$k] = $ymids[$k-1]; break; --- 199,203 ---- { $k = $this->_lcs_pos($y); ! USE_ASSERTS && assert($k > 0); $ymids[$k] = $ymids[$k-1]; break; *************** *** 204,208 **** if ($y > $this->seq[$k-1]) { ! //if ($y >= $this->seq[$k]) die('assertion failed'); // Optimization: this is a common case: // next match is just replacing previous match. --- 207,211 ---- if ($y > $this->seq[$k-1]) { ! USE_ASSERTS && assert($y < $this->seq[$k]); // Optimization: this is a common case: // next match is just replacing previous match. *************** *** 214,218 **** { $k = $this->_lcs_pos($y); ! //if (!$k) die('assertion "!$k" failed'); $ymids[$k] = $ymids[$k-1]; } --- 217,221 ---- { $k = $this->_lcs_pos($y); ! USE_ASSERTS && assert($k > 0); $ymids[$k] = $ymids[$k-1]; } *************** *** 254,258 **** } ! //if ($ypos == $this->seq[$end]) die("assertion failure"); $this->in_seq[$this->seq[$end]] = false; --- 257,261 ---- } ! USE_ASSERTS && assert($ypos != $this->seq[$end]); $this->in_seq[$this->seq[$end]] = false; *************** *** 329,333 **** * * We do something when a run of changed lines include a ! * line at one end and have an excluded, identical line at the other. * We are free to choose which identical line is included. * `compareseq' usually chooses the one at the beginning, --- 332,336 ---- * * We do something when a run of changed lines include a ! * line at one end and has an excluded, identical line at the other. * We are free to choose which identical line is included. * `compareseq' usually chooses the one at the beginning, *************** *** 341,345 **** --- 344,352 ---- $i = 0; $j = 0; + + USE_ASSERTS && assert('sizeof($lines) == sizeof($changed)'); $len = sizeof($lines); + $other_len = sizeof($other_changed); + while (1) { *************** *** 347,356 **** * Scan forwards to find beginning of another run of changes. * Also keep track of the corresponding point in the other file. */ ! while ($i < $len && $changed[$i] == 0) { ! while ($other_changed[$j++]) ! continue; ! $i++; } --- 354,374 ---- * Scan forwards to find beginning of another run of changes. * Also keep track of the corresponding point in the other file. + * + * Throughout this code, $i and $j are adjusted together so that + * the first $i elements of $changed and the first $j elements + * of $other_changed both contain the same number of zeros + * (unchanged lines). + * Furthermore, $j is always kept so that $j == $other_len or + * $other_changed[$j] == false. */ ! while ($j < $other_len && $other_changed[$j]) ! $j++; ! ! while ($i < $len && ! $changed[$i]) { ! USE_ASSERTS && assert('$j < $other_len && ! $other_changed[$j]'); ! $i++; $j++; ! while ($j < $other_len && $other_changed[$j]) ! $j++; } *************** *** 361,368 **** // Find the end of this run of changes. ! while (isset($changed[++$i])) continue; - while ($other_changed[$j]) - $j++; do --- 379,384 ---- // Find the end of this run of changes. ! while (++$i < $len && $changed[$i]) continue; do *************** *** 379,390 **** * This merges with previous changed regions. */ ! while ($start && $lines[$start - 1] == $lines[$i - 1]) { $changed[--$start] = 1; $changed[--$i] = false; ! while ($changed[$start - 1]) $start--; while ($other_changed[--$j]) continue; } --- 395,408 ---- * This merges with previous changed regions. */ ! while ($start > 0 && $lines[$start - 1] == $lines[$i - 1]) { $changed[--$start] = 1; $changed[--$i] = false; ! while ($start > 0 && $changed[$start - 1]) $start--; + USE_ASSERTS && assert('$j > 0'); while ($other_changed[--$j]) continue; + USE_ASSERTS && assert('$j >= 0 && !$other_changed[$j]'); } *************** *** 394,398 **** * CORRESPONDING == LEN means no such point has been found. */ ! $corresponding = empty($other_changed[$j - 1]) ? $len : $i; /* --- 412,416 ---- * CORRESPONDING == LEN means no such point has been found. */ ! $corresponding = $j < $other_len ? $i : $len; /* *************** *** 403,414 **** * the changed region is moved forward as far as possible. */ ! while ($i != $len && $lines[$start] == $lines[$i]) { $changed[$start++] = false; $changed[$i++] = 1; ! while ($changed[$i]) $i++; ! while ($other_changed[++$j]) $corresponding = $i; } } --- 421,439 ---- * the changed region is moved forward as far as possible. */ ! while ($i < $len && $lines[$start] == $lines[$i]) { $changed[$start++] = false; $changed[$i++] = 1; ! while ($i < $len && $changed[$i]) $i++; ! ! USE_ASSERTS && assert('$j < $other_len && ! $other_changed[$j]'); ! $j++; ! if ($j < $other_len && $other_changed[$j]) ! { $corresponding = $i; + while ($j < $other_len && $other_changed[$j]) + $j++; + } } } *************** *** 423,428 **** --- 448,455 ---- $changed[--$start] = 1; $changed[--$i] = 0; + USE_ASSERTS && assert('$j > 0'); while ($other_changed[--$j]) continue; + USE_ASSERTS && assert('$j >= 0 && !$other_changed[$j]'); } } *************** *** 482,486 **** { // Was an add, turn it into a delete. $nadd = sizeof($edit); ! if ($nadd == 0) die("assertion error"); $edit = -$nadd; } --- 509,513 ---- { // Was an add, turn it into a delete. $nadd = sizeof($edit); ! USE_ASSERTS && assert ($nadd > 0); $edit = -$nadd; } |