11.5Skamil/* $NetBSD: reallocarr.c,v 1.5 2015/08/20 22:27:49 kamil Exp $ */
21.1Sjoerg
31.1Sjoerg/*-
41.1Sjoerg * Copyright (c) 2015 Joerg Sonnenberger <joerg@NetBSD.org>.
51.1Sjoerg * All rights reserved.
61.1Sjoerg *
71.1Sjoerg * Redistribution and use in source and binary forms, with or without
81.1Sjoerg * modification, are permitted provided that the following conditions
91.1Sjoerg * are met:
101.1Sjoerg *
111.1Sjoerg * 1. Redistributions of source code must retain the above copyright
121.1Sjoerg *    notice, this list of conditions and the following disclaimer.
131.1Sjoerg * 2. Redistributions in binary form must reproduce the above copyright
141.1Sjoerg *    notice, this list of conditions and the following disclaimer in
151.1Sjoerg *    the documentation and/or other materials provided with the
161.1Sjoerg *    distribution.
171.1Sjoerg *
181.1Sjoerg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
191.1Sjoerg * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
201.1Sjoerg * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
211.1Sjoerg * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
221.1Sjoerg * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
231.1Sjoerg * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
241.1Sjoerg * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
251.1Sjoerg * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
261.1Sjoerg * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
271.1Sjoerg * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
281.1Sjoerg * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
291.1Sjoerg * SUCH DAMAGE.
301.1Sjoerg */
311.1Sjoerg
321.3Skamil#if HAVE_NBTOOL_CONFIG_H
331.3Skamil#include "nbtool_config.h"
341.3Skamil#endif
351.3Skamil
361.1Sjoerg#include <sys/cdefs.h>
371.5Skamil__RCSID("$NetBSD: reallocarr.c,v 1.5 2015/08/20 22:27:49 kamil Exp $");
381.1Sjoerg
391.1Sjoerg#include "namespace.h"
401.1Sjoerg#include <errno.h>
411.1Sjoerg/* Old POSIX has SIZE_MAX in limits.h */
421.1Sjoerg#include <limits.h>
431.1Sjoerg#include <stdint.h>
441.1Sjoerg#include <stdlib.h>
451.1Sjoerg#include <string.h>
461.1Sjoerg
471.1Sjoerg#ifdef _LIBC
481.1Sjoerg#ifdef __weak_alias
491.1Sjoerg__weak_alias(reallocarr, _reallocarr)
501.1Sjoerg#endif
511.1Sjoerg#endif
521.1Sjoerg
531.4Sjoerg#define SQRT_SIZE_MAX (((size_t)1) << (sizeof(size_t) * CHAR_BIT / 2))
541.3Skamil
551.3Skamil#if !HAVE_REALLOCARR
561.1Sjoergint
571.3Skamilreallocarr(void *ptr, size_t number, size_t size)
581.1Sjoerg{
591.1Sjoerg	int saved_errno, result;
601.1Sjoerg	void *optr;
611.1Sjoerg	void *nptr;
621.1Sjoerg
631.2Skamil	saved_errno = errno;
641.1Sjoerg	memcpy(&optr, ptr, sizeof(ptr));
651.3Skamil	if (number == 0 || size == 0) {
661.1Sjoerg		free(optr);
671.1Sjoerg		nptr = NULL;
681.1Sjoerg		memcpy(ptr, &nptr, sizeof(ptr));
691.1Sjoerg		errno = saved_errno;
701.1Sjoerg		return 0;
711.1Sjoerg	}
721.3Skamil
731.5Skamil	/*
741.5Skamil	 * Try to avoid division here.
751.5Skamil	 *
761.5Skamil	 * It isn't possible to overflow during multiplication if neither
771.5Skamil	 * operand uses any of the most significant half of the bits.
781.5Skamil	 */
791.5Skamil	if (__predict_false((number|size) >= SQRT_SIZE_MAX &&
801.5Skamil	                    number > SIZE_MAX / size)) {
811.3Skamil		errno = saved_errno;
821.1Sjoerg		return EOVERFLOW;
831.3Skamil	}
841.3Skamil
851.3Skamil	nptr = realloc(optr, number * size);
861.5Skamil	if (__predict_false(nptr == NULL)) {
871.1Sjoerg		result = errno;
881.1Sjoerg	} else {
891.1Sjoerg		result = 0;
901.1Sjoerg		memcpy(ptr, &nptr, sizeof(ptr));
911.1Sjoerg	}
921.1Sjoerg	errno = saved_errno;
931.1Sjoerg	return result;
941.1Sjoerg}
951.3Skamil#endif
96