Skip to content

BUG: Malformed MD3 with zero/invalid surfaces causes infinite CPU-bound hang instead of graceful rejection #1121

Description

@haze-megatf

Summary

ezQuake version: 3.6.9 Windows x64

OS/device including version:
Windows 10 x64, NVIDIA RTX 5070Ti 4.6.0 NVIDIA 595.71 OpenGL

Describe the bug
ezQuake 3.6.9 can infinite-loop/hang when loading a malformed/corrupt MD3 model. Removing the offending MD3 makes the game load normally.
In my case the offending file is a custom:

Fortress/progs/ammobox.md3

Noesis also cannot render/open this MD3, so the model is likely corrupt. The bug is that ezQuake appears to spin forever instead of rejecting the bad model with an error.

Reproduction

  1. Place the corrupt ammobox.md3 in:
    Fortress/progs/ammobox.md3
  2. Launch ezQuake 3.6.9 with the Fortress mod/assets.
  3. Client hangs during loading.
  4. Remove or rename ammobox.md3.
  5. Client loads normally.

Expected behavior

ezQuake should reject the malformed MD3 and fall back to the original model or print an error, rather than hanging indefinitely.

Actual behavior

Client hangs indefinitely. ProcMon shows file I/O stops. WinDbg shows the main thread burning CPU inside ezQuake.

Debug evidence

ProcMon showed no repeated file I/O loop at the hang point.

WinDbg ~* e !runaway showed the main thread consuming nearly all CPU time:

Thread 0: 0:00:40.468 user time

Other threads were idle or waiting.

Hot stack without PDB symbols:

ezquake_3_6_9+0x1c8142
ezquake_3_6_9+0x1c83db
ezquake_3_6_9+0x1e154c
ezquake_3_6_9+0x10aca9
ezquake_3_6_9+0x10aee3
ezquake_3_6_9+0x10d674
ezquake_3_6_9+0x114bb6
ezquake_3_6_9+0xfc273
ezquake_3_6_9+0xff7e6
ezquake_3_6_9+0x147224
ezquake_3_6_9+0x161c1
ezquake_3_6_9+0x5c562a

The hot instruction was:

ezquake_3_6_9+0x1c8142:
cmp r15d, ecx

The nearby disassembly appears to walk MD3 header/surface fields. It reads values consistent with:

[r13+54h] = numSurfaces
[r13+58h] = numSkins
[r13+64h] = ofsSurfaces

At the hang point, the register dump showed:

r13 = likely MD3 header pointer
r15 = 0
ecx = 1
rax = 0

The surrounding loop appears to jump back when the surface count is <= 0 without advancing the outer skin counter, which may cause an infinite loop for malformed MD3s with zero/invalid surfaces.

Suspected cause

Malformed MD3 model with zero or invalid surfaces is not rejected before skin/surface processing.

Possible fix area:

Validate MD3 header fields before processing skins/surfaces, especially:

numSurfaces <= 0
invalid ofsSurfaces
invalid ofsEnd
invalid surface ofsEnd
surface offset not advancing

Then reject the model gracefully instead of continuing through the loop.

Attachments available

I can provide:
corrupt ammobox.md3
ProcMon CSV/PML
WinDbg output (attached)
full dump if needed, although it is 1.5GB

ezquake-3.6.9-windb-output.txt
ammobox.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions