| #include <stdlib.h> |
| #ifdef _MSC_VER |
| #endif |
| #include <stdio.h> |
| #include <memory.h> |
| #include <assert.h> |
| |
| #include <cn-cbor/cn-cbor.h> |
| |
| #ifdef USE_CBOR_CONTEXT |
| #include "context.h" |
| |
| typedef unsigned char byte; |
| |
| typedef struct { |
| cn_cbor_context context; |
| byte *pFirst; |
| ssize_t iFailLeft; |
| ssize_t allocCount; |
| } MyContext; |
| |
| typedef struct _MyItem { |
| int allocNumber; |
| struct _MyItem *pNext; |
| size_t size; |
| byte pad[4]; |
| byte data[4]; |
| } MyItem; |
| |
| bool CheckMemory(MyContext *pContext) |
| { |
| MyItem *p = NULL; |
| // Walk memory and check every block |
| |
| for (p = (MyItem *)pContext->pFirst; p != NULL; p = p->pNext) { |
| if (p->pad[0] == (byte)0xab) { |
| // Block has been freed |
| for (unsigned i = 0; i < p->size + 8; i++) { |
| if (p->pad[i] != (byte)0xab) { |
| fprintf(stderr, "Freed block is modified"); |
| assert(false); |
| } |
| } |
| } |
| else if (p->pad[0] == (byte)0xef) { |
| for (unsigned i = 0; i < 4; i++) { |
| if ((p->pad[i] != (byte)0xef) || (p->pad[i + 4 + p->size] != (byte)0xef)) { |
| fprintf(stderr, "Current block was overrun"); |
| assert(false); |
| } |
| } |
| } |
| else { |
| fprintf(stderr, "Incorrect pad value"); |
| assert(false); |
| } |
| } |
| |
| return true; |
| } |
| |
| void *MyCalloc(size_t count, size_t size, void *context) |
| { |
| MyItem *pb = NULL; |
| MyContext *myContext = (MyContext *)context; |
| |
| CheckMemory(myContext); |
| |
| if (myContext->iFailLeft != -1) { |
| if (myContext->iFailLeft == 0) { |
| return NULL; |
| } |
| myContext->iFailLeft--; |
| } |
| |
| pb = (MyItem *)malloc(sizeof(MyItem) + count * size); |
| |
| memset(pb, 0xef, sizeof(MyItem) + count * size); |
| memset(&pb->data, 0, count * size); |
| |
| pb->pNext = (struct _MyItem *)myContext->pFirst; |
| myContext->pFirst = (byte *)pb; |
| pb->size = count * size; |
| pb->allocNumber = myContext->allocCount++; |
| |
| return &pb->data; |
| } |
| |
| void MyFree(void *ptr, void *context) |
| { |
| MyItem *pb = (MyItem *)((byte *)ptr - sizeof(MyItem) + 4); |
| MyContext *myContext = (MyContext *)context; |
| MyItem *pItem = NULL; |
| |
| CheckMemory(myContext); |
| if (ptr == NULL) { |
| return; |
| } |
| |
| for (pItem = (MyItem *)myContext->pFirst; pItem != NULL; pItem = pItem->pNext) { |
| if (pItem == pb) { |
| break; |
| } |
| } |
| |
| if (pItem == NULL) { |
| // Not an item we allocated |
| assert(false); |
| } |
| |
| if (pb->pad[0] == 0xab) { |
| // Item has already been freed |
| assert(false); |
| } |
| |
| memset(&pb->pad, 0xab, pb->size + 8); |
| } |
| |
| cn_cbor_context *CreateContext(unsigned int iFailPoint) |
| { |
| MyContext *p = malloc(sizeof(MyContext)); |
| |
| p->context.calloc_func = MyCalloc; |
| p->context.free_func = MyFree; |
| p->context.context = p; |
| p->pFirst = NULL; |
| p->iFailLeft = iFailPoint; |
| p->allocCount = 0; |
| |
| return &p->context; |
| } |
| |
| void FreeContext(cn_cbor_context *pContext) |
| { |
| MyContext *myContext = (MyContext *)pContext; |
| MyItem *pItem; |
| MyItem *pItem2; |
| |
| CheckMemory(myContext); |
| |
| for (pItem = (MyItem *)myContext->pFirst; pItem != NULL; pItem = pItem2) { |
| pItem2 = pItem->pNext; |
| free(pItem); |
| } |
| |
| free(myContext); |
| |
| return; |
| } |
| |
| int IsContextEmpty(const cn_cbor_context *pContext) |
| { |
| MyContext *myContext = (MyContext *)pContext; |
| MyItem *p; |
| int i = 0; |
| |
| // Walk memory and check every block |
| |
| for (p = (MyItem *)myContext->pFirst; p != NULL; p = p->pNext) { |
| if (p->pad[0] == (byte)0xab) { |
| // Block has been freed |
| } |
| else { |
| // This block has not been freed |
| i += 1; |
| } |
| } |
| |
| return i; |
| } |
| |
| #endif // USE_CBOR_CONTEXT |