suricata
util-mem.h
Go to the documentation of this file.
1 /* Copyright (C) 2007-2019 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
22  * \author Bill Meeks <billmeeks8@gmail.com>
23  *
24  * Utility Macros for memory management
25  *
26  * \todo Add wrappers for functions that allocate/free memory here.
27  * Currently we have malloc, calloc, realloc, strdup, strndup and
28  * free, but there are more.
29  */
30 
31 #ifndef __UTIL_MEM_H__
32 #define __UTIL_MEM_H__
33 
34 #include "util-atomic.h"
35 
36 #if CPPCHECK==1 || defined(__clang_analyzer__)
37 #define SCMalloc malloc
38 #define SCCalloc calloc
39 #define SCRealloc realloc
40 #define SCFree free
41 #define SCStrdup strdup
42 #define SCStrndup strndup
43 #define SCMallocAligned _mm_malloc
44 #define SCFreeAligned _mm_free
45 #else /* CPPCHECK */
46 
47 
48 #if defined(_WIN32) || defined(__WIN32)
49 #include "mm_malloc.h"
50 #endif
51 
52 SC_ATOMIC_EXTERN(unsigned int, engine_stage);
53 
54 /* Use this only if you want to debug memory allocation and free()
55  * It will log a lot of lines more, so think that is a performance killer */
56 
57 /* Uncomment this if you want to print memory allocations and free's() */
58 //#define DBG_MEM_ALLOC
59 
60 #ifdef DBG_MEM_ALLOC
61 
62 /* Uncomment this if you want to print mallocs at the startup (recommended) */
63 #define DBG_MEM_ALLOC_SKIP_STARTUP
64 
65 #define SCMalloc(a) ({ \
66  void *ptrmem = NULL; \
67  extern size_t global_mem; \
68  extern uint8_t print_mem_flag; \
69  \
70  ptrmem = malloc((a)); \
71  if (ptrmem == NULL && (a) > 0) { \
72  SCLogError(SC_ERR_MEM_ALLOC, "SCMalloc failed: %s, while trying " \
73  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)(a)); \
74  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
75  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
76  exit(EXIT_FAILURE); \
77  } \
78  } \
79  \
80  global_mem += (a); \
81  if (print_mem_flag == 1) { \
82  SCLogInfo("SCMalloc return at %p of size %"PRIuMAX, \
83  ptrmem, (uintmax_t)(a)); \
84  } \
85  (void*)ptrmem; \
86 })
87 
88 #define SCRealloc(x, a) ({ \
89  void *ptrmem = NULL; \
90  extern size_t global_mem; \
91  extern uint8_t print_mem_flag; \
92  \
93  ptrmem = realloc((x), (a)); \
94  if (ptrmem == NULL && (a) > 0) { \
95  SCLogError(SC_ERR_MEM_ALLOC, "SCRealloc failed: %s, while trying " \
96  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)(a)); \
97  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
98  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
99  exit(EXIT_FAILURE); \
100  } \
101  } \
102  \
103  global_mem += (a); \
104  if (print_mem_flag == 1) { \
105  SCLogInfo("SCRealloc return at %p (old:%p) of size %"PRIuMAX, \
106  ptrmem, (x), (uintmax_t)(a)); \
107  } \
108  (void*)ptrmem; \
109 })
110 
111 #define SCCalloc(nm, a) ({ \
112  void *ptrmem = NULL; \
113  extern size_t global_mem; \
114  extern uint8_t print_mem_flag; \
115  \
116  ptrmem = calloc((nm), (a)); \
117  if (ptrmem == NULL && (a) > 0) { \
118  SCLogError(SC_ERR_MEM_ALLOC, "SCCalloc failed: %s, while trying " \
119  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)a); \
120  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
121  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
122  exit(EXIT_FAILURE); \
123  } \
124  } \
125  \
126  global_mem += (a)*(nm); \
127  if (print_mem_flag == 1) { \
128  SCLogInfo("SCCalloc return at %p of size %"PRIuMAX" (nm) %"PRIuMAX, \
129  ptrmem, (uintmax_t)(a), (uintmax_t)(nm)); \
130  } \
131  (void*)ptrmem; \
132 })
133 
134 #define SCStrdup(a) ({ \
135  char *ptrmem = NULL; \
136  extern size_t global_mem; \
137  extern uint8_t print_mem_flag; \
138  size_t _len = strlen((a)); \
139  \
140  ptrmem = strdup((a)); \
141  if (ptrmem == NULL) { \
142  SCLogError(SC_ERR_MEM_ALLOC, "SCStrdup failed: %s, while trying " \
143  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)_len); \
144  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
145  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
146  exit(EXIT_FAILURE); \
147  } \
148  } \
149  \
150  global_mem += _len; \
151  if (print_mem_flag == 1) { \
152  SCLogInfo("SCStrdup return at %p of size %"PRIuMAX, \
153  ptrmem, (uintmax_t)_len); \
154  } \
155  (void*)ptrmem; \
156 })
157 
158 #ifndef HAVE_STRNDUP
159 #define SCStrndup(a, b) ({ \
160  char *ptrmem = NULL; \
161  extern size_t global_mem; \
162  extern uint8_t print_mem_flag; \
163  size_t _len = (b); \
164  \
165  size_t _scstrndup_len = _len + 1; \
166  ptrmem = (char *)malloc(_scstrndup_len); \
167  if (ptrmem == NULL) { \
168  SCLogError(SC_ERR_MEM_ALLOC, "SCStrndup failed: %s, while trying " \
169  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)_scstrndup_len); \
170  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
171  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
172  exit(EXIT_FAILURE); \
173  } \
174  } else { \
175  strlcpy(ptrmem, (a), _len); \
176  *(ptrmem + _len) = '\0'; \
177  } \
178  \
179  global_mem += _scstrndup_len; \
180  if (print_mem_flag == 1) { \
181  SCLogInfo("SCStrndup return at %p of size %"PRIuMAX, \
182  ptrmem, (uintmax_t)_scstrndup_len); \
183  } \
184  (void*)ptrmem; \
185 })
186 #else /* HAVE_STRNDUP */
187 #define SCStrndup(a, b) ({ \
188  char *ptrmem = NULL; \
189  extern size_t global_mem; \
190  extern uint8_t print_mem_flag; \
191  size_t _len = (b); \
192  \
193  ptrmem = strndup((a), _len); \
194  if (ptrmem == NULL) { \
195  SCLogError(SC_ERR_MEM_ALLOC, "SCStrndup failed: %s, while trying " \
196  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)_len); \
197  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
198  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
199  exit(EXIT_FAILURE); \
200  } \
201  } \
202  \
203  global_mem += _len; \
204  if (print_mem_flag == 1) { \
205  SCLogInfo("SCStrndup return at %p of size %"PRIuMAX, \
206  ptrmem, (uintmax_t)_len); \
207  } \
208  (void*)ptrmem; \
209 })
210 #endif
211 
212 #define SCFree(a) ({ \
213  extern uint8_t print_mem_flag; \
214  if (print_mem_flag == 1) { \
215  SCLogInfo("SCFree at %p", (a)); \
216  } \
217  free((a)); \
218 })
219 
220 #else /* !DBG_MEM_ALLOC */
221 
222 #define SCMalloc(a) ({ \
223  void *ptrmem = NULL; \
224  \
225  ptrmem = malloc((a)); \
226  if (ptrmem == NULL) { \
227  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
228  uintmax_t scmalloc_size_ = (uintmax_t)(a); \
229  SCLogError(SC_ERR_MEM_ALLOC, "SCMalloc failed: %s, while trying " \
230  "to allocate %"PRIuMAX" bytes", strerror(errno), scmalloc_size_); \
231  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
232  exit(EXIT_FAILURE); \
233  } \
234  } \
235  (void*)ptrmem; \
236 })
237 
238 #define SCRealloc(x, a) ({ \
239  void *ptrmem = NULL; \
240  \
241  ptrmem = realloc((x), (a)); \
242  if (ptrmem == NULL) { \
243  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
244  SCLogError(SC_ERR_MEM_ALLOC, "SCRealloc failed: %s, while trying " \
245  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)(a)); \
246  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
247  exit(EXIT_FAILURE); \
248  } \
249  } \
250  (void*)ptrmem; \
251 })
252 
253 #define SCCalloc(nm, a) ({ \
254  void *ptrmem = NULL; \
255  \
256  ptrmem = calloc((nm), (a)); \
257  if (ptrmem == NULL) { \
258  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
259  SCLogError(SC_ERR_MEM_ALLOC, "SCCalloc failed: %s, while trying " \
260  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)(a)); \
261  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
262  exit(EXIT_FAILURE); \
263  } \
264  } \
265  (void*)ptrmem; \
266 })
267 
268 #define SCStrdup(a) ({ \
269  char *ptrmem = NULL; \
270  \
271  ptrmem = strdup((a)); \
272  if (ptrmem == NULL) { \
273  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
274  size_t _scstrdup_len = strlen((a)); \
275  SCLogError(SC_ERR_MEM_ALLOC, "SCStrdup failed: %s, while trying " \
276  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)_scstrdup_len); \
277  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
278  exit(EXIT_FAILURE); \
279  } \
280  } \
281  (void*)ptrmem; \
282 })
283 
284 #ifndef HAVE_STRNDUP
285 #define SCStrndup(a, b) ({ \
286  char *ptrmem = NULL; \
287  size_t _len = (b); \
288  \
289  size_t _scstrndup_len = _len + 1; \
290  ptrmem = (char *)malloc(_scstrndup_len); \
291  if (ptrmem == NULL) { \
292  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
293  SCLogError(SC_ERR_MEM_ALLOC, "SCStrndup failed: %s, while trying " \
294  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)_scstrndup_len); \
295  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
296  exit(EXIT_FAILURE); \
297  } \
298  } else { \
299  strlcpy(ptrmem, (a), _len); \
300  *(ptrmem + _len) = '\0'; \
301  } \
302  (void*)ptrmem; \
303 })
304 #else /* HAVE_STRNDUP */
305 #define SCStrndup(a, b) ({ \
306  char *ptrmem = NULL; \
307  \
308  ptrmem = strndup((a), (b)); \
309  if (ptrmem == NULL) { \
310  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
311  size_t _scstrndup_len = (b); \
312  SCLogError(SC_ERR_MEM_ALLOC, "SCStrndup failed: %s, while trying " \
313  "to allocate %"PRIuMAX" bytes", strerror(errno), (uintmax_t)_scstrndup_len); \
314  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
315  exit(EXIT_FAILURE); \
316  } \
317  } \
318  (void*)ptrmem; \
319 })
320 #endif
321 
322 #define SCFree(a) ({ \
323  free(a); \
324 })
325 
326 #if defined(__WIN32) || defined(_WIN32)
327 
328 /** \brief wrapper for allocing aligned mem
329  * \param a size
330  * \param b alignement
331  */
332 #define SCMallocAligned(a, b) ({ \
333  void *ptrmem = NULL; \
334  \
335  ptrmem = _mm_malloc((a), (b)); \
336  if (ptrmem == NULL) { \
337  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
338  SCLogError(SC_ERR_MEM_ALLOC, "SCMallocAligned(posix_memalign) failed: %s, while trying " \
339  "to allocate %"PRIuMAX" bytes, alignment %"PRIuMAX, strerror(errno), (uintmax_t)(a), (uintmax_t)(b)); \
340  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
341  exit(EXIT_FAILURE); \
342  } \
343  } \
344  (void*)ptrmem; \
345 })
346 
347 /** \brief Free aligned memory
348  *
349  * Not needed for mem alloc'd by posix_memalign,
350  * but for possible future use of _mm_malloc needing
351  * _mm_free.
352  */
353 #define SCFreeAligned(a) ({ \
354  _mm_free(a); \
355 })
356 
357 #else /* !win */
358 
359 /** \brief wrapper for allocing aligned mem
360  * \param a size
361  * \param b alignement
362  */
363 #define SCMallocAligned(a, b) ({ \
364  void *ptrmem = NULL; \
365  \
366  int _r = posix_memalign(&ptrmem, (b), (a)); \
367  if (_r != 0 || ptrmem == NULL) { \
368  if (ptrmem != NULL) { \
369  free(ptrmem); \
370  ptrmem = NULL; \
371  } \
372  if (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT) {\
373  SCLogError(SC_ERR_MEM_ALLOC, "SCMallocAligned(posix_memalign) failed: %s, while trying " \
374  "to allocate %"PRIuMAX" bytes, alignment %"PRIuMAX, strerror(errno), (uintmax_t)a, (uintmax_t)b); \
375  SCLogError(SC_ERR_FATAL, "Out of memory. The engine cannot be initialized. Exiting..."); \
376  exit(EXIT_FAILURE); \
377  } \
378  } \
379  (void*)ptrmem; \
380 })
381 
382 /** \brief Free aligned memory
383  *
384  * Not needed for mem alloc'd by posix_memalign,
385  * but for possible future use of _mm_malloc needing
386  * _mm_free.
387  */
388 #define SCFreeAligned(a) ({ \
389  free(a); \
390 })
391 
392 #endif /* __WIN32 */
393 
394 #endif /* DBG_MEM_ALLOC */
395 
396 #endif /* CPPCHECK */
397 
398 #endif /* __UTIL_MEM_H__ */
399 
SC_ATOMIC_EXTERN(unsigned int, engine_stage)