|  | @@ -186,6 +186,42 @@ static inline void valgrind_make_blocks_noaccess ( void ) {
 | 
		
	
		
			
			| 186 | 186 |  	VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks, sizeof ( free_blocks ) );
 | 
		
	
		
			
			| 187 | 187 |  }
 | 
		
	
		
			
			| 188 | 188 |  
 | 
		
	
		
			
			|  | 189 | +/**
 | 
		
	
		
			
			|  | 190 | + * Check integrity of the blocks in the free list
 | 
		
	
		
			
			|  | 191 | + *
 | 
		
	
		
			
			|  | 192 | + */
 | 
		
	
		
			
			|  | 193 | +static inline void check_blocks ( void ) {
 | 
		
	
		
			
			|  | 194 | +	struct memory_block *block;
 | 
		
	
		
			
			|  | 195 | +	struct memory_block *prev = NULL;
 | 
		
	
		
			
			|  | 196 | +
 | 
		
	
		
			
			|  | 197 | +	if ( ! ASSERTING )
 | 
		
	
		
			
			|  | 198 | +		return;
 | 
		
	
		
			
			|  | 199 | +
 | 
		
	
		
			
			|  | 200 | +	list_for_each_entry ( block, &free_blocks, list ) {
 | 
		
	
		
			
			|  | 201 | +
 | 
		
	
		
			
			|  | 202 | +		/* Check that list structure is intact */
 | 
		
	
		
			
			|  | 203 | +		list_check ( &block->list );
 | 
		
	
		
			
			|  | 204 | +
 | 
		
	
		
			
			|  | 205 | +		/* Check that block size is not too small */
 | 
		
	
		
			
			|  | 206 | +		assert ( block->size >= sizeof ( *block ) );
 | 
		
	
		
			
			|  | 207 | +		assert ( block->size >= MIN_MEMBLOCK_SIZE );
 | 
		
	
		
			
			|  | 208 | +
 | 
		
	
		
			
			|  | 209 | +		/* Check that block does not wrap beyond end of address space */
 | 
		
	
		
			
			|  | 210 | +		assert ( ( ( void * ) block + block->size ) >
 | 
		
	
		
			
			|  | 211 | +			 ( ( void * ) block ) );
 | 
		
	
		
			
			|  | 212 | +
 | 
		
	
		
			
			|  | 213 | +		/* Check that blocks remain in ascending order, and
 | 
		
	
		
			
			|  | 214 | +		 * that adjacent blocks have been merged.
 | 
		
	
		
			
			|  | 215 | +		 */
 | 
		
	
		
			
			|  | 216 | +		if ( prev ) {
 | 
		
	
		
			
			|  | 217 | +			assert ( ( ( void * ) block ) > ( ( void * ) prev ) );
 | 
		
	
		
			
			|  | 218 | +			assert ( ( ( void * ) block ) >
 | 
		
	
		
			
			|  | 219 | +				 ( ( ( void * ) prev ) + prev->size ) );
 | 
		
	
		
			
			|  | 220 | +		}
 | 
		
	
		
			
			|  | 221 | +		prev = block;
 | 
		
	
		
			
			|  | 222 | +	}
 | 
		
	
		
			
			|  | 223 | +}
 | 
		
	
		
			
			|  | 224 | +
 | 
		
	
		
			
			| 189 | 225 |  /**
 | 
		
	
		
			
			| 190 | 226 |   * Discard some cached data
 | 
		
	
		
			
			| 191 | 227 |   *
 | 
		
	
	
		
			
			|  | @@ -242,6 +278,7 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
 | 
		
	
		
			
			| 242 | 278 |  	assert ( ( align == 0 ) || ( ( align & ( align - 1 ) ) == 0 ) );
 | 
		
	
		
			
			| 243 | 279 |  
 | 
		
	
		
			
			| 244 | 280 |  	valgrind_make_blocks_defined();
 | 
		
	
		
			
			|  | 281 | +	check_blocks();
 | 
		
	
		
			
			| 245 | 282 |  
 | 
		
	
		
			
			| 246 | 283 |  	/* Round up size to multiple of MIN_MEMBLOCK_SIZE and
 | 
		
	
		
			
			| 247 | 284 |  	 * calculate alignment mask.
 | 
		
	
	
		
			
			|  | @@ -314,6 +351,7 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
 | 
		
	
		
			
			| 314 | 351 |  	}
 | 
		
	
		
			
			| 315 | 352 |  
 | 
		
	
		
			
			| 316 | 353 |   done:
 | 
		
	
		
			
			|  | 354 | +	check_blocks();
 | 
		
	
		
			
			| 317 | 355 |  	valgrind_make_blocks_noaccess();
 | 
		
	
		
			
			| 318 | 356 |  	return ptr;
 | 
		
	
		
			
			| 319 | 357 |  }
 | 
		
	
	
		
			
			|  | @@ -338,6 +376,7 @@ void free_memblock ( void *ptr, size_t size ) {
 | 
		
	
		
			
			| 338 | 376 |  		return;
 | 
		
	
		
			
			| 339 | 377 |  
 | 
		
	
		
			
			| 340 | 378 |  	valgrind_make_blocks_defined();
 | 
		
	
		
			
			|  | 379 | +	check_blocks();
 | 
		
	
		
			
			| 341 | 380 |  
 | 
		
	
		
			
			| 342 | 381 |  	/* Round up size to match actual size that alloc_memblock()
 | 
		
	
		
			
			| 343 | 382 |  	 * would have used.
 | 
		
	
	
		
			
			|  | @@ -346,11 +385,29 @@ void free_memblock ( void *ptr, size_t size ) {
 | 
		
	
		
			
			| 346 | 385 |  	size = ( size + MIN_MEMBLOCK_SIZE - 1 ) & ~( MIN_MEMBLOCK_SIZE - 1 );
 | 
		
	
		
			
			| 347 | 386 |  	freeing = ptr;
 | 
		
	
		
			
			| 348 | 387 |  	VALGRIND_MAKE_MEM_DEFINED ( freeing, sizeof ( *freeing ) );
 | 
		
	
		
			
			| 349 |  | -	freeing->size = size;
 | 
		
	
		
			
			| 350 | 388 |  	DBGC2 ( &heap, "Freeing [%p,%p)\n",
 | 
		
	
		
			
			| 351 | 389 |  		freeing, ( ( ( void * ) freeing ) + size ) );
 | 
		
	
		
			
			| 352 | 390 |  
 | 
		
	
		
			
			|  | 391 | +	/* Check that this block does not overlap the free list */
 | 
		
	
		
			
			|  | 392 | +	if ( ASSERTING ) {
 | 
		
	
		
			
			|  | 393 | +		list_for_each_entry ( block, &free_blocks, list ) {
 | 
		
	
		
			
			|  | 394 | +			if ( ( ( ( void * ) block ) <
 | 
		
	
		
			
			|  | 395 | +			       ( ( void * ) freeing + size ) ) &&
 | 
		
	
		
			
			|  | 396 | +			     ( ( void * ) freeing <
 | 
		
	
		
			
			|  | 397 | +			       ( ( void * ) block + block->size ) ) ) {
 | 
		
	
		
			
			|  | 398 | +				assert ( 0 );
 | 
		
	
		
			
			|  | 399 | +				DBGC ( &heap, "Double free of [%p,%p) "
 | 
		
	
		
			
			|  | 400 | +				       "overlapping [%p,%p) detected from %p\n",
 | 
		
	
		
			
			|  | 401 | +				       freeing,
 | 
		
	
		
			
			|  | 402 | +				       ( ( ( void * ) freeing ) + size ), block,
 | 
		
	
		
			
			|  | 403 | +				       ( ( void * ) block + block->size ),
 | 
		
	
		
			
			|  | 404 | +				       __builtin_return_address ( 0 ) );
 | 
		
	
		
			
			|  | 405 | +			}
 | 
		
	
		
			
			|  | 406 | +		}
 | 
		
	
		
			
			|  | 407 | +	}
 | 
		
	
		
			
			|  | 408 | +
 | 
		
	
		
			
			| 353 | 409 |  	/* Insert/merge into free list */
 | 
		
	
		
			
			|  | 410 | +	freeing->size = size;
 | 
		
	
		
			
			| 354 | 411 |  	list_for_each_entry_safe ( block, tmp, &free_blocks, list ) {
 | 
		
	
		
			
			| 355 | 412 |  		/* Calculate gaps before and after the "freeing" block */
 | 
		
	
		
			
			| 356 | 413 |  		gap_before = ( ( ( void * ) freeing ) - 
 | 
		
	
	
		
			
			|  | @@ -392,6 +449,7 @@ void free_memblock ( void *ptr, size_t size ) {
 | 
		
	
		
			
			| 392 | 449 |  	/* Update free memory counter */
 | 
		
	
		
			
			| 393 | 450 |  	freemem += size;
 | 
		
	
		
			
			| 394 | 451 |  
 | 
		
	
		
			
			|  | 452 | +	check_blocks();
 | 
		
	
		
			
			| 395 | 453 |  	valgrind_make_blocks_noaccess();
 | 
		
	
		
			
			| 396 | 454 |  }
 | 
		
	
		
			
			| 397 | 455 |  
 |