Page MenuHomePhabricator

QueryBuilderFromRawSql::generalizeSQL: PHP Deprecated: preg_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated
Closed, ResolvedPublic

Description

[2024-06-04T18:50:32.533818+00:00] error.WARNING: [0f7af7fe099b730782156d75] /w/api.php?action=query&format=json&list=messagecollection&mcgroup=mediawiki&mclanguage=hr&mcoffset=printableversion-deprecated-warning&mclimit=100&mcfilter=!ignored%7C!optional%7Ctranslated%7C!reviewer%3A38122%7C!last-translator%3A38122&mcprop=definition%7Ctranslation%7Ctags%7Cproperties&rawcontinue=1&errorformat=html&formatversion=2&uselang=en   PHP Deprecated: preg_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated {"exception":"[object] (ErrorException(code: 0): PHP Deprecated: preg_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated at /srv/mediawiki/tags/2024-06-04_12:43:27/includes/libs/rdbms/database/QueryBuilderFromRawSql.php:202)
[stacktrace]
#0 [internal function]: MWExceptionHandler::handleError()
#1 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/libs/rdbms/database/QueryBuilderFromRawSql.php(202): preg_replace()
#2 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/libs/rdbms/database/utils/GeneralizedSql.php(56): Wikimedia\\Rdbms\\QueryBuilderFromRawSql::generalizeSQL()
#3 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/libs/rdbms/TransactionProfiler.php(542): Wikimedia\\Rdbms\\GeneralizedSql->stringify()
#4 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/libs/rdbms/TransactionProfiler.php(524): Wikimedia\\Rdbms\\TransactionProfiler->getGeneralizedSql()
#5 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/libs/rdbms/TransactionProfiler.php(322): Wikimedia\\Rdbms\\TransactionProfiler->reportExpectationViolated()
#6 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/libs/rdbms/database/TransactionManager.php(614): Wikimedia\\Rdbms\\TransactionProfiler->recordQueryCompletion()
#7 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/libs/rdbms/database/Database.php(825): Wikimedia\\Rdbms\\TransactionManager->recordQueryCompletion()
#8 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/libs/rdbms/database/Database.php(716): Wikimedia\\Rdbms\\Database->attemptQuery()
#9 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/libs/rdbms/database/Database.php(643): Wikimedia\\Rdbms\\Database->executeQuery()
#10 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/libs/rdbms/database/Database.php(1352): Wikimedia\\Rdbms\\Database->query()
#11 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/libs/rdbms/database/DBConnRef.php(126): Wikimedia\\Rdbms\\Database->select()
#12 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/libs/rdbms/database/DBConnRef.php(350): Wikimedia\\Rdbms\\DBConnRef->__call()
#13 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/libs/rdbms/querybuilder/SelectQueryBuilder.php(732): Wikimedia\\Rdbms\\DBConnRef->select()
#14 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/Storage/SqlBlobStore.php(410): Wikimedia\\Rdbms\\SelectQueryBuilder->fetchResultSet()
#15 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/Storage/SqlBlobStore.php(303): MediaWiki\\Storage\\SqlBlobStore->fetchBlobs()
#16 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/Revision/RevisionStore.php(2202): MediaWiki\\Storage\\SqlBlobStore->getBlobBatch()
#17 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/Revision/RevisionStore.php(2265): MediaWiki\\Revision\\RevisionStore->getSlotRowsForBatch()
#18 /srv/mediawiki/tags/2024-06-04_12:43:27/extensions/Translate/src/MessageLoading/MessageCollection.php(820): MediaWiki\\Revision\\RevisionStore->getContentBlobsForBatch()
#19 /srv/mediawiki/tags/2024-06-04_12:43:27/extensions/Translate/src/MessageLoading/MessageCollection.php(229): MediaWiki\\Extension\\Translate\\MessageLoading\\MessageCollection->initMessages()
#20 /srv/mediawiki/tags/2024-06-04_12:43:27/extensions/Translate/src/MessageLoading/QueryMessageCollectionActionApi.php(177): MediaWiki\\Extension\\Translate\\MessageLoading\\MessageCollection->loadTranslations()
#21 /srv/mediawiki/tags/2024-06-04_12:43:27/extensions/Translate/src/MessageLoading/QueryMessageCollectionActionApi.php(51): MediaWiki\\Extension\\Translate\\MessageLoading\\QueryMessageCollectionActionApi->run()
#22 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/api/ApiQuery.php(705): MediaWiki\\Extension\\Translate\\MessageLoading\\QueryMessageCollectionActionApi->execute()
#23 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/api/ApiMain.php(1952): ApiQuery->execute()
#24 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/api/ApiMain.php(928): ApiMain->executeAction()
#25 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/api/ApiMain.php(899): ApiMain->executeActionWithErrorHandling()
#26 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/api/ApiEntryPoint.php(158): ApiMain->execute()
#27 /srv/mediawiki/tags/2024-06-04_12:43:27/includes/MediaWikiEntryPoint.php(200): MediaWiki\\Api\\ApiEntryPoint->execute()
#28 /srv/mediawiki/tags/2024-06-04_12:43:27/api.php(44): MediaWiki\\MediaWikiEntryPoint->run()
#29 {main}
","exception_url":"/w/api.php?action=query&format=json&list=messagecollection&mcgroup=mediawiki&mclanguage=hr&mcoffset=printableversion-deprecated-warning&mclimit=100&mcfilter=!ignored%7C!optional%7Ctranslated%7C!reviewer%3A38122%7C!last-translator%3A38122&mcprop=definition%7Ctranslation%7Ctags%7Cproperties&rawcontinue=1&errorformat=html&formatversion=2&uselang=en","reqId":"0f7af7fe099b730782156d75","caught_by":"mwe_handler"} []

Event Timeline

The code is there since 6a475deac8b386b8159952e559104d2e3e0bfed8 and is a chain of preg_replace calls. preg_replace can return null for errors like limit error on backtracking. This is passed to the next preg_replace and fails under php8.1

The query could be a SELECT with a very long IN for old_id containing numbers. The regex is /-?\d+(,-?\d+)+/

You could increase php setting pcre.backtrack_limit or the regex needs adjust

I have it at the default value of 1000000. WMF has it at 5000000 I think.

The query shouldn't be very long IN, I see mclimit=100 in the URL though I am not sure what RevisionStore->getSlotRowsForBatch does.

The pagination is done via offset, so MessageCollection must load more as 100 messages.
For all messages the slot information including the content blob are loaded. getSlotRowsForBatch is a private helper used by getContentBlobsForBatch to load the main slot, but could load other slots in context of MCR as well.

For loading the blobs for translations, we have trimmed the list of messages down to 100 for the limit. Not expecting translations to have multiple slots.

BPirkle triaged this task as Medium priority.Sep 12 2024, 3:28 PM
HCoplin-WMF lowered the priority of this task from Medium to Low.
HCoplin-WMF subscribed.

@aaron -- please confirm this was fixed by related patch: https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1075067 (and update if it doesn't :) )

@aaron -- please confirm this was fixed by related patch: https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1075067 (and update if it doesn't :) )

Looks like it won't help after all, if the problem is regex backtrack limits.

Change #1077087 had a related patch set uploaded (by Aaron Schulz; author: Aaron Schulz):

[mediawiki/core@master] rdbms: avoid pcre.backtrack_limit in QueryBuilderFromRawSql::generalizeSQL()

https://gerrit.wikimedia.org/r/1077087

Change #1077087 merged by jenkins-bot:

[mediawiki/core@master] rdbms: avoid pcre.backtrack_limit in QueryBuilderFromRawSql::generalizeSQL()

https://gerrit.wikimedia.org/r/1077087