TheDoctor0 / TheDoctor0/CoDMod

Code review: bugs found in core plugins

Open
#128 0 comments 0 reactions 0 assignees View on GitHub

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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.