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