Skip to content

fix(plugin): resolve admin group references case-insensitively (#1503) - #1524

Merged
rumblefrog merged 1 commit into
mainfrom
fix/1503-admin-group-case-insensitive
Jul 5, 2026
Merged

rumblefrog merged 1 commit into
mainfrom
fix/1503-admin-group-case-insensitive

Conversation

@rumblefrog

Copy link
Copy Markdown
Member

Summary

Fixes #1503. SourceMod's admin cache matches group names case-sensitively, so a server group defined as admin in sb_admin_groups.cfg but referenced as Admin in sb_admins.cfg fails with a spurious Unknown group "Admin" error and silently drops the admin's group inheritance (flags, immunity). The same drift breaks group-immunity references between groups.

The case mismatch originates upstream of the reader: legacy AMXBans / SourceBans imports, manual DB edits, case-sensitive DB collations, or an older generator build that copied the admin's raw srv_group string instead of the canonical srvgroups.name.

Root cause & scope

FindAdmGroup() (SourceMod native) is case-sensitive and there is no native to enumerate loaded groups. The fix lives in the config reader (sbpp_admcfg), not the generator (sbpp_main):

  • The reader must tolerate a mismatch regardless of its source (config files can be hand-edited, legacy, or from a divergent generator).
  • The generator's in-memory admin path already normalises group names on the canonical srvgroups.name via SQL, so BackupConfigs 0 (in-memory) deployments don't exhibit the drift. Touching the DB-facing generator would add risk without covering the file-based path this issue reports.

Changes

  • sbpp_admcfg.sp — new g_GroupNameMap (StringMap, case-folded name → GroupId) plus helpers LowercaseCopy, RegisterGroupName, and FindAdmGroupInsensitive (exact-case FindAdmGroup first, then the case-folded fallback). Released in OnPluginEnd.
  • sbpp_admcfg/sbpp_admin_groups.sp — register each parsed group's name; clear+repopulate the map on every AdminCache_Groups rebuild so stored GroupIds never outlive the group cache; route group-immunity references through the case-insensitive lookup.
  • sbpp_admcfg/sbpp_admin_users.sp — route the admin group key through the case-insensitive lookup; skip pushing an invalid id after the Unknown group ParseError.

Group creation stays case-sensitive (SourceMod owns that); only references are resolved leniently, and only as a fallback after the exact-case match misses.

Adversarial review

Self-reviewed with an adversarial pass. No blockers. Addressed non-blocking findings: documented the map's freshness invariant (groups always rebuild before admins), clarified the case-collapse ("last one wins") comment, added a maxlength <= 0 guard to LowercaseCopy, noted the ASCII-only CharToLower limitation (benign — non-ASCII bytes pass through identically on both sides), and added explicit map teardown on unload. Confirmed the two-pass immunity parse fully populates the map in pass 1, view_as<GroupId> round-trips cleanly, and the immunity ParseError parity matches upstream.

Test plan

  • spcomp 1.12 compiles sbpp_admcfg.sp clean (exit 0, no warnings) — matches the plugin-build.yml gate.
  • Runtime: define a group admin and an admin referencing Admin; confirm no Unknown group in the SM log and the admin inherits the group's flags/immunity.
  • Regression: matched-case configs and cross-group immunity still resolve; a genuinely-unknown group still logs Unknown group.

SourceMod's admin cache matches group names case-sensitively, so a group
defined as "admin" in sb_admin_groups.cfg but referenced as "Admin" in
sb_admins.cfg (or in a group-immunity line) failed with a spurious
"Unknown group" error and silently dropped the admin's group inheritance.
The case drift comes from legacy AMXBans / SourceBans imports, manual DB
edits, case-sensitive DB collations, or an older generator build.

Fix the config reader (not the generator) since the reader must tolerate a
mismatch regardless of its source, and the generator's in-memory path
already normalises on the canonical srvgroups.name:

- Track parsed server-group names in a StringMap keyed by the case-folded
  name as sb_admin_groups.cfg is read (RegisterGroupName), cleared and
  repopulated on every AdminCache_Groups rebuild so stored GroupIds never
  outlive the group cache they describe.
- Add FindAdmGroupInsensitive: exact-case FindAdmGroup first (covers groups
  from any plugin), then the case-folded map fallback.
- Route the admin "group" key and the group-immunity references through it.
- Skip pushing an invalid id after the "Unknown group" ParseError.

Plugin-reader-only change; sb_main generator and config shape are untouched.
Copilot AI review requested due to automatic review settings July 4, 2026 23:11

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@rumblefrog
rumblefrog added this pull request to the merge queue Jul 5, 2026
Merged via the queue into main with commit 0ddfb14 Jul 5, 2026
1 of 2 checks passed
@rumblefrog
rumblefrog deleted the fix/1503-admin-group-case-insensitive branch July 5, 2026 00:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Server Group Name Case Mismatch

2 participants