Fix address sanitizer error when loading "Industrial Action" (#150)

* Move resource header check out of UserToRes to allow BrResCheck to fail

* Add BrResCheck and BrResSize to brender.h header (used while debugging)

* Skip OG code behavior of setting row_bytes to align to a 4 byte boundary
This commit is contained in:
Anonymous Maarten 2022-09-16 05:13:11 +02:00 committed by GitHub
parent 9ec9fb008f
commit 25b796335d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 9 deletions

View File

@ -13,6 +13,13 @@
#define RES_ALIGN 4
#define RESOURCE_SIZE(RES) ((RES)->size_h << 18) | ((RES)->size_m << 10) | ((RES)->size_l << 2)
#define PANIC_ON_INVALID_RESOURCE_HEADER(RES_HDR) \
do { \
if ((RES_HDR)->magic_num != 0xdeadbeef) { \
LOG_PANIC("Bad resource header from user at %p. Was 0x%x", (RES_HDR), (RES_HDR)->magic_num); \
} \
} while (0)
// IDA: void* __usercall ResToUser@<EAX>(resource_header *r@<EAX>)
void* ResToUser(resource_header* r) {
br_int_32 align;
@ -34,9 +41,6 @@ resource_header* UserToRes(void* r) {
while (*p == 0) {
p--;
}
if (((resource_header*)(p - (sizeof(resource_header) - 1)))->magic_num != 0xdeadbeef) {
LOG_PANIC("Bad resource header from user at %p. Was 0x%x", r, ((resource_header*)p)->magic_num);
}
return (resource_header*)(p - (sizeof(resource_header) - 1));
}
@ -76,6 +80,7 @@ void* BrResAllocate(void* vparent, br_size_t size, br_uint_8 res_class) {
if (vparent != NULL) {
// vparent points to a resource body, we track backwards to obtain its resource_header
parent = UserToRes(vparent);
PANIC_ON_INVALID_RESOURCE_HEADER(parent);
BrSimpleAddHead(&parent->children, &res->node);
}
@ -113,6 +118,7 @@ void BrResInternalFree(resource_header* res, br_boolean callback) {
void BrResFree(void* vres) {
LOG_TRACE10("(%p)", vres);
PANIC_ON_INVALID_RESOURCE_HEADER(UserToRes(vres));
BrResInternalFree(UserToRes(vres), 1);
}
@ -120,6 +126,7 @@ void BrResFree(void* vres) {
void BrResFreeNoCallback(void* vres) {
LOG_TRACE("(%p)", vres);
PANIC_ON_INVALID_RESOURCE_HEADER(UserToRes(vres));
BrResInternalFree(UserToRes(vres), 0);
}
@ -132,6 +139,9 @@ void* BrResAdd(void* vparent, void* vres) {
res = UserToRes(vres);
parent = UserToRes(vparent);
PANIC_ON_INVALID_RESOURCE_HEADER(res);
PANIC_ON_INVALID_RESOURCE_HEADER(parent);
if (res->node.prev != NULL) {
BrSimpleRemove(&res->node);
}
@ -145,6 +155,8 @@ void* BrResRemove(void* vres) {
LOG_TRACE("(%p)", vres);
res = UserToRes(vres);
PANIC_ON_INVALID_RESOURCE_HEADER(res);
BrSimpleRemove(&res->node);
return vres;
}
@ -155,6 +167,7 @@ br_uint_8 BrResClass(void* vres) {
LOG_TRACE("(%p)", vres);
res = UserToRes(vres);
PANIC_ON_INVALID_RESOURCE_HEADER(res);
return res->class;
}
@ -167,6 +180,8 @@ br_boolean BrResIsChild(void* vparent, void* vchild) {
parent = UserToRes(vparent);
child = UserToRes(vchild);
PANIC_ON_INVALID_RESOURCE_HEADER(parent);
PANIC_ON_INVALID_RESOURCE_HEADER(child);
for (cp = (resource_header*)parent->children.head; cp != NULL; cp = (resource_header*)cp->node.next) {
if (cp == child) {
@ -182,6 +197,8 @@ br_uint_32 BrResSize(void* vres) {
LOG_TRACE("(%p)", vres);
res = UserToRes(vres);
PANIC_ON_INVALID_RESOURCE_HEADER(res);
return RESOURCE_SIZE(res);
}
@ -212,6 +229,7 @@ br_uint_32 BrResChildEnum(void* vres, br_resenum_cbfn* callback, void* arg) {
LOG_TRACE("(%p, %p, %p)", vres, callback, arg);
res = UserToRes(vres);
PANIC_ON_INVALID_RESOURCE_HEADER(res);
r = 0;
for (rp = (resource_header*)res->children.head; rp != NULL; rp = (resource_header*)rp->node.next) {
r = callback(ResToUser(rp), arg);
@ -228,10 +246,9 @@ br_uint_32 BrResCheck(void* vres, int no_tag) {
LOG_TRACE("(%p, %d)", vres, no_tag);
res = UserToRes(vres);
if ((res->magic_ptr == res) & (res->magic_num == 0xdeadbeef)) {
return 1;
}
return 0;
// No PANIC_ON_INVALID_RESOURCE_HEADER check
return res->magic_ptr == res && res->magic_num == 0xdeadbeef;
}
// IDA: char* __cdecl BrResStrDup(void *vparent, char *str)
@ -272,6 +289,7 @@ void BrResDump(void* vres, br_putline_cbfn* putline, void* arg) {
LOG_TRACE("(%p, %p, %p)", vres, putline, arg);
res = UserToRes(vres);
PANIC_ON_INVALID_RESOURCE_HEADER(res);
InternalResourceDump(res, putline, arg, 0);
}

View File

@ -145,6 +145,8 @@ void* BrResAllocate(void* vparent, br_size_t size, br_uint_8 res_class);
br_resource_class* BrResClassAdd(br_resource_class* rclass);
void* BrResRemove(void* vres);
void BrResFree(void* vres);
br_uint_32 BrResCheck(void* vres, int no_tag);
br_uint_32 BrResSize(void* vres);
char* BrResStrDup(void* vparent, char* str);
// BrTable

View File

@ -453,7 +453,9 @@ br_pixelmap* DRPixelmapLoad(char* pFile_name) {
if (the_map != NULL) {
the_map->origin_x = 0;
the_map->origin_y = 0;
the_map->row_bytes = (the_map->row_bytes + sizeof(int) - 1) & ~(sizeof(int) - 1);
#if !defined(DETHRACE_FIX_BUGS)
the_map->row_bytes = (the_map->row_bytes + sizeof(int32_t) - 1) & ~(sizeof(int32_t) - 1);
#endif
}
return the_map;
}
@ -469,7 +471,9 @@ br_uint_32 DRPixelmapLoadMany(char* pFile_name, br_pixelmap** pPixelmaps, br_uin
number_loaded = BrPixelmapLoadMany(pFile_name, pPixelmaps, pNum);
for (i = 0; i < number_loaded; i++) {
the_map = pPixelmaps[i];
the_map->row_bytes = (the_map->row_bytes + 3) & 0xFFFC;
#if !defined(DETHRACE_FIX_BUGS)
the_map->row_bytes = (the_map->row_bytes + sizeof(int32_t) - 1) & ~(sizeof(int32_t) - 1);
#endif
the_map->base_x = 0;
the_map->base_y = 0;
}