fix(esx_identity): keep the accepted name length within the database column - #1825
fix(esx_identity): keep the accepted name length within the database column#1825seltonmt012 wants to merge 2 commits into
Conversation
…column Config.MaxNameLength was 20 while firstname and lastname are varchar(16), and the check used < rather than <=, so names of 17 to 19 characters passed validation and then failed the insert. MariaDB runs with STRICT_TRANS_TABLES by default, so the query aborts with "Data too long for column" instead of truncating. In multichar the insert is what triggers loadESXPlayer through its callback, so the callback never fires: the client is told registration succeeded and then hangs with no character, permanently, on every attempt. The web form only enforces a minimum of three characters, so this is reachable through the shipped UI. Lowering the limit to 16 and comparing with <= makes the accepted length match the column exactly - a 16 character name still fits, 17 is rejected up front with the existing invalid format message. Verified on artifact 25770 with MariaDB. A 17 character first name used to log "Data too long for column 'firstname'" and leave the player stuck; it is now rejected before the query. A 14 character name registers normally and the row is written. Checked separately that varchar(16) accepts exactly 16 characters and rejects 17. Widening the columns to varchar(20) would also work but needs a migration for existing installations, so the validation was aligned to the current schema instead.
There was a problem hiding this comment.
Hi, thank you for your PR.
Instead of still relying on the SQL Max varchar length, can you please modify the table values during runtime? You can achieve it with code like this:
MySQL.ready(function()
local MAX_NAME_LENGTH <const> = Config.MaxNameLength
local column = MySQL.scalar.await([[
SELECT CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'users' AND COLUMN_NAME = 'firstname'
]])
if column == MAX_NAME_LENGTH then return end
local query = ("ALTER TABLE users MODIFY COLUMN firstname VARCHAR(%d), MODIFY COLUMN lastname VARCHAR(%d)"):format(MAX_NAME_LENGTH, MAX_NAME_LENGTH)
local result = MySQL.update.await(query)
if not result then
return ESX.Trace("Failed to update firstname/lastname columns!")
end
ESX.Trace("Successfully updated firstname, lastname columns!")
end)That way, the server owner will not have to modify the SQL varchar length if he wants his names to exceed strings over 16.
…start Follow-up to the review. Instead of the config having to match whatever the database was created with, firstname and lastname are widened to Config.MaxNameLength when the server starts, so raising the limit no longer needs a manual SQL change. Both columns are checked, not only firstname. Only widening is done, never shrinking. Measured on a 50k row users table (156 MB, MariaDB 12.3.2): widening runs in 0.15s because InnoDB applies it instantly, while shrinking cannot use ALGORITHM=INSTANT at all (error 1846) and rebuilds the whole table in 3.5s. On a server without STRICT_TRANS_TABLES the shrink also truncates existing data without complaining - a stored 17 character name came back cut to 16. Leaving the column wider than the config costs nothing, checkNameFormat already enforces the lower value. With the default config of 16 the columns already match, so this runs no query beyond one lookup and changes nothing for existing servers.
|
Added, thanks. Both columns are checked now, not just firstname. One deviation: it only widens, never shrinks. Measured on a 50k row
Also worth mentioning about the snippet: With the default of 16 the columns already match what the SQL ships, so this runs one lookup and nothing else on existing servers unless someone raises the limit. |
A first or last name of 17 to 19 characters passes validation and then fails at the INSERT.
firstnameandlastnamearevarchar(16), butConfig.MaxNameLengthis 20. On top of that the check uses<instead of<=, so the configured limit itself is never reachable. Names in that window get throughcheckNameFormat, the insert is rejected by the database, and in the multicharacter path that insert is what triggersloadESXPlayerthrough its callback. The player is told registration succeeded and then hangs, with nothing else happening.Fixed by lowering the default to 16, matching the column, and by accepting a name of exactly the configured length.
Tested locally on artifact 25770 with MariaDB in strict mode:
17 characters before the change: server log
Data too long for column 'firstname', no row written, player stuck17 characters after: clean validation error, no hang
14 characters after: character created normally
boundary checked separately:
varchar(16)takes exactly 16 and rejects 17My commit messages and PR title follow the Conventional Commits standard.
My changes have been tested locally and function as expected.
My PR does not introduce any breaking changes.
I have provided a clear explanation of what my PR does.