📄 bcheck.c
字号:
if (e->start == 0) { /* no region : add it */ e->start = start; e->size = size; } else { /* already regions in the list: add it at the head */ e1 = bound_new_entry(); e1->start = e->start; e1->size = e->size; e1->next = e->next; e->start = start; e->size = size; e->next = e1; }}/* create a new region. It should not already exist in the region list */void __bound_new_region(void *p, unsigned long size){ unsigned long start, end; BoundEntry *page, *e, *e2; int t1_start, t1_end, i, t2_start, t2_end; start = (unsigned long)p; end = start + size; t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); t1_end = end >> (BOUND_T2_BITS + BOUND_T3_BITS); /* start */ page = get_page(t1_start); t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) & ((BOUND_T2_SIZE - 1) << BOUND_E_BITS); t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) & ((BOUND_T2_SIZE - 1) << BOUND_E_BITS);#ifdef BOUND_DEBUG printf("new %lx %lx %x %x %x %x\n", start, end, t1_start, t1_end, t2_start, t2_end);#endif e = (BoundEntry *)((char *)page + t2_start); add_region(e, start, size); if (t1_end == t1_start) { /* same ending page */ e2 = (BoundEntry *)((char *)page + t2_end); if (e2 > e) { e++; for(;e<e2;e++) { e->start = start; e->size = size; } add_region(e, start, size); } } else { /* mark until end of page */ e2 = page + BOUND_T2_SIZE; e++; for(;e<e2;e++) { e->start = start; e->size = size; } /* mark intermediate pages, if any */ for(i=t1_start+1;i<t1_end;i++) { page = get_page(i); e2 = page + BOUND_T2_SIZE; for(e=page;e<e2;e++) { e->start = start; e->size = size; } } /* last page */ page = get_page(t1_end); e2 = (BoundEntry *)((char *)page + t2_end); for(e=page;e<e2;e++) { e->start = start; e->size = size; } add_region(e, start, size); }}/* delete a region */static inline void delete_region(BoundEntry *e, void *p, unsigned long empty_size){ unsigned long addr; BoundEntry *e1; addr = (unsigned long)p; addr -= e->start; if (addr <= e->size) { /* region found is first one */ e1 = e->next; if (e1 == NULL) { /* no more region: mark it empty */ e->start = 0; e->size = empty_size; } else { /* copy next region in head */ e->start = e1->start; e->size = e1->size; e->next = e1->next; bound_free_entry(e1); } } else { /* find the matching region */ for(;;) { e1 = e; e = e->next; /* region not found: do nothing */ if (e == NULL) break; addr = (unsigned long)p - e->start; if (addr <= e->size) { /* found: remove entry */ e1->next = e->next; bound_free_entry(e); break; } } }}/* WARNING: 'p' must be the starting point of the region. *//* return non zero if error */int __bound_delete_region(void *p){ unsigned long start, end, addr, size, empty_size; BoundEntry *page, *e, *e2; int t1_start, t1_end, t2_start, t2_end, i; start = (unsigned long)p; t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) & ((BOUND_T2_SIZE - 1) << BOUND_E_BITS); /* find region size */ page = __bound_t1[t1_start]; e = (BoundEntry *)((char *)page + t2_start); addr = start - e->start; if (addr > e->size) e = __bound_find_region(e, p); /* test if invalid region */ if (e->size == EMPTY_SIZE || (unsigned long)p != e->start) return -1; /* compute the size we put in invalid regions */ if (e->is_invalid) empty_size = INVALID_SIZE; else empty_size = EMPTY_SIZE; size = e->size; end = start + size; /* now we can free each entry */ t1_end = end >> (BOUND_T2_BITS + BOUND_T3_BITS); t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) & ((BOUND_T2_SIZE - 1) << BOUND_E_BITS); delete_region(e, p, empty_size); if (t1_end == t1_start) { /* same ending page */ e2 = (BoundEntry *)((char *)page + t2_end); if (e2 > e) { e++; for(;e<e2;e++) { e->start = 0; e->size = empty_size; } delete_region(e, p, empty_size); } } else { /* mark until end of page */ e2 = page + BOUND_T2_SIZE; e++; for(;e<e2;e++) { e->start = 0; e->size = empty_size; } /* mark intermediate pages, if any */ /* XXX: should free them */ for(i=t1_start+1;i<t1_end;i++) { page = get_page(i); e2 = page + BOUND_T2_SIZE; for(e=page;e<e2;e++) { e->start = 0; e->size = empty_size; } } /* last page */ page = get_page(t2_end); e2 = (BoundEntry *)((char *)page + t2_end); for(e=page;e<e2;e++) { e->start = 0; e->size = empty_size; } delete_region(e, p, empty_size); } return 0;}/* return the size of the region starting at p, or EMPTY_SIZE if non existant region. */static unsigned long get_region_size(void *p){ unsigned long addr = (unsigned long)p; BoundEntry *e; e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; e = (BoundEntry *)((char *)e + ((addr >> (BOUND_T3_BITS - BOUND_E_BITS)) & ((BOUND_T2_SIZE - 1) << BOUND_E_BITS))); addr -= e->start; if (addr > e->size) e = __bound_find_region(e, p); if (e->start != (unsigned long)p) return EMPTY_SIZE; return e->size;}/* patched memory functions */static void install_malloc_hooks(void){#ifdef CONFIG_TCC_MALLOC_HOOKS saved_malloc_hook = __malloc_hook; saved_free_hook = __free_hook; saved_realloc_hook = __realloc_hook; saved_memalign_hook = __memalign_hook; __malloc_hook = __bound_malloc; __free_hook = __bound_free; __realloc_hook = __bound_realloc; __memalign_hook = __bound_memalign;#endif}static void restore_malloc_hooks(void){#ifdef CONFIG_TCC_MALLOC_HOOKS __malloc_hook = saved_malloc_hook; __free_hook = saved_free_hook; __realloc_hook = saved_realloc_hook; __memalign_hook = saved_memalign_hook;#endif}static void *libc_malloc(size_t size){ void *ptr; restore_malloc_hooks(); ptr = malloc(size); install_malloc_hooks(); return ptr;}static void libc_free(void *ptr){ restore_malloc_hooks(); free(ptr); install_malloc_hooks();}/* XXX: we should use a malloc which ensure that it is unlikely that two malloc'ed data have the same address if 'free' are made in between. */void *__bound_malloc(size_t size, const void *caller){ void *ptr; /* we allocate one more byte to ensure the regions will be separated by at least one byte. With the glibc malloc, it may be in fact not necessary */ ptr = libc_malloc(size + 1); if (!ptr) return NULL; __bound_new_region(ptr, size); return ptr;}void *__bound_memalign(size_t size, size_t align, const void *caller){ void *ptr; restore_malloc_hooks();#ifndef HAVE_MEMALIGN if (align > 4) { /* XXX: handle it ? */ ptr = NULL; } else { /* we suppose that malloc aligns to at least four bytes */ ptr = malloc(size + 1); }#else /* we allocate one more byte to ensure the regions will be separated by at least one byte. With the glibc malloc, it may be in fact not necessary */ ptr = memalign(size + 1, align);#endif install_malloc_hooks(); if (!ptr) return NULL; __bound_new_region(ptr, size); return ptr;}void __bound_free(void *ptr, const void *caller){ if (ptr == NULL) return; if (__bound_delete_region(ptr) != 0) bound_error("freeing invalid region"); libc_free(ptr);}void *__bound_realloc(void *ptr, size_t size, const void *caller){ void *ptr1; int old_size; if (size == 0) { __bound_free(ptr, caller); return NULL; } else { ptr1 = __bound_malloc(size, caller); if (ptr == NULL || ptr1 == NULL) return ptr1; old_size = get_region_size(ptr); if (old_size == EMPTY_SIZE) bound_error("realloc'ing invalid pointer"); memcpy(ptr1, ptr, old_size); __bound_free(ptr, caller); return ptr1; }}#ifndef CONFIG_TCC_MALLOC_HOOKSvoid *__bound_calloc(size_t nmemb, size_t size){ void *ptr; size = size * nmemb; ptr = __bound_malloc(size); if (!ptr) return NULL; memset(ptr, 0, size); return ptr;}#endif#if 0static void bound_dump(void){ BoundEntry *page, *e; int i, j; printf("region dump:\n"); for(i=0;i<BOUND_T1_SIZE;i++) { page = __bound_t1[i]; for(j=0;j<BOUND_T2_SIZE;j++) { e = page + j; /* do not print invalid or empty entries */ if (e->size != EMPTY_SIZE && e->start != 0) { printf("%08x:", (i << (BOUND_T2_BITS + BOUND_T3_BITS)) + (j << BOUND_T3_BITS)); do { printf(" %08lx:%08lx", e->start, e->start + e->size); e = e->next; } while (e != NULL); printf("\n"); } } }}#endif/* some useful checked functions *//* check that (p ... p + size - 1) lies inside 'p' region, if any */static void __bound_check(const void *p, size_t size){ if (size == 0) return; p = __bound_ptr_add((void *)p, size); if (p == INVALID_POINTER) bound_error("invalid pointer");}void *__bound_memcpy(void *dst, const void *src, size_t size){ __bound_check(dst, size); __bound_check(src, size); /* check also region overlap */ if (src >= dst && src < dst + size) bound_error("overlapping regions in memcpy()"); return memcpy(dst, src, size);}void *__bound_memmove(void *dst, const void *src, size_t size){ __bound_check(dst, size); __bound_check(src, size); return memmove(dst, src, size);}void *__bound_memset(void *dst, int c, size_t size){ __bound_check(dst, size); return memset(dst, c, size);}/* XXX: could be optimized */int __bound_strlen(const char *s){ const char *p; int len; len = 0; for(;;) { p = __bound_ptr_indir1((char *)s, len); if (p == INVALID_POINTER) bound_error("bad pointer in strlen()"); if (*p == '\0') break; len++; } return len;}char *__bound_strcpy(char *dst, const char *src){ int len; len = __bound_strlen(src); return __bound_memcpy(dst, src, len + 1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -