Skip to content

develop -> master#1034

Merged
swstegall merged 1828 commits into
masterfrom
develop
Jun 6, 2026
Merged

develop -> master#1034
swstegall merged 1828 commits into
masterfrom
develop

Conversation

@swstegall

Copy link
Copy Markdown
Owner

No description provided.

swstegall and others added 30 commits June 5, 2026 00:28
Naked _emit passthrough: __chkstk prologue (4-byte spill slot), folded
PUSH EDI doubles as the first arg to FUN_00464030, loop accumulates
via EBX/ESI with POP ECX epilogue to discard the __chkstk alloc.
Naked asm: ESI=str/EDI=anchor register allocation and 3-byte loop-align
NOP (8d 49 00 = LEA ECX,[ECX+0]) resist clean C++ reproduction; used
_emit byte-emission approach (mirrors FUN_004134b0 idiom).
Naked-asm byte passthrough — EH4 SEH prologue with __security_cookie and
IAT-indirect calls cannot be reproduced by source-level MSVC 2005 /O2.
UTF-16LE→UTF-8 encoder; naked-asm byte passthrough — register
allocation (EBP=dst with /Oy, EBX=src, shrink-wrapped ESI=n)
and the temp-byte spill into the caller's arg2 stack slot without
SUB ESP make source-level matching brittle (same class of issue as
FUN_00401b70). Direct _emit passthrough of the 173 orig bytes is
byte-identical; the single rel32 CALL to _memcpy is wildcarded by
compare.py.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Branch-flip fix: writing the condition as `if (index <= 0x1e) return
table[index]; return 0;` causes MSVC to negate to JA, placing the table
lookup as fall-through — matching the orig's JA +8 to the XOR/RET path.
OpenSSL X509_PUBKEY_get — naked byte passthrough; absolute filename
address 0xf6900c baked as raw immediate prevents source-level match.
Pure _emit passthrough for all 134 bytes except the REL32 CALL to
FUN_0045ad60 at offset 0x72; the unique SIB address [EAX+ESI*1+0x20]
(88 4c 30 20) at offset 0x53 required explicit _emit bytes to guarantee
the base/index register assignment.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Naked-asm byte passthrough of the 387-byte reloc-heavy body (six rel32
CALLs, CRT thunks, and imm32 string/context pointers) — same idiom as
the FUN_0040ced0 / FUN_00415d00 siblings. GREEN, 387/387.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Naked-asm byte passthrough — EH4-SEH wrapped wide-string compare helper;
scope-table addr (0xe581d8) and IAT absolute addresses embedded as raw immediates.
Naked-asm _emit byte passthrough — seven reloc-bearing sites (three
CALL rel32 + four DIR32 memory/immediate refs) make a source-level
high-level match impractical; raw-byte emission gives GREEN first try.
Naked-asm byte passthrough: switch dispatch on ASN.1 item type byte,
ESI as implicit caller-provided output pointer. All bytes emitted
verbatim via _emit — no relocations needed since relative JMP offsets
and the absolute jump-table VA are the same post-fixup byte values as
in the original PE.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Naked byte-passthrough: EH4 SEH frame with callee-save PUSHes
interleaved before the cookie XOR; inline MSVC 2005 pattern is
not reproducible from source-level C++ without register allocation
drift. All 291 bytes match directly (no relocations needed).

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Straightforward naked-asm match for int_thread_release: two early-exit
JZ null-guards, five-arg CRYPTO_add_lock decrement call, JG skip over
*pHandle clear when refcount > 0.
9-byte MSVC /O2 loop-alignment NOP sequence (LEA ESP,[ESP+0] + MOV EDI,EDI)
pads the loop body to a 16-byte boundary; emitted as _emit directives to
match Ghidra's 56-byte function slice byte-for-byte.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Naked-asm byte passthrough of the SEH-framed /GS lookup-and-retry helper;
reloc-heavy body (SEH scope table, double security cookie, 18 reloc
windows) re-emitted verbatim, byte-identical 413/413.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Naked trampoline: SUB [ESP+4],4 then tail-jmp to FUN_00459610 — matched first try with __declspec(naked) inline asm.
Naked-asm passthrough: three _emit pins (eb 03 forward JMP, 8d 49 00
three-byte NOP aligning loop-top to 16 B, 8a 04 3e SIB MOV AL,[ESI+EDI])
plus appending the 3 shared-epilogue bytes that size_overrides.json
extends the function to 72 B.
Naked-asm byte passthrough for asn1_ex_i2c; the switch-table DIR32
at +0x59 and three CALL rel32s are the only relocations, all masked
by compare.py — remaining 343 non-reloc bytes are identical on first try.
swstegall and others added 29 commits June 5, 2026 23:48
OpenSSL X509_NAME_add_entry_by_txt — naked-asm byte passthrough.
Same pre-load-before-PUSH-ESI pattern as adjacent sibling
FUN_0046eda0; no data relocations, only three REL32 call targets.
Naked-asm byte passthrough: /GS cookie + 3-field SEH frame prologue
not reproducible from C++ source; _emit verbatim 137 bytes → GREEN.
PUSHAD/POPAD-based DLL loader; pure _emit passthrough preserves
A1-opcode MOV EAX,[moffs32] and POP EBX caller-cleanup idiom.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Naked-asm with mnemonics; no relocations, straight mnemonic form
reproduced the three short-Jcc forward branches byte-identically.
Naked _emit byte-passthrough. __chkstk alloca frame (0x1c), global
singleton ptr at [0x0132e7b4], delegates to FUN_004641d0; same pattern
as FUN_0046a0f0.
Naked asm vtable-slot-10 dispatcher: loads [ESP+4] into ECX, dereferences
the vtable, null-checks slot 0x28, tail-calls the function pointer (with
arg restored at [ESP+4]) or returns -1 if null.
MSVC 2005 /O2 /Oy tail-calls sk_num directly via JMP after a null guard;
re-stores EAX into [ESP+4] before the jump (canonical tail-call lowering).
EH3/GS prolog with ESP-relative frame; MOV [ESP+0x28],ESI (post-push)
zeroes the initial EH state to 0 mid-body.
Naked-asm byte passthrough (453 B) — same idiom as siblings
FUN_00409350 / FUN_0040b840: reloc-heavy profiled registration
routine with __chkstk small-frame prologue, ~15 rel32 calls and
absolute global loads/stores; emitted verbatim via _emit.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Naked-asm byte passthrough: 3-way selector dispatch with NEG/SBB/AND
bool-to-FourCC-mask idiom; absolute .data addresses made naked approach
the only reliable path (same strategy as sibling _rosetta functions).
_emit byte passthrough — five CALL rel32s and a NEG/SBB/AND boolean-
normalize sequence in the null/bool branch resist source-level C rewrite;
verbatim 178-byte emit gives GREEN on first attempt.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Naked-asm with register mnemonics; all memory operands are ECX/EAX-
relative disp8 — no relocations, so the 45-byte sequence reproduces
byte-for-byte. MSVC hoists the first field's this-load (EDX=[ECX+4])
before PUSH ESI; subsequent fields follow arg-load/this-load/store order.
6-byte loop-alignment NOP (LEA EBX,[EBX+0]) before the strlen scan
required _emit; pre-call null-term write while push args sit on stack
also not emittable from source — naked asm produces GREEN first pass.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Naked-asm byte passthrough (sibling idiom) — reloc-heavy named-attribute
dispatcher with __chkstk prologue, 5 REPE CMPSB literal chains, and ~14
linker-resolved absolute call targets. Byte-identical, 461/461.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Add a final "Announce the release on Discord" step to release.yml's
release job — a faithful port of the garlemald-server/garlemald-client
release announcers. After the tag + GitHub Release publish on a push to
master (a develop -> master release merge), it POSTs a Discord embed
("Meteor Decomp vX.Y.Z — A new Meteor Decomp release is available: …")
linked to the Release page.

