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