From a0f8d8c2ae6921807ff9247b2d3e853b71c16148 Mon Sep 17 00:00:00 2001 From: Guillaume Petiot <guillaume.petiot@cea.fr> Date: Mon, 26 Nov 2012 08:52:54 +0000 Subject: [PATCH] + fix _valid_read --- .../e-acsl/memory_model/e_acsl_bittree.c | 281 +++++------ .../share/e-acsl/memory_model/e_acsl_mmodel.c | 439 ++++++++---------- .../share/e-acsl/memory_model/e_acsl_mmodel.h | 30 ++ .../e-acsl/memory_model/e_acsl_mmodel_api.h | 34 +- 4 files changed, 386 insertions(+), 398 deletions(-) diff --git a/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_bittree.c b/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_bittree.c index 6a29dea436a..098964e17b2 100644 --- a/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_bittree.c +++ b/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_bittree.c @@ -93,18 +93,20 @@ int Teq[] = {0,-1,3,-3,6,-5,7,-7,12,-9,11,-11,14,-13,15,-15,24,-17,19,-19,22,-21 int Tneq[] = {0,0,1,-2,2,-4,5,-6,4,-8,9,-10,10,-12,13,-14,8,-16,17,-18,18,-20,21,-22,20,-24,25,-26,26,-28,29,-30,16,-32,33,-34,34,-36,37,-38,36,-40,41,-42,42,-44,45,-46,40,-48,49,-50,50,-52,53,-54,52,-56,57,-58,58,-60,61,-62,-63}; /* common bits of two addresses */ - unsigned long mask(void * a, void * b) { unsigned long nxor = ~((unsigned long)a ^ (unsigned long)b); - int i = WORDBITS/2; - __cpt_mask++; + int i = WORDBITS/2; /* dichotomic search, starting in the middle */ + + /* if the current mask matches we use transition from Teq, else from Tneq + we stop as soon as i is negative, meaning that we found the mask */ + while(i > 0) i = (nxor >= Tmasks[i]) ? Teq[i] : Tneq[i]; - while(i > 0) - i = (nxor >= Tmasks[i]) ? Teq[i] : Tneq[i]; + /* a negative element i from Teq or Tneq means stop and return Tmasks[-i] */ return Tmasks[-i]; } -/* binary conjuction of a bittree and a new node */ + +/* logical AND of a bittree and a new node */ void* and(struct bittree * a, struct _block * b) { return (void*) ((unsigned long)a->addr & (unsigned long)b->ptr); } @@ -114,106 +116,99 @@ int matches_mask(struct bittree * a, void * b) { return ((unsigned long)a->addr & a->mask) == ((unsigned long)b & a->mask); } -/********************/ +/* remove the block from the structure */ void _remove_element (struct _block * ptr) { struct bittree * curr = __root; - if(__root == NULL || ptr == NULL) - return; + assert(__root != NULL); + assert(ptr != NULL); - if(__root->is_leaf) { - if(__root->addr == ptr->ptr) { - free(__root); - __root = NULL; - } + if(__root->is_leaf) { + assert(__root->addr == ptr->ptr); + free(__root); + __root = NULL; return; } - + while(1) { /* does not match the mask */ - if(!matches_mask(curr, ptr->ptr)) - break; - + assert(matches_mask(curr, ptr->ptr)); + /* element to delete */ if(curr->is_leaf) { - struct bittree * to_up, * cf; - assert(curr->father != NULL); - - to_up = (curr == curr->father->left)? - curr->father->right : curr->father->left; + struct bittree * brother, * cf; cf = curr->father; - assert(to_up != NULL); - - cf->is_leaf = to_up->is_leaf; - cf->addr = to_up->addr; - cf->mask = to_up->mask; - cf->left = to_up->left; - cf->right = to_up->right; - cf->leaf = to_up->leaf; - - if(!to_up->is_leaf) { - to_up->left->father = cf; - to_up->right->father = cf; + assert(cf != NULL); + brother = (curr == cf->left) ? cf->right : cf->left; + assert(brother != NULL); + + cf->is_leaf = brother->is_leaf; + cf->addr = brother->addr; + cf->mask = brother->mask; + cf->left = brother->left; + cf->right = brother->right; + cf->leaf = brother->leaf; + + if(!brother->is_leaf) { + brother->left->father = cf; + brother->right->father = cf; } - free(to_up); + free(brother); free(curr); - break; } - - /* visit child with most bits in common */ + assert(curr->left != NULL && curr->right != NULL); - curr = (mask(curr->left->addr, ptr->ptr) - > mask(curr->right->addr, ptr->ptr))? - curr->left : curr->right; + + /* visit child with greatest common prefix, + if the bit next to the mask is set to 1, go to right child, + because its address is higher than the other */ + curr = ((curr->mask >> 1) & ( ~ curr->mask ) & (unsigned long)ptr->ptr) ? + curr->right : curr->left; } } -/************************/ +/* add a block in the structure */ void _add_element (struct _block * ptr) { struct bittree * new_leaf; - if(ptr == NULL) - return; - + assert(ptr != NULL); + new_leaf = malloc(sizeof(struct bittree)); + assert(new_leaf != NULL); new_leaf->is_leaf = 1; new_leaf->addr = ptr->ptr; - new_leaf->mask = ~0; - new_leaf->left = NULL; - new_leaf->right = NULL; - new_leaf->father = NULL; + new_leaf->mask = ~0ul; + new_leaf->left = new_leaf->right = new_leaf->father = NULL; new_leaf->leaf = ptr; - - if(__root == NULL) - __root = new_leaf; - + + if(__root == NULL) __root = new_leaf; else { - struct bittree * curr = __root; /* __root != NULL */ - + struct bittree * curr = __root; + while(1) { /* matches the mask */ if(matches_mask(curr, ptr->ptr)) { - /* already stored */ - if(curr->is_leaf) { - free(new_leaf); - assert(ptr->ptr == curr->addr); - break; - } - assert(curr->left != NULL - && curr->right != NULL); - /* visit child with most bits in common */ - curr = mask(curr->left->addr, ptr->ptr) - > mask(curr->right->addr, ptr->ptr) - ? curr->left - : curr->right; - } + /* is a leaf => already stored */ + if(curr->is_leaf) + return; + + assert(!curr->is_leaf); + assert(curr->left != NULL && curr->right != NULL); + /* visit child with greatest common prefix */ + curr = + ((curr->mask >> 1) & ( ~ curr->mask ) & (unsigned long)ptr->ptr) ? + curr->right : curr->left; + } + /* does not match the mask : creating a new node */ else { struct bittree * new_node; new_node = malloc(sizeof(struct bittree)); + assert(new_node != NULL); + new_node->is_leaf = curr->is_leaf; new_node->addr = curr->addr; new_node->mask = curr->mask; @@ -223,163 +218,135 @@ void _add_element (struct _block * ptr) { new_leaf->father = curr; new_node->leaf = curr->leaf; - if(!new_node->is_leaf) { - new_node->left->father = new_node; - new_node->right->father = new_node; - } - + if(!new_node->is_leaf) + new_node->left->father = new_node->right->father = new_node; + curr->is_leaf = 0; - curr->addr = and(new_node, ptr); curr->mask = mask(new_node->addr, ptr->ptr); + curr->addr = (void*)((unsigned long)and(new_node, ptr) & curr->mask); + + /* smaller at left, higher at right */ if(new_node->addr < ptr->ptr) { curr->left = new_node; curr->right = new_leaf; - } else { + } + else { curr->left = new_leaf; curr->right = new_node; } curr->leaf = NULL; - break; } } } } -/**********************/ +/* return the block B such as : begin addr of B == ptr + we suppose that such a block exists, but we could return NULL if not */ struct _block * _get_exact (void * ptr) { struct bittree * tmp = __root; - if(__root == NULL || ptr == NULL) - return NULL; + if(__root == NULL || ptr == NULL) return NULL; while(1) { /* does not match the mask */ - if(!matches_mask(tmp, ptr)) - break; - /* the leaf we are looking for */ - if(tmp->is_leaf) - return tmp->leaf; - /* visit child with most bits in common */ - assert(tmp->left != NULL && tmp->right != NULL); + if(!matches_mask(tmp, ptr)) return NULL; - tmp = (mask(tmp->left->addr, ptr) - > mask(tmp->right->addr, ptr)) ? - tmp->left : - tmp->right; - } - - return NULL; -} - -/************************/ - -struct _block * _get_next (void * ptr) { - struct bittree * tmp = __root; - if(__root == NULL || ptr == NULL) - return NULL; - if(__root->is_leaf) - return NULL; + /* the leaf we are looking for */ + if(tmp->is_leaf) return tmp->leaf; - while(1) { - /* does not match the mask */ - if(!matches_mask(tmp, ptr)) - break; - if(tmp->is_leaf) - break; - /* visit child with most bits in common */ assert(tmp->left != NULL && tmp->right != NULL); - - tmp = (mask(tmp->left->addr, ptr) - > mask(tmp->right->addr, ptr)) ? - tmp->left : - tmp->right; + + /* visit child with greatest common prefix */ + tmp = ((tmp->mask >> 1) & ( ~ tmp->mask ) & (unsigned long)ptr) ? + tmp->right : tmp->left; } - - if(ptr < (void*)tmp->addr) - return NULL; - /* we move up, as long as we are on right branches */ - while(tmp->father != NULL && tmp == tmp->father->right) - tmp = tmp->father; - /* tmp is at bottom right => no next leaf */ - if(tmp == __root) - return NULL; - /* tmp has a father and is a left child */ - tmp = tmp->father->right; - /* we move down, following left branches */ - while(!tmp->is_leaf) - tmp = tmp->left; - assert(ptr < (void*)tmp->addr); - return tmp->leaf; } -/**************************/ +/* return the block B containing ptr, such as : + begin addr of B <= ptr < (begin addr + size) of B + or NULL if such a block does not exist */ struct _block * _get_cont (void * ptr) { struct bittree * tmp = __root; - if(__root == NULL || ptr == NULL) - return NULL; - + if(__root == NULL || ptr == NULL) return NULL; + while(1) { if(tmp->is_leaf) { - if(ptr < (void*)tmp->addr) - return NULL; - else - if(ptr < (void*)(tmp->addr + tmp->leaf->size)) - return tmp->leaf; + /* tmp cannot contain ptr because its begin addr is higher */ + if(tmp->addr > (char*)ptr) return NULL; + /* tmp->addr <= ptr, tmp may contain ptr + ptr is contained if tmp is large enough (begin addr + size) */ + else if((char*)ptr < tmp->leaf->size + tmp->addr) return tmp->leaf; + /* tmp->addr <= ptr, but tmp->addr is not large enough */ return NULL; } + assert(tmp->left != NULL && tmp->right != NULL); + + /* the right child has the highest address, so we test it first */ if(((unsigned long)tmp->right->addr & tmp->right->mask) <= ((unsigned long)ptr & tmp->right->mask)) tmp = tmp->right; else if(((unsigned long)tmp->left->addr & tmp->left->mask) <= ((unsigned long)ptr & tmp->left->mask)) tmp = tmp->left; - else - return NULL; + else return NULL; } } -/**************************/ +/*******************/ +/* CLEAN */ +/*******************/ + + +/* recursively erase the content of the structure, + do not call directly */ void __clean_rec (struct bittree * ptr) { - if(ptr == NULL) - return; - if(ptr->is_leaf) { + if(ptr == NULL) return; + else if(ptr->is_leaf) { _clean_block(ptr->leaf); ptr->leaf = NULL; - } else { + } + else { __clean_rec(ptr->left); - ptr->left = NULL; __clean_rec(ptr->right); - ptr->right = NULL; + ptr->left = ptr->right = NULL; } free(ptr); - ptr = NULL; } +/* erase the content of the structure */ void __clean_struct () { __clean_rec(__root); - /* printf("cpt mask: %i\n", __cpt_mask);*/ + __root = NULL; } + /*********************/ +/* DEBUG */ +/*********************/ + +/* recursively print the content of the structure + do not call directly */ void __debug_rec (struct bittree * ptr) { - if(ptr == NULL) - return; - if(ptr->is_leaf) { + if(ptr == NULL) return; + else if(ptr->is_leaf) { printf("\t\t\t"); _print_block(ptr->leaf); - } else { + } + else { __debug_rec(ptr->left); __debug_rec(ptr->right); } } +/* print the content of the structure */ void __debug_struct () { printf("\t\t\t------------DEBUG\n"); __debug_rec(__root); printf("\t\t\t-----------------\n"); } + diff --git a/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_mmodel.c b/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_mmodel.c index f73c75b385b..c1e242e49a2 100644 --- a/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_mmodel.c +++ b/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_mmodel.c @@ -2,185 +2,96 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stdbool.h> +#include <assert.h> #include "e_acsl_bittree.h" #include "e_acsl_mmodel_api.h" -/*#define KEEP_FREED_MEMORY*/ +const int nbr_bits_to_1[256] = { + 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 +}; -int __cpt_store = 0, __cpt_malloc = 0; -void _clean_init (struct _block * ptr) { - if(ptr->init_ptr != NULL) { - free(ptr->init_ptr); - ptr->init_ptr = NULL; - } - ptr->init_cpt = 0; -} - -void _clean_block (struct _block * ptr) { - if(ptr == NULL) - return; - _clean_init(ptr); - free(ptr); - ptr = NULL; +size_t needed_bytes (size_t size) { + return (size % 8) == 0 ? (size/8) : (size/8 + 1); } -void _print_block (struct _block * ptr) { - if (ptr != NULL) { - printf("%p %zu %s ; [init] : %li ", - ptr->ptr, - ptr->size, - ptr->valid? "valid":"invalid", - ptr->init_cpt); - if(ptr->init_ptr != NULL) { - unsigned i; - for(i = 0; i < ptr->size; i++) - printf("%i", ptr->init_ptr[i]); - } - printf("\n"); - } -} - -void* _store_block(void* tmp, size_t size) { -#ifdef KEEP_FREED_MEMORY - struct _block *cont, *next, *ptr; -#else - struct _block *ptr; -#endif - __cpt_store++; -#ifdef KEEP_FREED_MEMORY - cont = _get_cont(tmp); - if(cont != NULL) { - /* si cont commence avant => chevauchement à gauche */ - if(cont->ptr < tmp) { - /* cont se termine en plein milieu */ - if(tmp + size >= cont->ptr + cont->size) - cont->size = tmp - cont->ptr; - /* cont se termine après => chevauchement à droite */ - else { - struct _block * after; - after = malloc(sizeof(struct _block)); - if(after == NULL) - return NULL; - after->ptr = tmp + size; - after->size = cont->ptr + cont->size - - after->ptr; - after->valid = 0; /* false */ - cont->size = tmp - cont->ptr; - _add_element(after); - } - } - } - - for(; (next = _get_next(tmp)) != NULL ;) { - if(next->ptr >= tmp + size) - break; - /* next se termine en plein milieu => on supprime */ - if(tmp + size >= next->ptr + next->size) { - _remove_element(next); - free(next); - next = NULL; - } - /* next se termine après => chevauchement à droite */ - else { - struct _block * after; - after = malloc(sizeof(struct _block)); - if(after == NULL) - return NULL; - after->ptr = tmp + size; - after->size = next->ptr + next->size - after->ptr; - after->valid = 0; /* false */ - _remove_element(next); - free(next); - next = NULL; - _add_element(after); - } - } -#endif - ptr = malloc(sizeof(struct _block)); - if(ptr == NULL) - return NULL; - ptr->ptr = tmp; - ptr->size = size; - ptr->valid = 1; /* true */ - ptr->init_ptr = NULL; - ptr->init_cpt = 0; - _add_element(ptr); - return ptr->ptr; +/* store the block of size bytes starting at ptr */ +void* _store_block(void* ptr, size_t size) { + struct _block * tmp; + assert(ptr != NULL); + tmp = malloc(sizeof(struct _block)); + assert(tmp != NULL); + tmp->ptr = ptr; + tmp->size = size; + tmp->init_ptr = NULL; + tmp->init_cpt = 0; + tmp->is_litteral_string = false; + _add_element(tmp); + return ptr; } +/* remove the block starting at ptr */ void _delete_block(void* ptr) { struct _block * tmp; - if(ptr == NULL) - return; + assert(ptr != NULL); tmp = _get_exact(ptr); - if(tmp == NULL) - return; + assert(tmp != NULL); _clean_init(tmp); _remove_element(tmp); free(tmp); - tmp = NULL; } +/* allocate size bytes and store the returned block + * for further information, see malloc */ void* _malloc(size_t size) { - void * tmp; - if(size <= 0) - return NULL; + void * tmp, * tmp2; + if(size <= 0) return NULL; tmp = malloc(size); - if(tmp == NULL) - return NULL; - __cpt_malloc++; - return _store_block(tmp, size); + if(tmp == NULL) return NULL; + tmp2 = _store_block(tmp, size); + assert(tmp2 != NULL); + return tmp2; } +/* free the block starting at ptr, + * for further information, see free */ void _free(void* ptr) { struct _block * tmp; - if(ptr == NULL) - return; + if(ptr == NULL) return; tmp = _get_exact(ptr); - if(tmp == NULL) - return; - free(tmp->ptr); + assert(tmp != NULL); + free(ptr); _clean_init(tmp); -#ifdef KEEP_FREED_MEMORY - tmp->valid = 0; /* false */ -#else _remove_element(tmp); free(tmp); - tmp = NULL; -#endif } +/* resize the block starting at ptr to fit its new size, + * for further information, see realloc */ void* _realloc(void* ptr, size_t size) { -#ifdef KEEP_FREED_MEMORY - struct _block *tmp, *next; -#else - struct _block *tmp; -#endif - - if(ptr == NULL) - return _malloc(size); + struct _block * tmp, * next; + void * new_ptr; + if(ptr == NULL) return _malloc(size); if(size <= 0) { _free(ptr); - ptr = NULL; return NULL; } tmp = _get_exact(ptr); - if(tmp == NULL) - return NULL; - tmp->ptr = realloc(tmp->ptr, size); - tmp->valid = 1; /* true */ - + assert(tmp != NULL); + new_ptr = realloc(tmp->ptr, size); + if(new_ptr == NULL) return NULL; + tmp->ptr = new_ptr; /* uninitialized, do nothing */ if(tmp->init_cpt == 0) ; - /* already initialized block */ + /* already fully initialized block */ else if (tmp->init_cpt == tmp->size) { /* realloc smaller block */ if(size <= tmp->size) @@ -188,81 +99,75 @@ void* _realloc(void* ptr, size_t size) { tmp->init_cpt = size; /* realloc bigger larger block */ else { - tmp->init_ptr = malloc(size*sizeof(char)); - memset(tmp->init_ptr, 1, tmp->size); - memset(tmp->init_ptr + tmp->size, 0, size - tmp->size); + int i, nb = needed_bytes(size); + tmp->init_ptr = malloc(nb); + memset(tmp->init_ptr, 0xFF, nb); + if(size%8 != 0) + tmp->init_ptr[size/8] <<= (8 - size%8); } } /* contains initialized and uninitialized parts */ - else - tmp->init_ptr = realloc(tmp->init_ptr, size*sizeof(char)); - - tmp->size = size; -#ifdef KEEP_FREED_MEMORY - for(; (next = _get_next(tmp->ptr)) != NULL ;) { - if(next->ptr >= tmp->ptr + size) - break; - /* next se termine en plein milieu => on supprime */ - if(tmp->ptr + size >= next->ptr + next->size) { - _remove_element(next); - free(next); - next = NULL; - } - /* next se termine après => chevauchement à droite */ - else { - struct _block * after; - after = malloc(sizeof(struct _block)); - if(after == NULL) - return NULL; - after->ptr = tmp->ptr + size; - after->size = next->ptr + next->size - after->ptr; - after->valid = 0; /* false */ - _remove_element(next); - free(next); - next = NULL; - _add_element(after); + else { + int nb = needed_bytes(size); + int nb_old = needed_bytes(tmp->size); + int i; + tmp->init_ptr = realloc(tmp->init_ptr, nb); + for(i = nb_old; i < nb; i++) + tmp->init_ptr[i] = 0; + tmp->init_cpt = 0; + for(i = 0; i < nb; i++) + tmp->init_cpt += nbr_bits_to_1[tmp->init_ptr[i]]; + if(tmp->init_cpt == size || tmp->init_cpt == 0) { + free(tmp->init_ptr); + tmp->init_ptr = NULL; } } -#endif + tmp->size = size; return tmp->ptr; } +/* allocate memory for an array of nbr_block elements of size_block size, + * this memory is set to zero, the returned block is stored, + * for further information, see calloc */ void* _calloc(size_t nbr_block, size_t size_block) { - void * tmp; - if(nbr_block * size_block <= 0) - return NULL; + void * tmp, * tmp2; + if(nbr_block * size_block <= 0) return NULL; tmp = calloc(nbr_block, size_block); - if(tmp == NULL) - return NULL; - return _store_block(tmp, nbr_block * size_block); + if(tmp == NULL) return NULL; + tmp2 = _store_block(tmp, nbr_block * size_block); + assert(tmp2 != NULL); + return tmp2; } + +/* mark the size bytes of ptr as initialized */ void _initialize (void * ptr, size_t size) { struct _block * tmp; unsigned i; - if(ptr == NULL || size <= 0) - return; + assert(ptr != NULL); + assert(size > 0); tmp = _get_cont(ptr); - if(tmp == NULL) - return; - + assert(tmp != NULL); + /* already fully initialized, do nothing */ - if(tmp->init_cpt == tmp->size) - return; - + if(tmp->init_cpt == tmp->size) return; + /* fully uninitialized */ if(tmp->init_cpt == 0) { - tmp->init_ptr = malloc(tmp->size * sizeof(char)); - memset(tmp->init_ptr, 0, tmp->size); + int nb = needed_bytes(tmp->size); + tmp->init_ptr = malloc(nb); + memset(tmp->init_ptr, 0, nb); } for(i = 0; i < size; i++) { - if(!tmp->init_ptr[i + (char*)ptr /* JS: suspicious */ - tmp->ptr]) - tmp->init_cpt++; - tmp->init_ptr[i + (char*)ptr /* JS: suspicious */ - tmp->ptr] = 1; + int byte_offset =(char*)ptr - tmp->ptr + i; + int ind = byte_offset / 8; + unsigned char mask_bit = 1U << (7 - (byte_offset % 8)); + if((tmp->init_ptr[ind] & mask_bit) == 0) tmp->init_cpt++; + tmp->init_ptr[ind] |= mask_bit; } - + /* now fully initialized */ if(tmp->init_cpt == tmp->size) { free(tmp->init_ptr); @@ -270,102 +175,170 @@ void _initialize (void * ptr, size_t size) { } } + +/* mark all bytes of ptr as initialized */ void _full_init (void * ptr) { struct _block * tmp; - if(ptr == NULL) - return; + assert(ptr != NULL); tmp = _get_exact(ptr); - if(tmp == NULL) - return; + assert(tmp != NULL); if (tmp->init_ptr != NULL) { free(tmp->init_ptr); tmp->init_ptr = NULL; } - + tmp->init_cpt = tmp->size; } + +/* mark a block as litteral string */ +void _litteral_string (void * ptr) { + struct _block * tmp; + assert(ptr != NULL); + tmp = _get_exact(ptr); + assert(tmp != NULL); + tmp->is_litteral_string = true; +} + + +/* return whether the size bytes of ptr are initialized */ int _initialized (void * ptr, size_t size) { struct _block * tmp; unsigned i; - if(ptr == NULL || size < 0) - return 0; /* false */ + assert(ptr != NULL); + assert(size > 0); tmp = _get_cont(ptr); - if(tmp == NULL) - return 0; /* false */ - + assert(tmp != NULL); + /* fully uninitialized */ - if(tmp->init_cpt == 0) - return 0; /* false */ + if(tmp->init_cpt == 0) return false; /* fully initialized */ - if(tmp->init_cpt == tmp->size) - return 1; /* true */ - - for(i = 0; i < size; i++) + if(tmp->init_cpt == tmp->size) return true; + + for(i = 0; i < size; i++) { /* if one byte is uninitialized */ - if(!tmp->init_ptr[i + (char*)ptr /* JS: suspicious */ - tmp->ptr]) - return 0; /* false */ - return 1; /* true */ + int byte_offset =(char*)ptr - tmp->ptr + i; + int ind = byte_offset / 8; + unsigned char mask_bit = 1U << (7 - (byte_offset % 8)); + if((tmp->init_ptr[ind] & mask_bit) == 0) return false; + } + return true; } -/* Do not verify whether PTR is valid! */ +/* return the length (in bytes) of the block containing ptr */ size_t _block_length(void* ptr) { struct _block * tmp; - if(ptr == NULL) - return 0; + assert(ptr != NULL); tmp = _get_cont(ptr); - if(tmp == NULL) - return 0; - return tmp->ptr + tmp->size - (char*)ptr /* JS: suspicious */; + assert(tmp != NULL); + return tmp->size; } +/* return whether the size bytes of ptr are readable/writable */ int _valid(void* ptr, size_t size) { struct _block * tmp; - if(ptr == NULL || size < 0) - return 0; /* false */ + assert(ptr != NULL); + assert(size > 0); tmp = _get_cont(ptr); - if(tmp == NULL) - return 0; /* false */ - return - (tmp->ptr + tmp->size - (char*)ptr /* JS: suspicious */ >= size) - && tmp->valid; + return (tmp == NULL) ? + false : ( tmp->size - ( (char*)ptr - tmp->ptr ) >= size + && !tmp->is_litteral_string); } -/* Do not verify whether PTR is valid ! */ +/* return whether the size bytes of ptr are readable */ +int _valid_read(void* ptr, size_t size) { + struct _block * tmp; + assert(ptr != NULL); + assert(size > 0); + tmp = _get_cont(ptr); + return (tmp == NULL) ? + false : ( tmp->size - ( (char*)ptr - tmp->ptr ) >= size ); +} + + +/* return the base address of the block containing ptr */ void* _base_addr(void* ptr) { struct _block * tmp; - if(ptr == NULL) - return NULL; + assert(ptr != NULL); tmp = _get_cont(ptr); - if(tmp == NULL) - return NULL; + assert(tmp != NULL); return tmp->ptr; } -/* Do not verify whether PTR is valid ! */ +/* return the offset of ptr within its block */ +/* TODO: remove `size` parameter */ int _offset(void* ptr, size_t size) { - struct _block * tmp; - if(ptr == NULL || size < 0) - return -1; /* error */ - tmp = _get_cont(ptr); - if(tmp == NULL) - return -1; /* error */ - return ((char*)ptr /* JS: suspicious */ - tmp->ptr) / size; + struct _block * tmp; + assert(ptr != NULL); + tmp = _get_cont(ptr); + assert(tmp != NULL); + return ((char*)ptr - tmp->ptr); } +/*******************/ +/* PRINT */ +/*******************/ + + +/* print the information about a block */ +void _print_block (struct _block * ptr) { + if (ptr != NULL) { + printf("%p %zu (litt:%i); [init] : %li ", + ptr->ptr, ptr->size, ptr->is_litteral_string, ptr->init_cpt); + if(ptr->init_ptr != NULL) { + unsigned i; + for(i = 0; i < ptr->size; i++) { + int ind = i / 8; + int one_bit = (unsigned)1 << (8 - (i % 8) - 1); + printf("%i", (ptr->init_ptr[ind] & one_bit) != 0); + } + } + printf("\n"); + } +} + + +/********************/ +/* CLEAN */ +/********************/ + + +/* erase information about initialization of a block */ +void _clean_init (struct _block * ptr) { + if(ptr->init_ptr != NULL) { + free(ptr->init_ptr); + ptr->init_ptr = NULL; + } + ptr->init_cpt = 0; +} + + +/* erase all information about a block */ +void _clean_block (struct _block * ptr) { + if(ptr == NULL) return; + _clean_init(ptr); + free(ptr); +} + + +/* erase the content of the abstract structure */ void __clean() { __clean_struct(); - /* printf("cpt store: %i\n", __cpt_store); - printf("cpt malloc: %i\n", __cpt_malloc);*/ } +/**********************/ +/* DEBUG */ +/**********************/ + + +/* print the content of the abstract structure */ void __debug() { __debug_struct(); } diff --git a/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_mmodel.h b/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_mmodel.h index 90eb2862c9f..f66b49dd96d 100644 --- a/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_mmodel.h +++ b/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_mmodel.h @@ -4,65 +4,95 @@ #include "stdlib.h" +/* allocate size bytes and store the returned block + * for further information, see malloc */ void * _malloc(size_t size) __attribute__((FC_BUILTIN)) ; +/* free the block starting at ptr, + * for further information, see free */ void _free(void * ptr) __attribute__((FC_BUILTIN)); +/* resize the block starting at ptr to fit its new size, + * for further information, see realloc */ void * _realloc(void * ptr, size_t size) __attribute__((FC_BUILTIN)); +/* allocate memory for an array of nbr_block elements of size_block size, + * this memory is set to zero, the returned block is stored, + * for further information, see calloc */ void * _calloc(size_t nbr_elt, size_t size_elt) __attribute__((FC_BUILTIN)); /* From outside the library, the following functions have no side effect */ +/* store the block of size bytes starting at ptr */ /*@ assigns \nothing; */ void * _store_block(void * ptr, size_t size) __attribute__((FC_BUILTIN)); +/* remove the block starting at ptr */ /*@ assigns \nothing; */ void _delete_block(void * ptr) __attribute__((FC_BUILTIN)); +/* mark the size bytes of ptr as initialized */ /*@ assigns \nothing; */ void _initialize(void * ptr, size_t size) __attribute__((FC_BUILTIN)); +/* mark all bytes of ptr as initialized */ /*@ assigns \nothing; */ void _full_init(void * ptr) __attribute__((FC_BUILTIN)); +/* marks a block as litteral string */ +/*@ assigns \nothing; */ +void _litteral_string(void * ptr); + /* ****************** */ /* E-ACSL annotations */ /* ****************** */ +/* return whether the first size bytes of ptr are readable/writable */ /*@ assigns \nothing; */ int _valid(void * ptr, size_t size) __attribute__((FC_BUILTIN)); +/* return whether the first size bytes of ptr are readable */ +/*@ assigns \nothing; */ +int _valid_read(void * ptr, size_t size) + __attribute__((FC_BUILTIN)); + +/* return the base address of the block containing ptr */ /*@ assigns \nothing; */ void * _base_addr(void * ptr) __attribute__((FC_BUILTIN)); +/* return the length (in bytes) of the block containing ptr */ /*@ assigns \nothing; */ size_t _block_length(void * ptr) __attribute__((FC_BUILTIN)); +/* return the offset of ptr within its block */ /*@ assigns \nothing; */ int _offset(void * ptr, size_t size) __attribute__((FC_BUILTIN)); +/* return whether the size bytes of ptr are initialized */ /*@ ensures \result == 0 || \result == 1; @ ensures \result == 1 ==> \initialized(((char *)ptr)+(0..size-1)); @ assigns \nothing; */ int _initialized(void * ptr, size_t size) __attribute__((FC_BUILTIN)); +/* print the content of the abstract structure */ void __debug(void) __attribute__((FC_BUILTIN)); +/* erase the content of the abstract structure + * have to be called at the end of the `main` */ void __clean(void) __attribute__((FC_BUILTIN)); diff --git a/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_mmodel_api.h b/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_mmodel_api.h index b7c50b67155..ab31e733eaf 100644 --- a/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_mmodel_api.h +++ b/src/plugins/e-acsl/share/e-acsl/memory_model/e_acsl_mmodel_api.h @@ -2,29 +2,47 @@ #define E_ACSL_MMODEL_API #include "stdlib.h" +#include "stdbool.h" /* Memory block allocated and may be deallocated */ struct _block { - char* ptr; /* begin address */ - size_t size; /* size in bytes */ - int valid; /* whether the block has not been deallocated yet */ + char * ptr; /* begin address */ + size_t size; /* size in bytes */ /* Keep trace of initialized sub-blocks within a memory block */ - unsigned char * init_ptr; /* dynamic array of booleans */ - unsigned long init_cpt; + unsigned char * init_ptr; /* dynamic array of booleans */ + unsigned long init_cpt; + _Bool is_litteral_string; }; -void _print_block (struct _block * ptr); -void _clean_init (struct _block * ptr); -void _clean_block (struct _block * ptr); + +/* print the information about a block */ +void _print_block ( struct _block * ptr ); +/* erase information about initialization of a block */ +void _clean_init ( struct _block * ptr ); +/* erase all information about a block */ +void _clean_block ( struct _block * ptr ); + /* functions to be implemented */ + +/* remove the block from the structure */ void _remove_element ( struct _block * ); +/* add a block in the structure */ void _add_element ( struct _block * ); +/* return the block B such as : begin addr of B == ptr + we suppose that such a block exists, but we could return NULL if not */ struct _block * _get_exact ( void * ); +/* return the block B such as : begin addr of B > ptr + or NULL if such a block does not exist */ struct _block * _get_next ( void * ); +/* return the block B containing ptr, such as : + begin addr of B <= ptr < (begin addr + size) of B + or NULL if such a block does not exist */ struct _block * _get_cont ( void * ); +/* erase the content of the structure */ void __clean_struct ( ); +/* print the content of the structure */ void __debug_struct ( ); #endif -- GitLab