|
@@ -291,9 +291,17 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
|
291
|
291
|
*/
|
292
|
292
|
actual_size = ( ( size + MIN_MEMBLOCK_SIZE - 1 ) &
|
293
|
293
|
~( MIN_MEMBLOCK_SIZE - 1 ) );
|
|
294
|
+ if ( ! actual_size ) {
|
|
295
|
+ /* The requested size is not permitted to be zero. A
|
|
296
|
+ * zero result at this point indicates that either the
|
|
297
|
+ * original requested size was zero, or that unsigned
|
|
298
|
+ * integer overflow has occurred.
|
|
299
|
+ */
|
|
300
|
+ ptr = NULL;
|
|
301
|
+ goto done;
|
|
302
|
+ }
|
294
|
303
|
assert ( actual_size >= size );
|
295
|
304
|
align_mask = ( ( align - 1 ) | ( MIN_MEMBLOCK_SIZE - 1 ) );
|
296
|
|
- assert ( ( actual_size + align_mask ) > actual_size );
|
297
|
305
|
|
298
|
306
|
DBGC2 ( &heap, "Allocating %#zx (aligned %#zx+%zx)\n",
|
299
|
307
|
size, align, offset );
|
|
@@ -302,7 +310,8 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
|
302
|
310
|
list_for_each_entry ( block, &free_blocks, list ) {
|
303
|
311
|
pre_size = ( ( offset - virt_to_phys ( block ) )
|
304
|
312
|
& align_mask );
|
305
|
|
- if ( block->size < ( pre_size + actual_size ) )
|
|
313
|
+ if ( ( block->size < pre_size ) ||
|
|
314
|
+ ( ( block->size - pre_size ) < actual_size ) )
|
306
|
315
|
continue;
|
307
|
316
|
post_size = ( block->size - pre_size - actual_size );
|
308
|
317
|
/* Split block into pre-block, block, and
|
|
@@ -506,6 +515,8 @@ void * realloc ( void *old_ptr, size_t new_size ) {
|
506
|
515
|
if ( new_size ) {
|
507
|
516
|
new_total_size = ( new_size +
|
508
|
517
|
offsetof ( struct autosized_block, data ) );
|
|
518
|
+ if ( new_total_size < new_size )
|
|
519
|
+ return NULL;
|
509
|
520
|
new_block = alloc_memblock ( new_total_size, 1, 0 );
|
510
|
521
|
if ( ! new_block )
|
511
|
522
|
return NULL;
|