Skip to content

Instantly share code, notes, and snippets.

@ManuelBlanc
Last active May 26, 2024 04:52
Show Gist options
  • Save ManuelBlanc/ae975b79daa44fcda3d3ca1b46345a7d to your computer and use it in GitHub Desktop.
Save ManuelBlanc/ae975b79daa44fcda3d3ca1b46345a7d to your computer and use it in GitHub Desktop.
Recover from div by 0
/* 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