Fix write error when linter_params has excessively long strings

* The linter write code for linter_tag field and linter_template
   field are constrained by the database schema to 32 characters
   for the tag field and 255 characters for the template field.
   In some anomalous circumstances parsoid can report tag and or
   template fields in the linter_params object that exceed those
   character limits. This code truncates these anomalous strings
   to protect the database update code from a length exceeded
   error.

Bug: T328979
Change-Id: I057ae2e32a9e1a7735b5300409e5693e8db5c764
This commit is contained in:
sbailey 2023-02-06 14:44:34 -08:00
parent e2ce10d548
commit 07046457f0
2 changed files with 50 additions and 0 deletions

View file

@ -40,6 +40,13 @@ class Database {
public const MAX_PER_CAT = 20; public const MAX_PER_CAT = 20;
public const MAX_ACCURATE_COUNT = 20; public const MAX_ACCURATE_COUNT = 20;
/**
* The linter_tag field has a maximum length of 32 characters, linter_template field a maximum of 255 characters
* so to ensure the length is not exceeded, the tag and template strings are truncated a few bytes below that limit
*/
public const MAX_TAG_LENGTH = 30;
public const MAX_TEMPLATE_LENGTH = 250;
/** /**
* @var int * @var int
*/ */
@ -189,7 +196,10 @@ class Database {
$templateInfo = $templateInfo[ 'name' ] ?? ''; $templateInfo = $templateInfo[ 'name' ] ?? '';
} }
} }
$templateInfo = mb_strcut( $templateInfo, 0, self::MAX_TEMPLATE_LENGTH );
$result[ 'linter_template' ] = $templateInfo; $result[ 'linter_template' ] = $templateInfo;
$error->tagInfo = mb_strcut( $error->tagInfo, 0, self::MAX_TAG_LENGTH );
$result[ 'linter_tag' ] = $error->tagInfo ?? ''; $result[ 'linter_tag' ] = $error->tagInfo ?? '';
} }

View file

@ -161,6 +161,46 @@ class RecordLintJobTest extends MediaWikiIntegrationTestCase {
$this->assertEquals( $error[ 'params' ][ 'templateInfo' ][ 'name' ], $template ); $this->assertEquals( $error[ 'params' ][ 'templateInfo' ][ 'name' ], $template );
} }
public function testWriteTagAndTemplateLengthExceeded() {
$this->overrideConfigValue( 'LinterWriteTagAndTemplateColumnsStage', true );
// Verify special case test for write code encountering params with tag and template string lengths exceeded
$tagWithMoreThan30Characters = "center tag exceeding 30 characters";
$tagTruncated = "center tag exceeding 30 charac";
$templateWithMoreThan250Characters = str_repeat( "Template:Echo longer than 250 characters ", 8 );
$templateTruncated = "Template:Echo longer than 250 characters Template:Echo longer than 250 characters " .
"Template:Echo longer than 250 characters Template:Echo longer than 250 characters " .
"Template:Echo longer than 250 characters Template:Echo longer than 250 characters Temp";
$error = [
'type' => 'obsolete-tag',
'location' => [ 0, 10 ],
'params' => [
"name" => $tagWithMoreThan30Characters,
"templateInfo" => [ "name" => $templateWithMoreThan250Characters ]
],
'dbid' => null,
];
$titleAndPage = $this->createTitleAndPage( 'TestPage2' );
$job = new RecordLintJob( $titleAndPage[ 'title' ], [
'errors' => [ $error ],
'revision' => $titleAndPage[ 'revID' ]
] );
$this->assertTrue( $job->run() );
$pageId = $titleAndPage[ 'pageID' ];
$db = new Database( $pageId );
$errorsFromDb = array_values( $db->getForPage() );
$this->assertCount( 1, $errorsFromDb );
$this->assertInstanceOf( LintError::class, $errorsFromDb[0] );
$this->assertEquals( $error[ 'type' ], $errorsFromDb[0]->category );
$this->assertEquals( $error[ 'location' ], $errorsFromDb[0]->location );
$this->assertEquals( $error[ 'params' ], $errorsFromDb[0]->params );
$tag = $this->getTagForPage( $pageId );
$this->assertEquals( $tagTruncated, $tag );
$template = $this->getTemplateForPage( $pageId );
$this->assertEquals( $templateTruncated, $template );
}
/** /**
* @param string $titleText * @param string $titleText
* @param int $namespace * @param int $namespace