Пример #1
0
void*
egg_secure_alloc_full (const char *tag,
                       size_t length,
                       int flags)
{
	Block *block;
	void *memory = NULL;

	if (tag == NULL)
		tag = "?";

	if (length > 0xFFFFFFFF / 2) {
		if (egg_secure_warnings)
			fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n", 
			         (unsigned long)length);   
		return NULL;
	}

	/* Can't allocate zero bytes */
	if (length == 0)
		return NULL;
	
	DO_LOCK ();
	
		for (block = all_blocks; block; block = block->next) {
			memory = sec_alloc (block, tag, length);
			if (memory)
				break;	
		}
	
		/* None of the current blocks have space, allocate new */
		if (!memory) {
			block = sec_block_create (length, tag);
			if (block)
				memory = sec_alloc (block, tag, length);
		}
		
#ifdef WITH_VALGRIND
		if (memory != NULL)
			VALGRIND_MALLOCLIKE_BLOCK (memory, length, sizeof (void*), 1);
#endif
	
	DO_UNLOCK ();

	if (!memory && (flags & EGG_SECURE_USE_FALLBACK)) {
		memory = egg_memory_fallback (NULL, length);
		if (memory) /* Our returned memory is always zeroed */
			memset (memory, 0, length);
	}
	
	if (!memory)
		errno = ENOMEM;
	
	return memory;
}
Пример #2
0
static void*
sec_realloc (Block *block, void *memory, size_t length)
{
	Cell *cell, *other;
	word_t *word;
	size_t n_words;
	size_t valid;
	void *alloc;

	/* Standard realloc behavior, should have been handled elsewhere */
	ASSERT (memory != NULL);
	ASSERT (length > 0);

	/* Dig out where the meta should be */
	word = memory;
	--word;

#ifdef WITH_VALGRIND
	VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t));
#endif

	ASSERT (sec_is_valid_word (block, word));
	ASSERT (pool_valid (*word));
	cell = *word;

	/* Validate that it's actually for real */
	sec_check_guards (cell);
	ASSERT (cell->allocated > 0);
	ASSERT (cell->next == NULL);
	ASSERT (cell->prev == NULL);

	/* The amount of valid data */
	valid = cell->allocated;

	/* How many words we actually want */
	n_words = sec_size_to_words (length) + 2;

	/* Less memory is required than is in the cell */
	if (n_words <= cell->n_words) {

		/* TODO: No shrinking behavior yet */
		cell->allocated = length;
		alloc = sec_cell_to_memory (cell);

#ifdef WITH_VALGRIND
		VALGRIND_MAKE_MEM_DEFINED (alloc, length);
#endif

		/*
		 * Even though we may be reusing the same cell, that doesn't
		 * mean that the allocation is shrinking. It could have shrunk
		 * and is now expanding back some.
		 */
		if (length < valid)
			return sec_clear_memory (alloc, length, valid);
		else
			return alloc;
	}

	/* Need braaaaaiiiiiinsss... */
	while (cell->n_words < n_words) {

		/* See if we have a neighbor who can give us some memory */
		other = sec_neighbor_after (block, cell);
		if (!other || other->allocated != 0)
			break;

		/* Eat the whole neighbor if not too big */
		if (n_words - cell->n_words + WASTE >= other->n_words) {
			cell->n_words += other->n_words;
			sec_write_guards (cell);
			sec_remove_cell_ring (&block->unused, other);
			pool_free (other);

		/* Steal from the neighbor */
		} else {
			other->words += n_words - cell->n_words;
			other->n_words -= n_words - cell->n_words;
			sec_write_guards (other);
			cell->n_words = n_words;
			sec_write_guards (cell);
		}
	}

	if (cell->n_words >= n_words) {
		cell->allocated = length;
		alloc = sec_cell_to_memory (cell);

#ifdef WITH_VALGRIND
		VALGRIND_MAKE_MEM_DEFINED (alloc, length);
#endif

		return sec_clear_memory (alloc, valid, length);
	}

	/* That didn't work, try alloc/free */
	alloc = sec_alloc (block, length);
	if (alloc) {
		memcpy (alloc, memory, valid);
		sec_free (block, memory);
	}

	return alloc;
}