/** * Frees a block of memory previously allocated by dbus_malloc() or * dbus_malloc0(). If passed #NULL, does nothing. * * @param memory block to be freed */ void dbus_free (void *memory) { #ifdef DBUS_BUILD_TESTS if (guards) { check_guards (memory, TRUE); if (memory) { _dbus_atomic_dec (&n_blocks_outstanding); _dbus_assert (n_blocks_outstanding.value >= 0); free (((unsigned char*)memory) - GUARD_START_OFFSET); } return; } #endif if (memory) /* we guarantee it's safe to free (NULL) */ { #ifdef DBUS_BUILD_TESTS _dbus_atomic_dec (&n_blocks_outstanding); _dbus_assert (n_blocks_outstanding.value >= 0); #endif free (memory); } }
enum ach_status ach_open( ach_channel_t *chan, const char *channel_name, ach_attr_t *attr ) { ach_header_t * shm; size_t len; int fd = -1; if( attr ) memcpy( &chan->attr, attr, sizeof(chan->attr) ); else memset( &chan->attr, 0, sizeof(chan->attr) ); if( attr && attr->map_anon ) { shm = attr->shm; len = sizeof(ach_header_t) + sizeof(ach_index_t)*shm->index_cnt + shm->data_size; }else { if( ! channel_name_ok( channel_name ) ) return ACH_INVALID_NAME; /* open shm */ if( ! channel_name_ok( channel_name ) ) return ACH_INVALID_NAME; if( (fd = fd_for_channel_name( channel_name, 0 )) < 0 ) { return check_errno(); } if( (shm = (ach_header_t*) mmap (NULL, sizeof(ach_header_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0ul) ) == MAP_FAILED ) return ACH_FAILED_SYSCALL; if( ACH_SHM_MAGIC_NUM != shm->magic ) return ACH_BAD_SHM_FILE; /* calculate mmaping size */ len = sizeof(ach_header_t) + sizeof(ach_index_t)*shm->index_cnt + shm->data_size; /* remap */ if( -1 == munmap( shm, sizeof(ach_header_t) ) ) return check_errno(); if( (shm = (ach_header_t*) mmap( NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0ul) ) == MAP_FAILED ) return check_errno(); } /* Check guard bytes */ { enum ach_status r = check_guards(shm); if( ACH_OK != r ) return r; } /* initialize struct */ chan->fd = fd; chan->len = len; chan->shm = shm; chan->seq_num = 0; chan->next_index = 1; chan->cancel = 0; return ACH_OK; }
/* returns 1 if valid, *safe == 1 if safe to dump stack */ static inline int check_allocation_locked(struct hdr *hdr, int *safe) { int valid = 1; *safe = 1; if (hdr->tag != ALLOCATION_TAG && hdr->tag != BACKLOG_TAG) { log_message("+++ ALLOCATION %p HAS INVALID TAG %08x (NOT DUMPING STACKTRACE)\n", user(hdr), hdr->tag); /* Allocation header is probably corrupt, do not dequeue or dump stack * trace. */ *safe = 0; return 0; } if (hdr->tag == BACKLOG_TAG && was_used_after_free(hdr)) { log_message("+++ ALLOCATION %p SIZE %d WAS USED AFTER BEING FREED\n", user(hdr), hdr->size); valid = 0; /* check the guards to see if it's safe to dump a stack trace */ (void)check_guards(hdr, safe); } else valid = check_guards(hdr, safe); if (!valid && *safe) { log_message("+++ ALLOCATION %p SIZE %d ALLOCATED HERE:\n", user(hdr), hdr->size); print_backtrace(hdr->bt, hdr->bt_depth); if (hdr->tag == BACKLOG_TAG) { log_message("+++ ALLOCATION %p SIZE %d FREED HERE:\n", user(hdr), hdr->size); print_backtrace(hdr->freed_bt, hdr->freed_bt_depth); } } return valid; }
/** * Frees a block of memory previously allocated by dbus_malloc() or * dbus_malloc0(). If passed #NULL, does nothing. * * @param memory block to be freed */ void dbus_free (void *memory) { #ifdef DBUS_ENABLE_EMBEDDED_TESTS if (guards) { check_guards (memory, TRUE); if (memory) { #ifdef DBUS_DISABLE_ASSERT _dbus_atomic_dec (&n_blocks_outstanding); #else dbus_int32_t old_value; old_value = _dbus_atomic_dec (&n_blocks_outstanding); _dbus_assert (old_value >= 1); #endif free (((unsigned char*)memory) - GUARD_START_OFFSET); dbus_track_free (memory); } return; } #endif if (memory) /* we guarantee it's safe to free (NULL) */ { #ifdef DBUS_ENABLE_EMBEDDED_TESTS #ifdef DBUS_DISABLE_ASSERT _dbus_atomic_dec (&n_blocks_outstanding); #else dbus_int32_t old_value; old_value = _dbus_atomic_dec (&n_blocks_outstanding); _dbus_assert (old_value >= 1); #endif #endif free (memory); dbus_track_free (memory); } }
static void* set_guards (void *real_block, size_t requested_bytes, BlockSource source) { unsigned char *block = real_block; unsigned int i; if (block == NULL) return NULL; _dbus_assert (GUARD_START_OFFSET + GUARD_END_PAD == GUARD_EXTRA_SIZE); *((dbus_uint32_t*)block) = requested_bytes; *((dbus_uint32_t*)(block + 4)) = source; i = GUARD_INFO_SIZE; while (i < GUARD_START_OFFSET) { (*(dbus_uint32_t*) &block[i]) = GUARD_VALUE; i += 4; } i = GUARD_START_OFFSET + requested_bytes; while (i < (GUARD_START_OFFSET + requested_bytes + GUARD_END_PAD)) { (*(dbus_uint32_t*) &block[i]) = GUARD_VALUE; i += 4; } check_guards (block + GUARD_START_OFFSET, FALSE); return block + GUARD_START_OFFSET; }
/** * Resizes a block of memory previously allocated by dbus_malloc() or * dbus_malloc0(). Guaranteed to free the memory and return #NULL if bytes * is zero on all platforms. Returns #NULL if the resize fails. * If the resize fails, the memory is not freed. * * @param memory block to be resized * @param bytes new size of the memory block * @return allocated memory, or #NULL if the resize fails. */ void* dbus_realloc (void *memory, size_t bytes) { #ifdef DBUS_BUILD_TESTS _dbus_initialize_malloc_debug (); if (_dbus_decrement_fail_alloc_counter ()) { _dbus_verbose (" FAILING realloc of %ld bytes\n", (long) bytes); return NULL; } #endif if (bytes == 0) /* guarantee this is safe */ { dbus_free (memory); return NULL; } #ifdef DBUS_BUILD_TESTS else if (fail_size != 0 && bytes > fail_size) return NULL; else if (guards) { if (memory) { size_t old_bytes; void *block; check_guards (memory, FALSE); block = realloc (((unsigned char*)memory) - GUARD_START_OFFSET, bytes + GUARD_EXTRA_SIZE); old_bytes = *(dbus_uint32_t*)block; if (block && bytes >= old_bytes) /* old guards shouldn't have moved */ check_guards (((unsigned char*)block) + GUARD_START_OFFSET, FALSE); return set_guards (block, bytes, SOURCE_REALLOC); } else { void *block; block = malloc (bytes + GUARD_EXTRA_SIZE); if (block) _dbus_atomic_inc (&n_blocks_outstanding); return set_guards (block, bytes, SOURCE_REALLOC_NULL); } } #endif else { void *mem; mem = realloc (memory, bytes); #ifdef DBUS_BUILD_TESTS if (memory == NULL && mem != NULL) _dbus_atomic_inc (&n_blocks_outstanding); #endif return mem; } }
/** * Resizes a block of memory previously allocated by dbus_malloc() or * dbus_malloc0(). Guaranteed to free the memory and return #NULL if bytes * is zero on all platforms. Returns #NULL if the resize fails. * If the resize fails, the memory is not freed. * * @param memory block to be resized * @param bytes new size of the memory block * @return allocated memory, or #NULL if the resize fails. */ void* _dbus_realloc (void *memory, size_t bytes, const char *file, int line) { #ifdef DBUS_ENABLE_EMBEDDED_TESTS _dbus_initialize_malloc_debug (); if (_dbus_decrement_fail_alloc_counter ()) { _dbus_verbose (" FAILING realloc of %ld bytes\n", (long) bytes); return NULL; } #endif if (bytes == 0) /* guarantee this is safe */ { dbus_free (memory); return NULL; } #ifdef DBUS_ENABLE_EMBEDDED_TESTS else if (fail_size != 0 && bytes > fail_size) return NULL; else if (guards) { if (memory) { size_t old_bytes; void *block; check_guards (memory, FALSE); block = realloc (((unsigned char*)memory) - GUARD_START_OFFSET, bytes + GUARD_EXTRA_SIZE); if (block == NULL) { if (malloc_cannot_fail) { _dbus_warn ("out of memory: realloc (%p, %ld + %ld)\n", memory, (long) bytes, (long) GUARD_EXTRA_SIZE); _dbus_abort (); } return NULL; } dbus_track_free (((unsigned char*)memory) - GUARD_START_OFFSET); dbus_track_realloc (((unsigned char*)memory) - GUARD_START_OFFSET, bytes + GUARD_EXTRA_SIZE, file, line); old_bytes = *(dbus_uint32_t*)block; if (bytes >= old_bytes) /* old guards shouldn't have moved */ check_guards (((unsigned char*)block) + GUARD_START_OFFSET, FALSE); return set_guards (block, bytes, SOURCE_REALLOC); } else { void *block; block = malloc (bytes + GUARD_EXTRA_SIZE); if (block) { _dbus_atomic_inc (&n_blocks_outstanding); dbus_track_malloc(block, bytes + GUARD_EXTRA_SIZE, file, line); } else if (malloc_cannot_fail) { _dbus_warn ("out of memory: malloc (%ld + %ld)\n", (long) bytes, (long) GUARD_EXTRA_SIZE); _dbus_abort (); } return set_guards (block, bytes, SOURCE_REALLOC_NULL); } } #endif else { void *mem; mem = realloc (memory, bytes); #ifdef DBUS_ENABLE_EMBEDDED_TESTS if (mem == NULL && malloc_cannot_fail) { _dbus_warn ("out of memory: malloc (%ld)\n", (long) bytes); _dbus_abort (); } if (memory == NULL && mem != NULL) _dbus_atomic_inc (&n_blocks_outstanding); #endif dbus_track_free (memory); dbus_track_realloc (mem, bytes, file, line); return mem; } }