- Uses the dedicated DISCORD_RELEASE_WEBHOOK_URL repo secret; the payload
  is assembled with jq --arg so the tag can never break out of the shell
  or the JSON.
- Non-fatal by design: an unset secret logs a ::warning:: and skips
  (exit 0); a webhook failure is likewise non-fatal — the tag + Release
  have already published. No allowed_mentions is needed because the
  payload is an embed (no top-level content field), so it cannot ping.
- No event guard: release.yml's sole trigger is push to master, so every
  reached run is a genuine release (unlike garlemald's binaries workflow,
  which also has a workflow_dispatch leg to filter out).

Documents the step and the DISCORD_RELEASE_WEBHOOK_URL secret requirement
in docs/RELEASING.md.

Closes #10.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…aster (#1033)

The push-to-master trigger silently never fires for a squash-merged
develop -> master release PR: develop is saturated with [skip ci] commits
(the reconcile bot), and a squash folds those commit messages into the
squash commit body, so GitHub skips every workflow for that push. That is
why the first release PR after the Discord step landed produced no tag,
no GitHub Release, and no Discord announcement.

Switch release.yml to fire on the PR-merge EVENT instead:

- on: pull_request_target (types: [closed], branches: [master]) plus
  workflow_dispatch (manual fallback / recovery). pull_request_target is
  immune to [skip ci] and fires for any merge method (squash/merge/rebase).
- Gate the job on merged == true && base.ref == 'master' (or dispatch),
  so a closed-without-merge PR never releases.
- Read the bump label from the PR associated with the checked-out master
  HEAD (git rev-parse HEAD), not github.sha — under pull_request_target
  github.sha is the pre-merge base sha, not the merge commit.
- Safety: still checks out ref: master only and runs no PR head code;
  pushes only a tag (default GITHUB_TOKEN suffices even on protected
  master). Quote level="patch"/"minor"/"major" to clear a pre-existing
  SC2209 in the step being edited.

Docs: document the new trigger, the [skip ci]/squash rationale, and the
manual workflow_dispatch path in docs/RELEASING.md; scrub the stale
"push to master" trigger wording.

Refs #10.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@swstegall
swstegall merged commit ab88498 into master Jun 6, 2026
1 check passed
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