⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gwmem-check.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ====================================================================  * The Kannel Software License, Version 1.0  *  * Copyright (c) 2001-2004 Kannel Group   * Copyright (c) 1998-2001 WapIT Ltd.    * All rights reserved.  *  * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  *  * 1. Redistributions of source code must retain the above copyright  *    notice, this list of conditions and the following disclaimer.  *  * 2. Redistributions in binary form must reproduce the above copyright  *    notice, this list of conditions and the following disclaimer in  *    the documentation and/or other materials provided with the  *    distribution.  *  * 3. The end-user documentation included with the redistribution,  *    if any, must include the following acknowledgment:  *       "This product includes software developed by the  *        Kannel Group (http://www.kannel.org/)."  *    Alternately, this acknowledgment may appear in the software itself,  *    if and wherever such third-party acknowledgments normally appear.  *  * 4. The names "Kannel" and "Kannel Group" must not be used to  *    endorse or promote products derived from this software without  *    prior written permission. For written permission, please   *    contact org@kannel.org.  *  * 5. Products derived from this software may not be called "Kannel",  *    nor may "Kannel" appear in their name, without prior written  *    permission of the Kannel Group.  *  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,   * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT   * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE   * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  * ====================================================================  *  * This software consists of voluntary contributions made by many  * individuals on behalf of the Kannel Group.  For more information on   * the Kannel Group, please see <http://www.kannel.org/>.  *  * Portions of this software are based upon software originally written at   * WapIT Ltd., Helsinki, Finland for the Kannel project.   */ /* * gwmem-check.c - memory management wrapper functions, check flavor * * This implementation of the gwmem.h interface checks for writes to * non-allocated areas, and fills freshly allocated and freshly freed * areas with garbage to prevent their use.  It also reports memory * leaks. * * Design: Memory is allocated with markers before and after the * area to be used.  These markers can be checked to see if anything * has written to them.  There is a table of all allocated areas, * which is used to detect memory leaks and which contains context * information about each area. * * The start marker contains the index into this table, so that it * can be looked up quickly -- but if the start marker has been damaged, * the index can still be found by searching the table. * * Enlarging an area with realloc is handled by allocating new area, * copying the old data, and freeing the old area.  This is an expensive * operation which is avoided by reserving extra space (up to the nearest * power of two), and only enlarging the area if the requested space is * larger than this extra space.  The markers are still placed at exactly * the size requested, so every realloc does mean moving the end marker. * * When data is freed, it is overwritten with 0xdeadbeef, so that code * that tries to use it after freeing will likely crash.  The freed area * is kept around for a while, to see if anything tries to write to it * after it's been freed. *  * Richard Braakman */#include <stdlib.h>#include <errno.h>#include <string.h>#include "gwlib.h"/* In this module, we must use the real versions so let's undefine the * accident protectors. */#undef malloc#undef realloc#undef free/* Freshly malloced space is filled with NEW_AREA_PATTERN, to break * code that assumes it is filled with zeroes. */#define NEW_AREA_PATTERN 0xcafebabe/* Freed space is filled with FREE_AREA_PATTERN, to break code that * tries to read from it after freeing. */#define FREE_AREA_PATTERN 0xdeadbeef/* The marker before an area is filled with START_MARK_PATTERN * (except for some bookkeeping bytes at the start of the marker). */#define START_MARK_PATTERN 0xdadaface/* The marker beyond an area is filled with END_MARK_PATTERN. */#define END_MARK_PATTERN 0xadadafec/* How many bytes to dump when listing unfreed areas. */#define MAX_DUMP 16static int initialized = 0;/* Use slower, more reliable method of detecting memory corruption. */static int slow = 0;/* We have to use a static mutex here, because otherwise the mutex_create * call would try to allocate memory with gw_malloc before we're * initialized. */static Mutex gwmem_lock;struct location{    const char *filename;    long lineno;    const char *function;};/* Duplicating the often-identical location information in every table * entry uses a lot of memory, but saves the effort of maintaining a * data structure for it, and keeps access to it fast. */struct area{    void *area;    /* The allocated memory area, as seen by caller */    size_t area_size;   /* Size requested by caller */    size_t max_size;    /* Size we can expand area to when reallocing */    struct location allocator;     /* Caller that alloced area */    struct location reallocator;   /* Caller that last realloced area */    struct location claimer;       /* Owner of area, set by caller */};/* Number of bytes to reserve on either side of each allocated area, * to detect writes just outside the area.  It must be at least large * enough to hold a long. */#define MARKER_SIZE 16#define MAX_TAB_SIZE (1024*1024L)#define MAX_ALLOCATIONS ((long) (MAX_TAB_SIZE/sizeof(struct area)))/* Freed areas are thrown into the free ring.  They are not released * back to the system until FREE_RING_SIZE other allocations have been * made.  This is more effective at finding bugs than releasing them * immediately, because when we eventually release them we can check * that they have not been tampered with in that time. */#define FREE_RING_SIZE 1024static struct area allocated[MAX_ALLOCATIONS];static struct area free_ring[FREE_RING_SIZE];/* Current number of allocations in the "allocated" table.  They are * always consecutive and start at the beginning of the table. */static long num_allocations;/* The free ring can wrap around the edges of its array. */static long free_ring_start;static long free_ring_len;/* The next three are used for informational messages at shutdown *//* Largest number of allocations we've had at one time */static long highest_num_allocations;/* Largest value of the sum of allocated areas we've had at one time */static long highest_total_size;/* Current sum of allocated areas */static long total_size;/* Static functions */static void lock(void){    mutex_lock(&gwmem_lock);}static void unlock(void){    mutex_unlock(&gwmem_lock);}static unsigned long round_pow2(unsigned long num){    unsigned long i;    if (num <= 16)        return 16;    for (i = 32; i < 0x80000000L; i <<= 1) {        if (num <= i)            return i;    }    /* We have to handle this case separately; the loop cannot go that     * far because i would overflow. */    if (num <= 0x80000000L)        return 0x80000000L;    return 0xffffffffL;}/* Fill a memory area with a bit pattern */static void fill(unsigned char *p, size_t bytes, long pattern){    while (bytes > sizeof(pattern)) {        memcpy(p, &pattern, sizeof(pattern));        p += sizeof(pattern);        bytes -= sizeof(pattern);    }    if (bytes > 0)        memcpy(p, &pattern, bytes);}/* Check that a filled memory area has not changed */static int untouched(unsigned char *p, size_t bytes, long pattern){    while (bytes > sizeof(pattern)) {        if (memcmp(p, &pattern, sizeof(pattern)) != 0)            return 0;        p += sizeof(pattern);        bytes -= sizeof(pattern);    }    if (bytes > 0 && memcmp(p, &pattern, bytes) != 0)        return 0;    return 1;}/* Fill the end marker for this area */static void endmark(unsigned char *p, size_t size){    fill(p + size, MARKER_SIZE, END_MARK_PATTERN);}/* Fill the start marker for this area, and assign an number to the * area which can be used for quick lookups later.  The number must * not be negative. */static void startmark(unsigned char *p, long number){    gw_assert(MARKER_SIZE >= sizeof(long));    gw_assert(number >= 0);    fill(p - MARKER_SIZE, sizeof(long), number);    fill(p - MARKER_SIZE + sizeof(long),         MARKER_SIZE - sizeof(long), START_MARK_PATTERN);}/* Check that the start marker for this area are intact, and return the * marker number if it seems intact.  Return a negative number if * it does not seem intact. */static long check_startmark(unsigned char *p){    long number;    if (!untouched(p - MARKER_SIZE + sizeof(long),                   MARKER_SIZE - sizeof(long), START_MARK_PATTERN))        return -1;    memcpy(&number, p - MARKER_SIZE, sizeof(number));    return number;}static int check_endmark(unsigned char *p, size_t size){    if (!untouched(p + size, MARKER_SIZE, END_MARK_PATTERN))        return -1;    return 0;}static int check_marks(struct area *area, long index){    int result = 0;    if (check_startmark(area->area) != index) {        error(0, "Start marker was damaged for area %ld", index);        result = -1;    }    if (check_endmark(area->area, area->area_size) < 0) {        error(0, "End marker was damaged for area %ld", index);        result = -1;    }    return result;}static void dump_area(struct area *area){    debug("gwlib.gwmem", 0, "Area %p, size %ld, max_size %ld",          area->area, (long) area->area_size, (long) area->max_size);    debug("gwlib.gwmem", 0, "Allocated by %s() at %s:%ld",          area->allocator.function,          area->allocator.filename,          area->allocator.lineno);    if (area->reallocator.function) {        debug("gwlib.gwmem", 0, "Re-allocated by %s() at %s:%ld",              area->reallocator.function,              area->reallocator.filename,              area->reallocator.lineno);    }    if (area->claimer.function) {        debug("gwlib.gwmem", 0, "Claimed by %s() at %s:%ld",              area->claimer.function,              area->claimer.filename,              area->claimer.lineno);    }    if (area->area_size > 0) {        size_t i;        unsigned char *p;        char buf[MAX_DUMP * 3 + 1];    	p = area->area;        buf[0] = '\0';        for (i = 0; i < area->area_size && i < MAX_DUMP; ++i)            sprintf(strchr(buf, '\0'), "%02x ", p[i]);        debug("gwlib.gwmem", 0, "Contents of area (first %d bytes):", MAX_DUMP);        debug("gwlib.gwmem", 0, "  %s", buf);    }}static struct area *find_area(unsigned char *p){    long index;    struct area *area;    long suspicious_pointer;    unsigned long p_ul;    gw_assert(p != NULL);    p_ul = (unsigned long) p;    suspicious_pointer =

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -