[3.0] Reserve the names on the reserved names list - #9484
Merged
Sesquipedalian merged 2 commits intoAug 29, 2026
Merged
Conversation
A fresh forum reserves nothing. Admin, Webmaster, Guest and root are all free to register, and so is every name an admin adds afterwards until they open the settings page and press Save. The default list comes from a language string that spells its separators as the two characters backslash and n. 2.1 fed that into an SQL literal, where both MySQL and PostgreSQL's E'' turned them into newlines. 3.0 defines its schema in PHP and inserts the value as a query parameter, so nothing unescapes it and the whole list is stored as one name that nobody would ever type. checkReservedName() explodes it on "\n" and gets a single element back. The admin page has carried its own str_replace for this since 2.1, so the list has always looked right in the textarea while none of it was in force. Seeds real newlines, and reads either form, so a forum already installed is fixed without having to touch its settings. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
Sesquipedalian
approved these changes
Aug 29, 2026
Co-authored-by: Jon Stovell <jonstovell@gmail.com>
live627
pushed a commit
that referenced
this pull request
Aug 31, 2026
A second sweep of the bug fixes now on release-3.0, in the same spirit as #9511: ask of each one whether the suite can reach it, and write a test where it can. Everything merged since that sweep was looked at, along with the backlog that landed in one batch on the 29th and 30th. Most of it is templates, JavaScript, or PHP that wants Db::$db or User::$me. Four fixes do not. #9484 made SMF\Unicode\SpoofDetector::checkReservedName() split the admin's list on the two characters backslash and n as well as on a real newline. The installer writes the default list with the separators spelled out that way, so splitting on newlines alone gave one long name nobody would type and every reserved name was free to register. #9409 made SMF\Localization\MessageFormatter::formatMessage() flatten a \Stringable argument to its string value. The class skips any argument that is not already a string and hands the intl formatter only the scalar ones, so an object argument reached neither and the member was shown the placeholder. #9453 made SMF\PageIndex remember, across __toString(), that the start value it was handed was out of bounds. fixStart() records that as a side effect of clamping, and __toString() called it again on a value already clamped, so the verdict was always thrown away: page 1 came out as plain text rather than a link, with a "next page" link beside it. #9440 and #9442 both concern a gallery avatar, which is stored as a path under the avatars directory rather than as a URL. Read as a URL, it was worked back to a file from the URL's path, which lands outside the avatar directories; and on a forum at the root of its domain that path is null, so stripping the board URL off it threw a TypeError on every page the member appeared on. Each set was run against the code as it was before its fix, by checking out the single source file at the commit before the merge: - SpoofDetector.php before #9484: one failure, the installer's list. - MessageFormatter.php before #9409: three failures, all the \Stringable cases. The plain string, the number and the no-placeholder message pass either side. - PageIndex.php before #9453: two failures. The four tests covering an ordinary start pass either side, which is what makes them the control. - Avatar.php before #9440: five of six fail, the root-of-domain cases with the TypeError and the subdirectory ones by falling through to default.png. With #9440 but not #9442, four still fail: every gallery avatar becomes the default image. 202 tests, 295 assertions, still under a second. 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
A fresh 3.0 forum reserves nothing.
Admin,Webmaster,Guestandrootareall free to register, and so is anything an admin adds afterwards — until they
open Registration → Reserved Names and press Save, which is the only thing that
ever writes the setting properly.
The stored value on a fresh install:
5C6Eis backslash-n, two characters, not a newline.checkReservedName()doesexplode("\n", …)and gets one element back: the whole list as a single namethat nobody would ever type.
Where it comes from. The default is a language string that spells its
separators that way:
2.1 fed that straight into an SQL literal — plain
'…'for MySQL,E'…'forPostgreSQL — and both engines turned the escapes into newlines on the way in.
3.0 defines its schema in PHP and inserts the value as a query parameter, so
nothing unescapes it. The
strtr()inTable.phpthat survives from 2.1 onlyturns
\nback into\n; it was compensating for the escaping that the SQLliteral then undid, and there is no SQL literal any more.
Why nobody noticed.
Admin/Registration.phphas carriedstr_replace('\n', "\n", …)since 2.1, so the textarea splits the list ontoseparate lines and it looks exactly right. It has just never been in force.
What changes
Seeds real newlines, so a new install is correct.
Reads either form in
checkReservedName(), so a forum that is already installedstarts enforcing its list without the admin having to go and re-save a page they
have no reason to think is broken. That is also why this needs no migration.
Testing
On a forum installed before the change,
?action=signup;sa=usernamecheck;xml:root,WebmasterandGuestcome backvalid="0";r00tandzzznewusercome back
valid="1". Submitting a registration asWebmasteris refused withthe name in the error box. A name not on the list registers as before.
(Read together with #9483, which is what makes the refusal a
valid="0"ratherthan an error page. Each stands alone.)
Issues References (Fixes|Related|Closes)
Related to #7933