mirror of
				https://github.com/KartKrewDev/RingRacers.git
				synced 2025-10-30 08:01:28 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			76 lines
		
	
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			76 lines
		
	
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* Fail-proof memory allocation by Graue <graue@oceanbase.org>; public domain */
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
#include <limits.h>
 | 
						|
#include "err.h"
 | 
						|
 | 
						|
/* MinGW (for example) appears to lack SIZE_T_MAX. */
 | 
						|
#ifndef SIZE_T_MAX
 | 
						|
#define SIZE_T_MAX ULONG_MAX
 | 
						|
#endif
 | 
						|
 | 
						|
/*
 | 
						|
 * The usual xmalloc and xrealloc type routines, for allocating memory
 | 
						|
 * and bombing out if it fails.
 | 
						|
 *
 | 
						|
 * xm and xr here take two values: size and nmemb, like fread/fwrite.
 | 
						|
 * The idea is to be able to check for overflow, to prevent some weird
 | 
						|
 * crashes and security problems that can arise if you multiply size
 | 
						|
 * and nmemb and they overflow.
 | 
						|
 */
 | 
						|
 | 
						|
/* FIXME: use %zu (size_t) in these format arguments if library is C99 */
 | 
						|
 | 
						|
/*
 | 
						|
 * Multiply size and number of elements, bombing out if overflow would
 | 
						|
 * occur.
 | 
						|
 | 
						|
 * Note: In the case where size*nmemb is exactly equal to SIZE_T_MAX,
 | 
						|
 * this function considers that an overflow, even though it isn't
 | 
						|
 * really. But it's not likely the program will get that much memory,
 | 
						|
 * anyway.
 | 
						|
 */
 | 
						|
static size_t sizmul(size_t size, size_t nmemb)
 | 
						|
{
 | 
						|
	if (SIZE_T_MAX / size <= nmemb)
 | 
						|
	{
 | 
						|
		errx(1, "allocating %lu objects of size %lu "
 | 
						|
			"would overflow", (unsigned long)nmemb,
 | 
						|
			(unsigned long)size);
 | 
						|
	}
 | 
						|
	return size * nmemb; /* won't overflow */
 | 
						|
}
 | 
						|
 | 
						|
static void nomem(size_t size, size_t nmemb)
 | 
						|
{
 | 
						|
	err(1, "cannot allocate %lu objects of size %lu "
 | 
						|
		"(total %lu bytes)", (unsigned long)nmemb,
 | 
						|
		(unsigned long)size, (unsigned long)(nmemb*size));
 | 
						|
}
 | 
						|
 | 
						|
void *xm(size_t size, size_t nmemb)
 | 
						|
{
 | 
						|
	const size_t bytes = sizmul(size, nmemb);
 | 
						|
	void *p;
 | 
						|
 | 
						|
	p = malloc(bytes);
 | 
						|
	if (p == NULL) nomem(size, nmemb);
 | 
						|
	return p;
 | 
						|
}
 | 
						|
 | 
						|
void *xr(void *p, size_t size, size_t nmemb)
 | 
						|
{
 | 
						|
	const size_t bytes = sizmul(size, nmemb);
 | 
						|
 | 
						|
	p = realloc(p, bytes);
 | 
						|
	if (p == NULL) nomem(size, nmemb);
 | 
						|
	return p;
 | 
						|
}
 | 
						|
 | 
						|
/* expand array */
 | 
						|
void *xpnd(void *p, int nit, int *sit, size_t sz)
 | 
						|
{
 | 
						|
	if (nit < *sit) return p;
 | 
						|
	else if (*sit > 0) return xr(p, sz, (*sit *= 2));
 | 
						|
	else return xm(sz, (*sit = 10));
 | 
						|
}
 |