1/*
2 * Copyright (c) 1999-2005, 2007, 2010
3 *	Todd C. Miller <Todd.Miller@courtesan.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
17 * Sponsored in part by the Defense Advanced Research Projects
18 * Agency (DARPA) and Air Force Research Laboratory, Air Force
19 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
20 */
21
22#include <config.h>
23
24#include <sys/types.h>
25#include <sys/param.h>
26#include <stdio.h>
27#ifdef STDC_HEADERS
28# include <stdlib.h>
29# include <stddef.h>
30#else
31# ifdef HAVE_STDLIB_H
32#  include <stdlib.h>
33# endif
34#endif /* STDC_HEADERS */
35#ifdef HAVE_STRING_H
36# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
37#  include <memory.h>
38# endif
39# include <string.h>
40#endif /* HAVE_STRING_H */
41#ifdef HAVE_STRINGS_H
42# include <strings.h>
43#endif /* HAVE_STRING_H */
44#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
45# include <malloc.h>
46#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
47#ifdef HAVE_INTTYPES_H
48# include <inttypes.h>
49#endif
50
51#include "missing.h"
52#include "alloc.h"
53#include "error.h"
54
55/*
56 * If there is no SIZE_MAX or SIZE_T_MAX we have to assume that size_t
57 * could be signed (as it is on SunOS 4.x).  This just means that
58 * emalloc2() and erealloc3() cannot allocate huge amounts on such a
59 * platform but that is OK since sudo doesn't need to do so anyway.
60 */
61#ifndef SIZE_MAX
62# ifdef SIZE_T_MAX
63#  define SIZE_MAX	SIZE_T_MAX
64# else
65#  define SIZE_MAX	INT_MAX
66# endif /* SIZE_T_MAX */
67#endif /* SIZE_MAX */
68
69/*
70 * emalloc() calls the system malloc(3) and exits with an error if
71 * malloc(3) fails.
72 */
73void *
74emalloc(size)
75    size_t size;
76{
77    void *ptr;
78
79    if (size == 0)
80	errorx(1, "internal error, tried to emalloc(0)");
81
82    if ((ptr = malloc(size)) == NULL)
83	errorx(1, "unable to allocate memory");
84    return ptr;
85}
86
87/*
88 * emalloc2() allocates nmemb * size bytes and exits with an error
89 * if overflow would occur or if the system malloc(3) fails.
90 */
91void *
92emalloc2(nmemb, size)
93    size_t nmemb;
94    size_t size;
95{
96    void *ptr;
97
98    if (nmemb == 0 || size == 0)
99	errorx(1, "internal error, tried to emalloc2(0)");
100    if (nmemb > SIZE_MAX / size)
101	errorx(1, "internal error, emalloc2() overflow");
102
103    size *= nmemb;
104    if ((ptr = malloc(size)) == NULL)
105	errorx(1, "unable to allocate memory");
106    return ptr;
107}
108
109/*
110 * ecalloc() allocates nmemb * size bytes and exits with an error
111 * if overflow would occur or if the system malloc(3) fails.
112 * On success, the allocated space is zero-filled.
113 */
114void *
115ecalloc(nmemb, size)
116    size_t nmemb;
117    size_t size;
118{
119    void *ptr;
120
121    if (nmemb == 0 || size == 0)
122	errorx(1, "internal error, tried to ecalloc(0)");
123    if (nmemb != 1) {
124	if (nmemb > SIZE_MAX / size)
125	    errorx(1, "internal error, ecalloc() overflow");
126	size *= nmemb;
127    }
128    if ((ptr = malloc(size)) == NULL)
129	errorx(1, "unable to allocate memory");
130    memset(ptr, 0, size);
131    return ptr;
132}
133
134/*
135 * erealloc() calls the system realloc(3) and exits with an error if
136 * realloc(3) fails.  You can call erealloc() with a NULL pointer even
137 * if the system realloc(3) does not support this.
138 */
139void *
140erealloc(ptr, size)
141    void *ptr;
142    size_t size;
143{
144
145    if (size == 0)
146	errorx(1, "internal error, tried to erealloc(0)");
147
148    ptr = ptr ? realloc(ptr, size) : malloc(size);
149    if (ptr == NULL)
150	errorx(1, "unable to allocate memory");
151    return ptr;
152}
153
154/*
155 * erealloc3() realloc(3)s nmemb * size bytes and exits with an error
156 * if overflow would occur or if the system malloc(3)/realloc(3) fails.
157 * You can call erealloc() with a NULL pointer even if the system realloc(3)
158 * does not support this.
159 */
160void *
161erealloc3(ptr, nmemb, size)
162    void *ptr;
163    size_t nmemb;
164    size_t size;
165{
166
167    if (nmemb == 0 || size == 0)
168	errorx(1, "internal error, tried to erealloc3(0)");
169    if (nmemb > SIZE_MAX / size)
170	errorx(1, "internal error, erealloc3() overflow");
171
172    size *= nmemb;
173    ptr = ptr ? realloc(ptr, size) : malloc(size);
174    if (ptr == NULL)
175	errorx(1, "unable to allocate memory");
176    return ptr;
177}
178
179/*
180 * estrdup() is like strdup(3) except that it exits with an error if
181 * malloc(3) fails.  NOTE: unlike strdup(3), estrdup(NULL) is legal.
182 */
183char *
184estrdup(src)
185    const char *src;
186{
187    char *dst = NULL;
188    size_t len;
189
190    if (src != NULL) {
191	len = strlen(src);
192	dst = (char *) emalloc(len + 1);
193	(void) memcpy(dst, src, len);
194	dst[len] = '\0';
195    }
196    return dst;
197}
198
199/*
200 * estrdup() is like strndup(3) except that it exits with an error if
201 * malloc(3) fails.  NOTE: unlike strdup(3), estrdup(NULL) is legal.
202 */
203char *
204estrndup(src, maxlen)
205    const char *src;
206    size_t maxlen;
207{
208    char *dst = NULL;
209    size_t len = 0;
210
211    if (src != NULL) {
212	while (maxlen != 0 && src[len] != '\0') {
213	    len++;
214	    maxlen--;
215	}
216	dst = (char *) emalloc(len + 1);
217	(void) memcpy(dst, src, len);
218	dst[len] = '\0';
219    }
220    return dst;
221}
222
223/*
224 * easprintf() calls vasprintf() and exits with an error if vasprintf()
225 * returns -1 (out of memory).
226 */
227int
228#ifdef __STDC__
229easprintf(char **ret, const char *fmt, ...)
230#else
231easprintf(ret, fmt, va_alist)
232    char **ret;
233    const char *fmt;
234    va_dcl
235#endif
236{
237    int len;
238    va_list ap;
239#ifdef __STDC__
240    va_start(ap, fmt);
241#else
242    va_start(ap);
243#endif
244    len = vasprintf(ret, fmt, ap);
245    va_end(ap);
246
247    if (len == -1)
248	errorx(1, "unable to allocate memory");
249    return len;
250}
251
252/*
253 * evasprintf() calls vasprintf() and exits with an error if vasprintf()
254 * returns -1 (out of memory).
255 */
256int
257evasprintf(ret, format, args)
258    char **ret;
259    const char *format;
260    va_list args;
261{
262    int len;
263
264    if ((len = vasprintf(ret, format, args)) == -1)
265	errorx(1, "unable to allocate memory");
266    return len;
267}
268
269/*
270 * Wrapper for free(3) so we can depend on C89 semantics.
271 */
272void
273efree(ptr)
274    void *ptr;
275{
276    if (ptr != NULL)
277	free(ptr);
278}
279