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