void Purify_free (void * mem) { MemHash * hash = Purify_FindMemory (mem); PMemoryNode * node; if (!hash) { Purify_Error = IllPointer; Purify_PrintError ("free(addr=%p)", mem); } else { node = (PMemoryNode *)(hash->data); Purify_SetMemoryFlags (hash, 0, hash->size, PURIFY_MemFlag_Free); Purify_RememberCallers (&node->free); } }
void * Purify_realloc (void * mem, size_t size) { PMemoryNode * oldnode, * newnode; MemHash * oldmem, * newmem; if (size) { newnode = malloc (sizeof (PMemoryNode) + size); if (!newnode) return NULL; Purify_RememberCallers (&newnode->alloc); newnode->free.nstack = -1; /* Not freed yet */ newnode->memptr = ALIGN(newnode->mem); newmem = Purify_AddMemory (newnode->memptr, size, PURIFY_MemFlag_Writable | PURIFY_MemFlag_Empty , PURIFY_MemType_Heap ); newmem->data = newnode; } else newnode = NULL; if (mem && size) { memcpy (newnode->memptr, mem, size); } if (mem) { oldmem = Purify_FindMemory (mem); if (!oldmem) { Purify_Error = IllPointer; Purify_PrintError ("realloc(addr=%p, size=%ld)", mem, size); } else { oldnode = (PMemoryNode *)(oldmem->data); if (newnode) { if (size > oldmem->size) size = oldmem->size; memcpy (newnode->memptr, oldnode->memptr, size); Purify_SetMemoryFlags (newmem, 0, size, PURIFY_MemFlag_Readable | PURIFY_MemFlag_Writable ); } Purify_SetMemoryFlags (oldmem, 0, oldmem->size, PURIFY_MemFlag_Free); Purify_RememberCallers (&oldnode->free); } } return newnode ? newnode->memptr : NULL; }
int Purify_CheckMemoryAccess (const void * mem, int size, int access) { MemHash * node = Purify_FindMemory (mem); long offset, cnt; char * ptr; if (!node) return 0; offset = (long)mem - (long)node->mem; if (offset+size > node->size) { Purify_Error = BorderAccess; return 0; } ptr = node->flags + offset; if (access == PURIFY_MemAccess_Read) { cnt = size; while (cnt--) { if (!(*ptr & PURIFY_MemFlag_Readable) ) { if (*ptr & PURIFY_MemFlag_Free) { Purify_Error = (node->type == PURIFY_MemType_Stack) ? FreeStackRead : FreeRead; return 0; } else if (*ptr & PURIFY_MemFlag_Empty) { Purify_Error = UndefRead; return 0; } else { Purify_Error = IllRead; return 0; } } ptr ++; } } else /* write */ { if (node->type == PURIFY_MemType_Code) { Purify_Error = CodeWrite; return 0; } cnt=size; while (cnt--) { if (!(*ptr & PURIFY_MemFlag_Writable) ) { if (*ptr & PURIFY_MemFlag_Free) { Purify_Error = (node->type == PURIFY_MemType_Stack) ? FreeStackWrite : FreeWrite; return 0; } else { Purify_Error = IllWrite; return 0; } } ptr ++; } Purify_ModifyMemoryFlags (node, offset, size, PURIFY_MemFlag_Readable, PURIFY_MemFlag_Readable|PURIFY_MemFlag_Empty ); } return 1; }