Last active
May 26, 2024 04:52
-
-
Save ManuelBlanc/ae975b79daa44fcda3d3ca1b46345a7d to your computer and use it in GitHub Desktop.
Recover from div by 0
This file contains 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
/* div0.c -- Recover from a division by zero. | |
** References: | |
** https://learn.microsoft.com/en-us/cpp/cpp/writing-an-exception-filter | |
** http://ref.x86asm.net/coder64.html | |
** https://www.felixcloutier.com/x86/idiv | |
** AMD64 Architecture Programmer's Manual Volume 3 | |
** Intel Architectures Software Developer's Manual Volume 2 | |
** https://web.archive.org/web/20110304144303/http://www.microsoft.com/msj/0898/bugslayer0898.aspx | |
*/ | |
#define WIN32_LEAN_AND_MEAN | |
#include <windows.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
int seh_filter(int code, PEXCEPTION_POINTERS err); | |
void main(void) | |
{ | |
int dividend = 100; | |
int zero = 0; | |
__try | |
{ | |
int result = dividend / zero; /* <-- Divides by 0. */ | |
printf("%d / %d = %d\n", dividend, zero, result); | |
} | |
__except (seh_filter(GetExceptionCode(), GetExceptionInformation())) | |
{ | |
puts("Could not recover from division by 0."); | |
} | |
} | |
/* Structured exception handler filter. */ | |
int seh_filter(int code, PEXCEPTION_POINTERS err) | |
{ | |
if (code == EXCEPTION_INT_DIVIDE_BY_ZERO) | |
{ | |
uint8_t *ip = (uint8_t *)err->ContextRecord->Rip; | |
fprintf(stderr, "[division by zero at rip:%p]\n", ip); | |
/* Decode the size of a DIV or IDIV to jump over it. */ | |
if ((*ip & 0xf0) == 0x40) ip += 1; /* Skip REX prefix. */ | |
if (*ip != 0xf7) return EXCEPTION_EXECUTE_HANDLER; /* Check Opcode. */ | |
ip += 1; | |
if ((*ip & 0x30) != 0x30) return EXCEPTION_EXECUTE_HANDLER; /* Check Reg for 6 or 7. */ | |
uint8_t mod = *ip >> 6; /* Read ModR/M. */ | |
uint8_t rm = *ip & 7; | |
ip += 1; | |
if (mod != 3) | |
{ | |
if (mod == 2) ip += 4; /* Skip disp32. */ | |
if (mod == 1) ip += 1; /* Skip disp8. */ | |
if (mod == 0 && rm == 5) ip += 4; /* Skip disp32. */ | |
if (rm == 4) ip += 1; /* Skip SIB. */ | |
} | |
err->ContextRecord->Rax = err->ContextRecord->Rdx = 0; /* Clear destinations. */ | |
err->ContextRecord->Rip = (DWORD64)ip; /* Jump. */ | |
return EXCEPTION_CONTINUE_EXECUTION; | |
} | |
return EXCEPTION_CONTINUE_SEARCH; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment