Skip to content

[Bug] crash when shooting grapple in between closing doors #27

Description

@Niehztog

Hello, this is a really rare incident, but if you're playing CTF with bots, this crash happens surprisingly often. This bug has been present in the original Three-Wave Capture the Flag source code since the beginning and has been carried over to the Yamagi CTF port.

If you shoot the grapple hook between a closing door, the game will make the hook explode but will fail to free its memory properly, leading to a game crash. Getting the timing right is crucial; it took me quite a few attempts to capture the following video.

I recorded this video at the red base on q2ctf6 (.dm2 demo file available on request):
Image

Here is an AI explanation of what is happening:
Crash path (q2ctf6, grapple vs. moving func_door):

  1. Player fires grapple via CTFFireGrapple -> new edict solid=SOLID_BBOX, owner->client->ctf_grapple = grapple.
  2. Mid-flight, SV_Push moves func_door *14; its swept BBOX contains the grapple -> engine calls self->blocked(door, grapple) (g_func.c door_blocked).
  3. door_blocked -> T_Damage(grapple, ..., MOD_CRUSH) -> BecomeExplosion1(grapple) -> G_FreeEdict(grapple) (g_misc.c:475). This path never touches owner->client->ctf_grapple - the stale pointer survives the free.
  4. Same frame, ClientThink -> CTFHook_Fire reads cl->ctf_grapple (still non-NULL) -> CTFGrapplePull(grapple).
  5. First field access in CTFGrapplePull dereferences self->owner->client - but the just-freed edict was zeroed by G_FreeEdict, so self->owner == NULL. Read at NULL+0x54 -> SIGSEGV.

Root cause: G_FreeEdict (and its callers on the mover-blocked path) doesn't clear the back-pointer that CTFGrappleTouch/CTFResetGrapple would have cleared. Only the touch/reset paths maintain that invariant; the blocked path bypasses both.

crash dump (custom compiled yamagi q2 version, addresses won't tell much)

CRASH: exception 0xC0000005 at 0x6C45B43A
  EIP module: game.dll  base=0x6C440000  RVA=0x0001B43A
  gladiator.dll runtime base: 0x6C360000
  AV type  : READ
  AV addr  : 0x00000054  (address that was accessed)
  EAX=0x00000000  EBX=0x00000000  ECX=0x59217B38  EDX=0x00000000
  ESI=0x00000000  EDI=0x00000014  ESP=0x02A3F350  EBP=0x02A3F548
  Stack (ESP-relative):
    [ESP+000] 0x6C5186F7  (game.dll+0xD86F7)
    [ESP+004] 0x6C5186A8  (game.dll+0xD86A8)
    [ESP+008] 0x26B70460
    [ESP+012] 0x00000124
    [ESP+016] 0x6C51F3CD  (game.dll+0xDF3CD)
    [ESP+020] 0x00000000
    [ESP+024] 0x60000000
    [ESP+028] 0x40A17766
    [ESP+032] 0x00000000
    [ESP+036] 0x00000000
    [ESP+040] 0x00000000
    [ESP+044] 0x00000000
    [ESP+048] 0x00000000
    [ESP+052] 0x0106B880  (yquake2.exe+0x26B880)
    [ESP+056] 0x00000000
    [ESP+060] 0x02A3F3A8
    [ESP+064] 0x45373232
    [ESP+068] 0x0000FEC1
    [ESP+072] 0x5BA1D512
    [ESP+076] 0x6C45C0F1  (game.dll+0x1C0F1)
    [ESP+080] 0x6C518829  (game.dll+0xD8829)
    [ESP+084] 0x6C5187FC  (game.dll+0xD87FC)
    [ESP+088] 0x00000010
    [ESP+092] 0x00000005
    [ESP+096] 0x26B70460
    [ESP+100] 0x00000000
    [ESP+104] 0x00000000
    [ESP+108] 0x00000000
    [ESP+112] 0x42000000
    [ESP+116] 0x00000002
    [ESP+120] 0x00000004
    [ESP+124] 0x00000124
    [ESP+128] 0x2563C21C
    [ESP+132] 0x00000000
    [ESP+136] 0x2563C21C
    [ESP+140] 0x6C4D1DF2  (game.dll+0x91DF2)
    [ESP+144] 0x26B70460
    [ESP+148] 0x02A3F440
    [ESP+152] 0x0000001C
    [ESP+156] 0x450BBB33
    [ESP+160] 0x3DCC8000
    [ESP+164] 0x00000013
    [ESP+168] 0xC46DD000
    [ESP+172] 0x45295600
    [ESP+176] 0xC21F8000
    [ESP+180] 0x00000000
    [ESP+184] 0x00000000
    [ESP+188] 0x00000000
    [ESP+192] 0xC46DD000
    [ESP+196] 0x45295600
    [ESP+200] 0xC21F8000
    [ESP+204] 0xC4752000
    [ESP+208] 0x4528E200
    [ESP+212] 0xC21F8000
    [ESP+216] 0xC1800000
    [ESP+220] 0xC1800000
    [ESP+224] 0xC1C00000
    [ESP+228] 0x41800000
    [ESP+232] 0x41800000
    [ESP+236] 0x42000000
    [ESP+240] 0x00000000
    [ESP+244] 0x5BA1D512
    [ESP+248] 0x0000FEC1
    [ESP+252] 0x00000000
  EBP frame:
    [EBP-16] 0x45374200
    [EBP-12] 0x00000003
    [EBP-8] 0x00000000
    [EBP-4] 0x00000000
    [EBP+0] 0x02A3F688
    [EBP+4] 0x6C444ACF  (game.dll+0x4ACF)
    [EBP+8] 0x26B25580
    [EBP+12] 0x02A3F574
    [EBP+16] 0x02A3F584
    [EBP+20] 0x00000000
    [EBP+24] 0x00000000
    [EBP+28] 0x00000000
    [EBP+32] 0x00000000

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions