Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F584963
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/maintenance/cleanupBlocks.php b/maintenance/cleanupBlocks.php
index c9f8af43af7..56a8f47851e 100644
--- a/maintenance/cleanupBlocks.php
+++ b/maintenance/cleanupBlocks.php
@@ -1,6 +1,7 @@
<?php
use MediaWiki\Maintenance\Maintenance;
+use Wikimedia\IPUtils;
require_once __DIR__ . '/Maintenance.php';
@@ -18,6 +19,7 @@ class CleanupBlocks extends Maintenance {
$this->deleteOrphanBlockTargets();
$this->deleteTargetlessBlocks();
+ $this->normalizeAddresses();
$this->mergeDuplicateBlockTargets();
$this->fixTargetCounts();
}
@@ -127,6 +129,88 @@ class CleanupBlocks extends Maintenance {
$this->output( $affected ? "OK\n" : "no rows affected\n" );
}
+ /**
+ * Fix IP address normalization issues:
+ * - Leading zeroes like 1.1.1.001
+ * - Lower-case IPv6 addresses like 200e::
+ * - Non-zero range suffixes like 1.1.1.111/24
+ */
+ private function normalizeAddresses() {
+ $dbr = $this->getReplicaDB();
+ $dbType = $dbr->getType();
+ if ( $dbType !== 'mysql' ) {
+ $this->output( "Skipping IP address normalization: not implemented on $dbType\n" );
+ return;
+ }
+ $res = $dbr->newSelectQueryBuilder()
+ ->select( [ 'bt_id', 'bt_address' ] )
+ ->from( 'block_target' )
+ ->where( [ 'bt_user' => null ] )
+ ->andWhere( 'bt_range_start IS NOT NULL OR ' .
+ 'bt_address RLIKE \'(^|[.:])0[0-9]|[a-f]|::\'' )
+ ->caller( __METHOD__ )
+ ->fetchResultSet();
+ $writeDone = false;
+ foreach ( $res as $row ) {
+ $addr = $row->bt_address;
+ if ( IPUtils::isValid( $addr ) ) {
+ $norm = IPUtils::sanitizeIP( $addr );
+ } elseif ( IPUtils::isValidRange( $addr ) ) {
+ $norm = IPUtils::sanitizeRange( $addr );
+ } else {
+ continue;
+ }
+ if ( $addr !== $norm && is_string( $norm ) ) {
+ $this->normalizeAddress( (int)$row->bt_id, $addr, $norm );
+ $writeDone = true;
+ }
+ }
+ if ( $writeDone ) {
+ // Ensure that mergeDuplicateBlockTargets() sees our changes
+ $this->waitForReplication();
+ }
+ }
+
+ /**
+ * Normalize the IP address in a single block_target row
+ *
+ * @param int $targetId
+ * @param string $address
+ * @param string $normalizedAddress
+ */
+ private function normalizeAddress( int $targetId, string $address, string $normalizedAddress ) {
+ $this->output( "Normalizing bt_id=$targetId $address -> $normalizedAddress: " );
+ if ( $this->dryRun ) {
+ $this->output( "dry run\n" );
+ return;
+ }
+ $dbw = $this->getPrimaryDB();
+ $dbw->startAtomic( __METHOD__ );
+ $primaryAddr = $dbw->newSelectQueryBuilder()
+ ->select( 'bt_address' )
+ ->from( 'block_target' )
+ ->where( [ 'bt_id' => $targetId ] )
+ ->forUpdate()
+ ->caller( __METHOD__ )
+ ->fetchField();
+ if ( $primaryAddr === false ) {
+ $this->output( "missing in primary\n" );
+ return;
+ }
+ if ( $primaryAddr !== $address ) {
+ $this->output( "changed in primary\n" );
+ return;
+ }
+ $dbw->newUpdateQueryBuilder()
+ ->update( 'block_target' )
+ ->set( [ 'bt_address' => $normalizedAddress ] )
+ ->where( [ 'bt_id' => $targetId ] )
+ ->caller( __METHOD__ )
+ ->execute();
+ $dbw->endAtomic( __METHOD__ );
+ $this->output( "done\n" );
+ }
+
/**
* Merge block_target rows referring to the same user, IP address or range
*/
diff --git a/tests/phpunit/maintenance/CleanupBlocksTest.php b/tests/phpunit/maintenance/CleanupBlocksTest.php
index 1d4f4f417a6..136d29f2fe5 100644
--- a/tests/phpunit/maintenance/CleanupBlocksTest.php
+++ b/tests/phpunit/maintenance/CleanupBlocksTest.php
@@ -2,7 +2,10 @@
namespace MediaWiki\Tests\Maintenance;
+use MediaWiki\Block\AnonIpBlockTarget;
use MediaWiki\Block\DatabaseBlock;
+use MediaWiki\Block\RangeBlockTarget;
+use MediaWiki\MainConfigNames;
use MediaWiki\User\UserIdentityValue;
/**
@@ -25,6 +28,9 @@ class CleanupBlocksTest extends MaintenanceBaseTestCase {
'by' => new UserIdentityValue( 100, 'Admin' ),
'address' => '127.0.0.1',
];
+ if ( isset( $options['target'] ) ) {
+ unset( $options['address'] );
+ }
return $this->getServiceContainer()->getDatabaseBlockStore()
->insertBlockWithParams( $options );
}
@@ -68,6 +74,42 @@ class CleanupBlocksTest extends MaintenanceBaseTestCase {
->assertFieldValues( [ (string)$block1->getId() ] );
}
+ public function testNormalizeAddresses() {
+ if ( $this->getDb()->getType() !== 'mysql' ) {
+ $this->markTestSkipped( 'not implemented on this DBMS' );
+ }
+ $this->insertBlock();
+ $this->insertBlock( [ 'target' => new AnonIpBlockTarget( '1.1.1.001' ) ] );
+ $this->insertBlock( [ 'target' => new AnonIpBlockTarget( '300e:0:0:0:0:0:0:0' ) ] );
+ $this->insertBlock( [
+ 'target' => new RangeBlockTarget(
+ '2.1.1.111/24',
+ $this->getConfVar( MainConfigNames::BlockCIDRLimit )
+ )
+ ] );
+
+ $this->newSelectQueryBuilder()
+ ->select( 'bt_address' )
+ ->from( 'block_target' )
+ ->assertFieldValues( [
+ '1.1.1.001',
+ '127.0.0.1',
+ '2.1.1.111/24',
+ '300e:0:0:0:0:0:0:0',
+ ] );
+
+ $this->maintenance->execute();
+ $this->newSelectQueryBuilder()
+ ->select( 'bt_address' )
+ ->from( 'block_target' )
+ ->assertFieldValues( [
+ '1.1.1.1',
+ '127.0.0.1',
+ '2.1.1.0/24',
+ '300E:0:0:0:0:0:0:0',
+ ] );
+ }
+
public function testMergeDuplicateBlockTargets() {
$block1 = $this->insertBlock();
$b1 = $block1->getId();
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Jul 5, 5:31 AM (11 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
227435
Default Alt Text
(5 KB)
Attached To
Mode
rMW mediawiki
Attached
Detach File
Event Timeline
Log In to Comment