Skip to content

feat(AscHotPatch): interface hot-patch channel and 0x5BC formatter check (build-gated) - #14

Merged
firstoni-dev merged 4 commits into
mainfrom
feat/hot-patch
Oct 18, 2026
Merged

firstoni-dev merged 4 commits into
mainfrom
feat/hot-patch

Conversation

@firstoni-dev

Copy link
Copy Markdown
Owner

Not in the genuine DLL. Everything here is compiled in only with -DASCENSION_HOT_PATCH=ON (OFF by default), so the exact reconstruction build is unchanged — the default build was rebuilt and contains none of it.

Why

Servers already push interface Lua to the stock client: Fel Commutation (azerothcore-wotlk-coa #8021, DMCK96) and the Manastorm UI fixes (#8046) patch a ChallengeRequirementTypes row over SMSG 0x5BC whose formatter starts with end,, escaping the client's return function(value) %s end template, then fake a challenge 5 criteria completion to make the client compile it. No Ascension opcode is meant to carry interface code. This gives servers a supported channel for clients running this DLL, and closes the formatter route on it.

Design and threat model: AscensionRebirth/HOT_PATCH_DESIGN.md (not in this repo). In short: the server is open source, so payload signing would only protect one operator's players and is not used; the guards limit what a patch can reach rather than who may send one.

What it does

  • SMSG 0x8F0 HOT_PATCH — sized patch id, sized target addon, sized Lua. Guards:
    • source only: no ESC byte, no loadstring, no string.dump (this client's loadstring already refuses bytecode — measured in game — so this is a second layer);
    • 32 KB per patch, 128 KB per Lua session;
    • runs once per (patch id, content hash) per Lua session; an identical resend is reported as duplicate;
    • no target: runs at once with no taint source — the attribution the formatter route gets, measured in game with issecurevariable on a pushed global (1 nil), so existing payloads behave the same on both routes;
    • named target: runs at that addon's ADDON_LOADED with the addon's name as the taint source (0xD4139C), so it gets exactly the trust SMSG 0x94E gave that addon;
    • errors are caught and reported; a patch may return "applied" or "skipped: <reason>".
  • CMSG 0x8F1 after every world entry (u32 protocol version 1, u8 mode) so the server can tell this DLL from the genuine one; CMSG 0x8F2 reports each patch's outcome (ran / applied / deferred / skipped / duplicate / refused-by-player / refused-guard / error, plus detail).
  • Player control: allowed by default; /hotpatch off refuses patches, /hotpatch ask asks once per realm (StaticPopup naming the realm and patch ids), /hotpatch on allows again, /hotpatch lists the session's patches. Stored in WTF\HotPatch.txt.
  • SMSG 0x5BC check: a row is dropped unless every formatter is a single return <expression> over value, literals, operators and the seven functions the shipped table calls (C_Quest.GetTitleByID, SecondsToTime, GetCreatureNameByID, GetMoneyString, C_Item.GetColoredItemName, GetColoredReputationName, GetFactionInfoByID). Implemented as a validator hook in AscDbcPatch (no-op unless a validator is registered).
  • README documents the build option and protocol.

Opcodes 0x8F0–0x8F2 come from an unused run inside the server's extension range, checked against the Ascension opcode list, the CoA server's Opcodes.h and every opcode this DLL registers.

Validation

  • tests/hot_patch_formatter.py: every formatter in the shipped ChallengeRequirementTypes.dbc (22) passes; 20 smuggling shapes are refused. Passes under MSVC (x86) and g++.
  • Both builds (ASCENSION_HOT_PATCH on and off) compile and link; the off build contains none of the hot-patch strings.
  • In game on a local CoA realm with the matching server branch (feat/coa-client-hot-patch, stacked on #8046):
    • ask mode: the per-realm popup appeared, Allow was stored, and the server logged hot patch MANASTORM_UI_FIXES: ran and hot patch FEL_COMMUTATION_WINDOW: ran; both features behaved as on the formatter route;
    • default (allow) mode: no popup, both patches ran;
    • .clientpush reqtype 25 PROBE … (the formatter escape) was refused by the 0x5BC check: nothing ran and the token never registered.
  • Not yet exercised in game: /hotpatch off followed by a relog, Deny in ask mode, a patch with a named target addon.

Server side

The matching server change (capability tracking, per-client route choice, result logging) will be a separate azerothcore-wotlk-coa PR once #8046 merges. Servers that don't know the opcodes are unaffected: the DLL only sends 0x8F1/0x8F2, which such servers ignore, and with the formatter route closed this build simply won't run their pushed Lua.

🤖 Generated with Claude Code

firstoni-dev and others added 4 commits October 17, 2026 19:01
…eck (build-gated)

Not in the original DLL; compiled only with ASCENSION_HOT_PATCH (OFF by default).

- SMSG 0x8F0 runs server-sent interface Lua with guards: source only (no ESC
  byte, loadstring or string.dump), 32 KB per patch / 128 KB per session, run
  once per (patch id, content hash) per Lua session, per-realm consent
  (WTF\HotPatch.txt, /hotpatch on|ask|off), logged and listed by /hotpatch.
  An empty target runs at once with no taint source (as the formatter route
  does); a named target runs at that addon's ADDON_LOADED with its taint.
- CMSG 0x8F1 announces the channel after world entry; CMSG 0x8F2 reports each
  patch's outcome.
- SMSG 0x5BC rows are dropped unless every formatter is one return expression
  over value, literals and the seven functions the shipped table calls
  (AscDbcPatch validator hook). tests/hot_patch_formatter.py checks all 22
  shipped formatters pass and 20 smuggling shapes are refused.

Design: AscensionRebirth/HOT_PATCH_DESIGN.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… to change it

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- intro: Deliberate differences now cover the native logon and hot-patch
  build options and the tooltip insertion fix
- reference regenerated: C_HotPatch bindings, SMSG 0x8F0 and CMSG
  0x8F1/0x8F2 (named in the generator as ours), AscHotPatch module
- AscHotPatch uses literal opcodes like the other modules so the
  generator lists them; AscDbcPatch header mentions SetValidator

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@firstoni-dev
firstoni-dev merged commit 8cafde9 into main Oct 18, 2026
4 checks passed
@firstoni-dev
firstoni-dev deleted the feat/hot-patch branch October 18, 2026 15:26
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.

1 participant