TheDoctor0 / TheDoctor0/CoDMod
Code review: bugs found in core plugins
Nobody has claimed this yet.
- Dominant language
- Pawn
- Stars
- 17
- Forks
- 7
- PR merge metrics
- No merged PRs in 30d
Description
Code review findings from a full pass over the core plugins. None of these are covered by existing open issues.
High
1. set_user_clip masks by entity index instead of weapon id
cod_mod.sma:5938
while ((weaponId = engfunc(EngFunc_FindEntityByString, weaponId, "classname", weaponName)) != 0) {
if (pev(weaponId, pev_owner) == id && !(excludedWeapons & (1<<weaponId))) set_pdata_int(weaponId, 51, maxClipAmmo[weapon], 4);
}
excludedWeapons is a CSW_* bitmask (cod_mod.sma:52), but weaponId here is an entity index (typically 100+). 1<<entity wraps mod 32, making the exclusion check effectively random. Should be 1<<weapon.
2. cod_market: seller tracked by raw player index
cod_market.sma:158, 250, 306, 316-317
MARKET_OWNER stores the seller's player index in the listing. If the seller disconnects and another player joins into the same slot, the sale payout (cod_set_user_honor(marketItem[MARKET_OWNER], ...)) and notifications go to the wrong player; if the slot is empty, the honor is written to a stale slot and lost on the next join. The purchase confirmation menu also shows the wrong seller name (playerName[marketItem[MARKET_OWNER]]). Needs a get_user_userid() snapshot with validation, or a name-keyed payout.
3. cod_transfer: transfer target tracked by raw player index
cod_transfer.sma:87, 104, 134
transferPlayer[id] is captured when the menu is confirmed, but the honor amount arrives via messagemode later. Only is_user_connected() is checked, so if the target leaves and a different player joins into the slot in the meantime, the honor is transferred to the wrong player.
4. Threaded SQL callbacks apply data by raw player index (id-reuse race)
cod_mod.sma:3776 (load_data_handle), plus the load handlers in cod_stats / cod_honor / cod_clans / cod_accounts
load_data_handle applies query results to playerId[0] with no is_user_connected() and no userid check at all. The other plugins check connectivity but not identity. If a player disconnects during query latency and another connects into the same slot, the wrong player receives the loaded data. load_data also self-retries every second while SQL is down (cod_mod.sma:3761), widening the window. The correct pattern already exists in the codebase (cod_clans.sma:1099/1171 uses get_user_userid).
Related to the #114 redesign, but fixable independently.
Medium
5. cod_stats: inverted min-players gate on revenge/assist rewards
cod_stats.sma:791, 793, 827, 830
if (cvarMinPlayers >= get_playersnum()) cod_add_user_honor(killer, cvarRevengeHonor, true);
Rewards are granted only when the population is at or below cod_min_players - backwards vs. every other gate in the mod (cod_honor.sma:122 and cod_mod.sma use if (get_playersnum() < cvarMinPlayers) return;). On populated servers revenge/assist pay nothing; on near-empty servers (easiest to farm) they pay out. Four occurrences.
6. cod_clans: charsmax() on 2D arrays passes the wrong dimension
cod_clans.sma:116, 118, 1109
get_user_name(id, playerName[id], charsmax(playerName));
cod_sql_string(playerName[id], playerName[id], charsmax(playerName));
formatex(chosenName[id], charsmax(chosenName), userName);
charsmax(playerName) yields the major dimension (32) instead of the row max (31). Since cod_sql_string escapes in place and escaping grows the string, a ~31-char nick containing '/`/" writes one cell past the row into the next player's name slot. cod_stats.sma:150 and cod_honor.sma:103 use the correct charsmax(arr[]) idiom - clans is the outlier.
7. show_help tip roll off-by-one
cod_mod.sma:3093
switch (random_num(1, cvarMinPlayers ? 17 : 16)) {
Cases are 1-16. With cod_min_players set (default), 1-in-17 rolls display no tip at all. With it set to 0, the roll includes case 16, which prints the min-players tip with a nonsensical "0 players" value. Intended cvarMinPlayers ? 16 : 15.
Low
8. message_health clamp is dead code
cod_mod.sma:2667
CS's Health message is one byte, so read_data(1) > 255 can never be true and the intended >255 HUD clamp never fires (e.g. 300 HP displays as 44).
9. Kill exp boundary inconsistent with other rewards
cod_mod.sma:2445 gates kill exp on get_playersnum() > cvarMinPlayers (strictly greater), while bomb plant/defuse/hostage rescue exp use >= (via < ... return). At exactly cod_min_players players, kills award nothing but planting the bomb does.
10. cod_display_fade short overflow for durations >= 8s
cod_mod.sma (_cod_display_fade)
The native multiplies duration * (1<<12) and writes it with write_short; durations >= 8 seconds wrap negative, breaking the fade. In-repo callers pass small values, but the native is public API for class/item plugins.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by selecting one numbered finding and inspect the named Pawn source and line references, especially the existing userid pattern in cod_clans.sma:1099/1171. Reproduce or trace the affected behavior, then verify the focused fix against the corresponding plugin path; this issue contains multiple independent bugs and no tests are named.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- sql
- Domain
- databases, game-dev
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100