Last active
May 12, 2026 05:01
-
-
Save siraben/53a6ad67cbf20c021dff8f1044c75353 to your computer and use it in GitHub Desktop.
m2-planet segfault
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/cc_core.c b/cc_core.c | |
| index 1890595..cddb43b 100644 | |
| --- a/cc_core.c | |
| +++ b/cc_core.c | |
| @@ -273,13 +273,16 @@ void function_call(struct token_list* s, int is_function_pointer) | |
| emit_push(REGISTER_BASE, "Protect the old base pointer"); | |
| emit_push(REGISTER_LOCALS, "Protect the old locals pointer"); | |
| - emit_move(REGISTER_TEMP, REGISTER_STACK, "Copy new base pointer"); | |
| - | |
| + /* Spill the function pointer to the stack instead of a register. | |
| + * On x86 REGISTER_TEMP2 is EDX, which is implicitly written by mul | |
| + * (used to scale array subscripts) when evaluating arguments. */ | |
| if(is_function_pointer) | |
| { | |
| - emit_move(REGISTER_TEMP2, REGISTER_ZERO, "Save function pointer address"); | |
| + emit_push(REGISTER_ZERO, "Save function pointer on stack"); | |
| } | |
| + emit_move(REGISTER_TEMP, REGISTER_STACK, "Copy new base pointer"); | |
| + | |
| int passed = 0; | |
| while(global_token->s[0] != ')') | |
| { | |
| @@ -305,7 +308,8 @@ void function_call(struct token_list* s, int is_function_pointer) | |
| if(TRUE == is_function_pointer) | |
| { | |
| - emit_move(REGISTER_ZERO, REGISTER_TEMP2, "Restore function pointer"); | |
| + emit_load_relative_to_register(REGISTER_ZERO, REGISTER_TEMP, 0, "Address of saved function pointer"); | |
| + emit_dereference(REGISTER_ZERO, "Restore function pointer from stack"); | |
| if(Architecture & ARCH_FAMILY_KNIGHT) | |
| { | |
| @@ -372,6 +376,11 @@ void function_call(struct token_list* s, int is_function_pointer) | |
| emit_move(REGISTER_STACK, REGISTER_BASE, "Clean up function arguments"); | |
| } | |
| + if(is_function_pointer) | |
| + { | |
| + emit_pop(REGISTER_ONE, "Discard saved function pointer slot"); | |
| + } | |
| + | |
| emit_pop(REGISTER_LOCALS, "Restore old locals pointer"); | |
| emit_pop(REGISTER_BASE, "Restore old base pointer"); | |
| if((AARCH64 == Architecture) || (RISCV64 == Architecture) || (RISCV32 == Architecture)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* Minimal reproducer for the M2-Planet 1.13.x indirect-call bug. | |
| * Exits 0 patched, segfaults unpatched. */ | |
| typedef unsigned (*FUNCTION)(unsigned); | |
| unsigned table[1]; | |
| /* Array subscript emits `mul_ecx`, which clobbers EDX. */ | |
| unsigned get(unsigned i) { return table[i]; } | |
| unsigned sink(unsigned x) { return x; } | |
| int main() | |
| { | |
| FUNCTION fp = sink; | |
| fp(get(0)); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment