[3.0] Widens the report comment column to fit an entity encoded report - #9616
Open
albertlast wants to merge 1 commit into
Open
[3.0] Widens the report comment column to fit an entity encoded report#9616albertlast wants to merge 1 commit into
albertlast wants to merge 1 commit into
Conversation
Reporting a post stores the comment with HTML entities in place of the characters that need them, so a double quote costs six characters, an ampersand five and an angle bracket four. The form allows 254 characters and the column held 255, which leaves no room at all for that: a report that quotes the post it is about, or pastes a link with a query string, overflows the column and the insert fails with "Data too long for column 'comment'" on MySQL, or "value too long for type character varying(255)" on PostgreSQL. The report row is written before the comment is, so the failure also leaves a report behind with no comment on it and no notification sent. Makes the column a text column, which holds the encoded form of anything the form's own length check lets through. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Reported on the community forum: a member of a Swedish forum wrote a longish
comment when reporting a post and got
Line 310 in 2.1.7 is the insert into
log_reported_comments. The same defect isin 3.0, at
ReportToMod::reportMsg()andReportToMod::reportMember().What goes wrong
The report form allows 254 characters, and the check that enforces that is
entityStrlen()isgrapheme_strlen(entityDecode($string)), so it counts thecharacters the member typed. That is the right thing for a form limit, and the
round trip through
htmlspecialchars()is deliberate: it stops someone wholiterally types
…from having those eight characters counted as one.But what gets stored is the entity encoded string, and every character that
needs an entity grows. A double quote becomes
", six characters. Anampersand becomes
&, five. An angle bracket becomes<, four. Thecolumn was
varchar(255), one character wider than the form limit, so there wasno room for any of that expansion at all.
Measured against the real
Utilsmethods:"&"So it does not take anything exotic. A report that quotes the post it is about,
or pastes the link to it, is enough.
Both engines reject it rather than truncating, and both are reachable in a
default install — MySQL 8.4 ships
STRICT_TRANS_TABLESinsql_mode, and SMFonly calls
setSqlMode('strict')during an upgrade, so normal requests inheritthe server default:
It also leaves a mess behind.
reportMsg()inserts thelog_reportedrowfirst and that commits, then the comment insert fatals. The moderators are left
with a report that has no comment attached and no
MsgReport_Notifytaskqueued, so nobody is told about it.
On a server with strict mode off you get the other failure instead: the comment
is silently cut at 255 characters, in the middle of an entity, leaving a tail
like
&qu.The fix
Make
log_reported_comments.commentatextcolumn, so it holds the encodedform of anything the form's own length check lets through. The 254 character
limit the member sees is unchanged, and it now means what it says.
The check in
ReportToModis left alone. It is correct as a statement of theform limit; it was only ever wrong to size the column to it.
Nothing reads the column in a way a
texttype changes — there is no index onit, and the four queries that select it (
ReportedContent,RepairBoards) areplain selects with no
DISTINCT,GROUP BYorORDER BYon the column.Verification
Done in the Docker environment on both engines, since this is a schema change.
varchar(255)column:isCandidate()true,execute()altersit to
textwith the default dropped. MySQL and PostgreSQL both.isCandidate()false, so the upgrader skips it. Forcingexecute()a second time is harmless and leaves the column as it is. MySQL andPostgreSQL both.
both, so the
textcolumn is valid in aCREATE TABLEas well as anALTER TABLE. (Atextcolumn takes no default on MySQL, hence thedrop_defaultin the migration.)characters once encoded — now inserts through SMF's own
Db::$db->insert()with the column list
ReportToModuses, and reads back byte for byte on bothengines.
composer lintandvendor/bin/phpunit(280 tests, 495 assertions) pass.On tests
No unit test accompanies this. The change is not reachable from the suite:
Schema\Column::__construct()callsDb::$db->calculate_type(), so the schemaclasses cannot be instantiated without a database connection, and the length
check on the other side of the bug lives in
ReportToMod::submit(), which needsa session and a database too. Faking either is not worth it. The verification
above was done against real MySQL and PostgreSQL instead.
Note on the Swedish forum it was reported from
Worth saying, since it is the obvious first guess:
å,äandöare not thecause.
varchar(255)counts characters and not bytes on both engines — 254åstore fine as 254 characters and 508 bytes — and the constructor normalises to
NFC, so a decomposed
a+ combining ring from an Apple keyboard is composedbefore anything measures it. Swedish typographic quotes (
”, U+201D) are notentity encoded either. It is the ASCII
",&and<that cost.Issues References (Fixes|Related|Closes)
🤖 Generated with Claude Code