1 /*-------------------------------------------------------------------------
2  *
3  * fe_memutils.c
4  *	  memory management support for frontend code
5  *
6  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *	  src/common/fe_memutils.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #ifndef FRONTEND
17 #error "This file is not expected to be compiled for backend code"
18 #endif
19 
20 #include "postgres_fe.h"
21 
22 static inline void *
pg_malloc_internal(size_t size,int flags)23 pg_malloc_internal(size_t size, int flags)
24 {
25 	void	   *tmp;
26 
27 	/* Avoid unportable behavior of malloc(0) */
28 	if (size == 0)
29 		size = 1;
30 	tmp = malloc(size);
31 	if (tmp == NULL)
32 	{
33 		if ((flags & MCXT_ALLOC_NO_OOM) == 0)
34 		{
35 			fprintf(stderr, _("out of memory\n"));
36 			exit(EXIT_FAILURE);
37 		}
38 		return NULL;
39 	}
40 
41 	if ((flags & MCXT_ALLOC_ZERO) != 0)
42 		MemSet(tmp, 0, size);
43 	return tmp;
44 }
45 
46 void *
pg_malloc(size_t size)47 pg_malloc(size_t size)
48 {
49 	return pg_malloc_internal(size, 0);
50 }
51 
52 void *
pg_malloc0(size_t size)53 pg_malloc0(size_t size)
54 {
55 	return pg_malloc_internal(size, MCXT_ALLOC_ZERO);
56 }
57 
58 void *
pg_malloc_extended(size_t size,int flags)59 pg_malloc_extended(size_t size, int flags)
60 {
61 	return pg_malloc_internal(size, flags);
62 }
63 
64 void *
pg_realloc(void * ptr,size_t size)65 pg_realloc(void *ptr, size_t size)
66 {
67 	void	   *tmp;
68 
69 	/* Avoid unportable behavior of realloc(NULL, 0) */
70 	if (ptr == NULL && size == 0)
71 		size = 1;
72 	tmp = realloc(ptr, size);
73 	if (!tmp)
74 	{
75 		fprintf(stderr, _("out of memory\n"));
76 		exit(EXIT_FAILURE);
77 	}
78 	return tmp;
79 }
80 
81 /*
82  * "Safe" wrapper around strdup().
83  */
84 char *
pg_strdup(const char * in)85 pg_strdup(const char *in)
86 {
87 	char	   *tmp;
88 
89 	if (!in)
90 	{
91 		fprintf(stderr,
92 				_("cannot duplicate null pointer (internal error)\n"));
93 		exit(EXIT_FAILURE);
94 	}
95 	tmp = strdup(in);
96 	if (!tmp)
97 	{
98 		fprintf(stderr, _("out of memory\n"));
99 		exit(EXIT_FAILURE);
100 	}
101 	return tmp;
102 }
103 
104 void
pg_free(void * ptr)105 pg_free(void *ptr)
106 {
107 	if (ptr != NULL)
108 		free(ptr);
109 }
110 
111 /*
112  * Frontend emulation of backend memory management functions.  Useful for
113  * programs that compile backend files.
114  */
115 void *
palloc(Size size)116 palloc(Size size)
117 {
118 	return pg_malloc_internal(size, 0);
119 }
120 
121 void *
palloc0(Size size)122 palloc0(Size size)
123 {
124 	return pg_malloc_internal(size, MCXT_ALLOC_ZERO);
125 }
126 
127 void *
palloc_extended(Size size,int flags)128 palloc_extended(Size size, int flags)
129 {
130 	return pg_malloc_internal(size, flags);
131 }
132 
133 void
pfree(void * pointer)134 pfree(void *pointer)
135 {
136 	pg_free(pointer);
137 }
138 
139 char *
pstrdup(const char * in)140 pstrdup(const char *in)
141 {
142 	return pg_strdup(in);
143 }
144 
145 char *
pnstrdup(const char * in,Size size)146 pnstrdup(const char *in, Size size)
147 {
148 	char	   *tmp;
149 	int			len;
150 
151 	if (!in)
152 	{
153 		fprintf(stderr,
154 				_("cannot duplicate null pointer (internal error)\n"));
155 		exit(EXIT_FAILURE);
156 	}
157 
158 	len = strnlen(in, size);
159 	tmp = malloc(len + 1);
160 	if (tmp == NULL)
161 	{
162 		fprintf(stderr, _("out of memory\n"));
163 		exit(EXIT_FAILURE);
164 	}
165 
166 	memcpy(tmp, in, len);
167 	tmp[len] = '\0';
168 
169 	return tmp;
170 }
171 
172 void *
repalloc(void * pointer,Size size)173 repalloc(void *pointer, Size size)
174 {
175 	return pg_realloc(pointer, size);
176 }
177