r111701 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r111700‎ | r111701 | r111702 >
Date:23:27, 16 February 2012
Author:tstarling
Status:ok (Comments)
Tags:
Comment:
(bug 34428) Fixed hash mismatch errors in DiffHistoryBlob::patch() by simulating LibXDiff's broken Adler-32 implementation.
Modified paths:
  • /trunk/phase3/RELEASE-NOTES-1.20 (modified) (history)
  • /trunk/phase3/includes/HistoryBlob.php (modified) (history)
  • /trunk/phase3/tests/phpunit/includes/DiffHistoryBlobTest.php (added) (history)

Diff [purge]

Index: trunk/phase3/tests/phpunit/includes/DiffHistoryBlobTest.php
@@ -0,0 +1,36 @@
 2+<?php
 3+
 4+class DiffHistoryBlobTest extends MediaWikiTestCase {
 5+ function setUp() {
 6+ if ( !extension_loaded( 'xdiff' ) ) {
 7+ $this->markTestSkipped( 'The xdiff extension is not available' );
 8+ return;
 9+ }
 10+ if ( !extension_loaded( 'hash' ) && !extension_loaded( 'mhash' ) ) {
 11+ $this->markTestSkipped( 'Neither the hash nor mhash extension is available' );
 12+ return;
 13+ }
 14+ }
 15+
 16+ /**
 17+ * Test for DiffHistoryBlob::xdiffAdler32()
 18+ * @dataProvider provideXdiffAdler32
 19+ */
 20+ function testXdiffAdler32( $input ) {
 21+ $xdiffHash = substr( xdiff_string_rabdiff( $input, '' ), 0, 4 );
 22+ $dhb = new DiffHistoryBlob;
 23+ $myHash = $dhb->xdiffAdler32( $input );
 24+ $this->assertSame( bin2hex( $xdiffHash ), bin2hex( $myHash ),
 25+ "Hash of " . addcslashes( $input, "\0..\37!@\@\177..\377" ) );
 26+ }
 27+
 28+ function provideXdiffAdler32() {
 29+ return array(
 30+ array( '', 'Empty string' ),
 31+ array( "\0", 'Null' ),
 32+ array( "\0\0\0", "Several nulls" ),
 33+ array( "Hello", "An ASCII string" ),
 34+ array( str_repeat( "x", 6000 ), "A string larger than xdiff's NMAX (5552)" )
 35+ );
 36+ }
 37+}
Property changes on: trunk/phase3/tests/phpunit/includes/DiffHistoryBlobTest.php
___________________________________________________________________
Added: svn:eol-style
138 + native
Index: trunk/phase3/includes/HistoryBlob.php
@@ -515,14 +515,11 @@
516516
517517 $header = unpack( 'Vofp/Vcsize', substr( $diff, 0, 8 ) );
518518
519 - # Check the checksum if mhash is available
520 - if ( extension_loaded( 'mhash' ) ) {
521 - $ofp = mhash( MHASH_ADLER32, $base );
522 - if ( $ofp !== substr( $diff, 0, 4 ) ) {
523 - wfDebug( __METHOD__. ": incorrect base checksum\n" );
524 - // Temp patch for bug 34428: don't return false
525 - //return false;
526 - }
 519+ # Check the checksum if hash/mhash is available
 520+ $ofp = $this->xdiffAdler32( $base );
 521+ if ( $ofp !== false && $ofp !== substr( $diff, 0, 4 ) ) {
 522+ wfDebug( __METHOD__. ": incorrect base checksum\n" );
 523+ return false;
527524 }
528525 if ( $header['csize'] != strlen( $base ) ) {
529526 wfDebug( __METHOD__. ": incorrect base length\n" );
@@ -561,6 +558,29 @@
562559 return $out;
563560 }
564561
 562+ /**
 563+ * Compute a binary "Adler-32" checksum as defined by LibXDiff, i.e. with
 564+ * the bytes backwards and initialised with 0 instead of 1. See bug 34428.
 565+ *
 566+ * Returns false if no hashing library is available
 567+ */
 568+ function xdiffAdler32( $s ) {
 569+ static $init;
 570+ if ( $init === null ) {
 571+ // The real Adler-32 checksum of this string is zero, so it
 572+ // initialises the state to the LibXDiff initial value.
 573+ $init = str_repeat( "\xf0", 205 ) . "\xee" . str_repeat( "\xf0", 67 ) . "\x02";
 574+ }
 575+ if ( function_exists( 'hash' ) ) {
 576+ $hash = hash( 'adler32', $init . $s, true );
 577+ } elseif ( function_exists( 'mhash' ) ) {
 578+ $hash = mhash( MHASH_ADLER32, $init . $s );
 579+ } else {
 580+ return false;
 581+ }
 582+ return strrev( $hash );
 583+ }
 584+
565585 function uncompress() {
566586 if ( !$this->mDiffs ) {
567587 return;
Index: trunk/phase3/RELEASE-NOTES-1.20
@@ -29,6 +29,8 @@
3030 * (bug 12021) Added user talk link on Special:Listusers
3131 * (bug 34445) section edit and TOC hide/show links are excluded from selection and
3232 copy/paste on supporting browsers
 33+* (bug 34428) Fixed incorrect hash mismatch errors in the DiffHistoryBlob
 34+ history compression method.
3335
3436 === API changes in 1.20 ===
3537 * (bug 34316) Add ability to retrieve maximum upload size from MediaWiki API.

Follow-up revisions

RevisionCommit summaryAuthorDate
r111706Clarified comment per CR r111701tstarling00:28, 17 February 2012
r111936xdiff_string_rabdiff() appeared in version 1.5.0 of xdiff extension....platonides16:03, 20 February 2012

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r111602Temporary patch for bug 34428tstarling00:35, 16 February 2012
r111603Temp patch for bug 34428, merged from 1.19wmf1 r111602tstarling00:51, 16 February 2012

Comments

#Comment by Aaron Schulz (talk | contribs)   23:50, 16 February 2012
+ // The real Adler-32 checksum of this string is zero, so it
+ // initialises the state to the LibXDiff initial value.

This is confusing, it seems to be saying that the checksum for anything is 0.

#Comment by Tim Starling (talk | contribs)   00:03, 17 February 2012

Because it's unclear what "this string" refers to?

#Comment by Aaron Schulz (talk | contribs)   00:04, 17 February 2012

Yes.

Status & tagging log