openmohaa/code/sys/win_bounds.cpp

189 lines
4.6 KiB
C++
Raw Normal View History

2023-01-31 01:23:49 +01:00
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// win_bounds.cpp : Bounds checks all new's and delete's
extern "C"
2023-02-05 13:27:12 +01:00
{
void* b_malloc(unsigned int size);
void b_free(void*);
};
2023-01-31 01:23:49 +01:00
//////////////////////////
// Bounds checking
//
// #define DISABLE_BOUNDS to disable checking a compiler
// warning will happen if checking is enabled
//
// #define BOUNDS_ENDOFPAGE to check for overflowed, don't
// define it to check for underflows
//
// functions:
// void *b_malloc ( unsigned );
// Does a bounds-malloc, or just a normal one if checking's
// disabled
// void b_free ( void * );
// Frees a bounds pointer, or just a normal free if no
// checking
//
// void *operator new ( size_t ), operator new[] ( size )
// For C++ new's and new []'s, bounds checked
// void operator delete ( void * ), operator delete[] ( void * )
// For C++ delete's and delete []'s, bounds checked
//////////////////////////
#define DISABLE_BOUNDS
#if defined(GAME_DLL) || defined(CGAME_DLL)
#define DISABLE_BOUNDS
#endif
//#define BOUNDS_ENDOFPAGE
/////////////////////////
// If bounds are disabled
/////////////////////////
#ifdef DISABLE_BOUNDS
#include <malloc.h>
2023-02-05 13:27:12 +01:00
void* b_malloc(unsigned int size)
{
return malloc(size);
}
2023-01-31 01:23:49 +01:00
2023-02-05 13:27:12 +01:00
void b_free(void* what)
{
free(what);
}
2023-01-31 01:23:49 +01:00
///////////////////////////
// If bounds are enabled
///////////////////////////
#else
#pragma message ("win_bounds.cpp: Warning - Bounds checking is enabled\n" )
#include <stdio.h>
#include <windows.h>
typedef struct {
unsigned int header;
int size;
2023-02-05 13:27:12 +01:00
void* returned;
2023-01-31 01:23:49 +01:00
} bounds_type_t;
#define PAGE_SIZE ( 4096 )
#define NORMAL_HEADER 0xdeadbeef
#define ARRAY_HEADER 0xdeadbabe
2023-02-05 13:27:12 +01:00
static unsigned int bounds_numpages(unsigned int size) {
2023-01-31 01:23:49 +01:00
unsigned int ret;
ret = size / PAGE_SIZE + 3;
2023-02-05 13:27:12 +01:00
if (size % PAGE_SIZE)
2023-01-31 01:23:49 +01:00
ret++;
return ret;
}
2023-02-05 13:27:12 +01:00
void* bounds_malloc(unsigned int size, unsigned head = NORMAL_HEADER) {
bounds_type_t* where;
2023-01-31 01:23:49 +01:00
unsigned int num_pages;
2023-02-05 13:27:12 +01:00
void* mainaddress;
2023-01-31 01:23:49 +01:00
2023-02-05 13:27:12 +01:00
num_pages = bounds_numpages(size);
2023-01-31 01:23:49 +01:00
2023-02-05 13:27:12 +01:00
mainaddress = VirtualAlloc(NULL, num_pages * PAGE_SIZE, MEM_RESERVE, PAGE_NOACCESS);
VirtualAlloc(mainaddress, PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE);
VirtualAlloc((char*)mainaddress + PAGE_SIZE * 2, (num_pages - 3) * PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE);
where = (bounds_type_t*)mainaddress;
2023-01-31 01:23:49 +01:00
where->header = head;
where->size = size;
#ifdef BOUNDS_ENDOFPAGE
2023-02-05 13:27:12 +01:00
where->returned = (char*)mainaddress + (num_pages - 1) * PAGE_SIZE - size;
2023-01-31 01:23:49 +01:00
#else
2023-02-05 13:27:12 +01:00
where->returned = (char*)mainaddress + PAGE_SIZE * 2;
2023-01-31 01:23:49 +01:00
#endif
2023-02-05 13:27:12 +01:00
memset(where->returned, 0xdc, size);
return where->returned;
2023-01-31 01:23:49 +01:00
}
2023-02-05 13:27:12 +01:00
void bounds_free(void* address, unsigned head = NORMAL_HEADER) {
bounds_type_t* where;
2023-01-31 01:23:49 +01:00
unsigned int num_pages;
2023-02-05 13:27:12 +01:00
void* mainaddress;
2023-01-31 01:23:49 +01:00
2023-02-05 13:27:12 +01:00
mainaddress = (char*)address - PAGE_SIZE * 2;
2023-01-31 01:23:49 +01:00
#ifdef BOUNDS_ENDOFPAGE
2023-02-05 13:27:12 +01:00
mainaddress = (char*)mainaddress - ((unsigned int)mainaddress % 4096);
2023-01-31 01:23:49 +01:00
#endif
2023-02-05 13:27:12 +01:00
where = (bounds_type_t*)mainaddress;
2023-01-31 01:23:49 +01:00
2023-02-05 13:27:12 +01:00
if (where->header != head || where->returned != address) {
2023-01-31 01:23:49 +01:00
__asm int 3 // Breakpoint
}
2023-02-05 13:27:12 +01:00
num_pages = bounds_numpages(where->size);
2023-01-31 01:23:49 +01:00
// All pages must be in the same state to be MEM_RELEASED
2023-02-05 13:27:12 +01:00
VirtualFree(mainaddress, PAGE_SIZE, MEM_DECOMMIT);
VirtualFree((char*)mainaddress + PAGE_SIZE * 2, (num_pages - 3) * PAGE_SIZE, MEM_DECOMMIT);
VirtualFree(mainaddress, 0, MEM_RELEASE);
}
void* b_malloc(unsigned int size)
{
return bounds_malloc(size);
}
void b_free(void* what)
{
bounds_free(what);
2023-01-31 01:23:49 +01:00
}
2023-02-05 13:27:12 +01:00
void* operator new[](size_t size)
{
return bounds_malloc(size, ARRAY_HEADER);
}
void* operator new (size_t size)
{
return bounds_malloc(size);
}
void operator delete [](void* what)
{
if (what)
bounds_free(what, ARRAY_HEADER);
}
void operator delete (void* what)
{
if (what)
bounds_free(what);
}
2023-01-31 01:23:49 +01:00
#endif /* !DISABLE_BOUNDS */