1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2017 Jason King
14 * Copyright 2019, Joyent, Inc.
15 */
16
17 #include <errno.h>
18 #include <limits.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include "demangle-sys.h"
22 #include "demangle_int.h"
23
24 void *
zalloc(sysdem_ops_t * ops,size_t len)25 zalloc(sysdem_ops_t *ops, size_t len)
26 {
27 void *p = ops->alloc(len);
28
29 if (p != NULL)
30 (void) memset(p, 0, len);
31
32 #ifdef DEBUG
33 /*
34 * In normal operation, we should never exhaust memory. Either
35 * something's wrong, or the system is so hosed that aborting
36 * shouldn't hurt anything, and it gives us a more useful stack
37 * trace.
38 */
39 if (p == NULL)
40 abort();
41 #endif
42
43 return (p);
44 }
45
46 void *
xcalloc(sysdem_ops_t * ops,size_t n,size_t elsize)47 xcalloc(sysdem_ops_t *ops, size_t n, size_t elsize)
48 {
49 uint64_t sz;
50
51 if (mul_overflow(n, elsize, &sz)) {
52 errno = ENOMEM;
53 return (NULL);
54 }
55
56 #ifndef _LP64
57 if (sz > SIZE_MAX) {
58 errno = ENOMEM;
59 return (NULL);
60 }
61 #endif
62
63 return (zalloc(ops, sz));
64 }
65 void
xfree(sysdem_ops_t * ops,void * p,size_t len)66 xfree(sysdem_ops_t *ops, void *p, size_t len)
67 {
68 if (p == NULL || len == 0)
69 return;
70
71 ops->free(p, len);
72 }
73
74 void *
xrealloc(sysdem_ops_t * ops,void * p,size_t oldsz,size_t newsz)75 xrealloc(sysdem_ops_t *ops, void *p, size_t oldsz, size_t newsz)
76 {
77 if (newsz == oldsz)
78 return (p);
79
80 VERIFY3U(newsz, >, oldsz);
81
82 void *temp = zalloc(ops, newsz);
83
84 if (temp == NULL)
85 return (NULL);
86
87 if (oldsz > 0) {
88 (void) memcpy(temp, p, oldsz);
89 xfree(ops, p, oldsz);
90 }
91
92 return (temp);
93 }
94
95 char *
xstrdup(sysdem_ops_t * ops,const char * src)96 xstrdup(sysdem_ops_t *ops, const char *src)
97 {
98 size_t len = strlen(src);
99 char *str = zalloc(ops, len + 1);
100
101 if (str == NULL)
102 return (NULL);
103
104 /* zalloc(len+1) guarantees this will be NUL-terminated */
105 (void) memcpy(str, src, len);
106 return (str);
107 }
108
109 /*ARGSUSED*/
110 static void
def_free(void * p,size_t len)111 def_free(void *p, size_t len)
112 {
113 free(p);
114 }
115
116 static sysdem_ops_t i_sysdem_ops_default = {
117 .alloc = malloc,
118 .free = def_free
119 };
120 sysdem_ops_t *sysdem_ops_default = &i_sysdem_ops_default;
121