The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
talloc.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library 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 GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** Functions which we wish were included in the standard talloc distribution
18 *
19 * @file src/lib/util/talloc.c
20 *
21 * @copyright 2017 The FreeRADIUS server project
22 * @copyright 2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23 */
24RCSID("$Id: 7b7662e8009d6e6eea77ad90fe7eb8e8eb72a515 $")
25
26#include <freeradius-devel/util/atexit.h>
27#include <freeradius-devel/util/debug.h>
28#include <freeradius-devel/util/dlist.h>
29#include <freeradius-devel/util/syserror.h>
30
31
32static TALLOC_CTX *global_ctx;
33static _Thread_local TALLOC_CTX *thread_local_ctx;
34
35/** A wrapper that can be passed to tree or hash alloc functions that take a #fr_free_t
36 */
38{
40}
41
42/** Retrieve the current talloc NULL ctx
43 *
44 * Talloc doesn't provide a function to retrieve the top level memory tracking context.
45 * This function does that...
46 *
47 * @return the current talloc NULL context or NULL if memory tracking is not enabled.
48 */
49void *talloc_null_ctx(void)
50{
51 TALLOC_CTX *null_ctx;
52 bool *tmp;
53
54 tmp = talloc(NULL, bool);
55 null_ctx = talloc_parent(tmp);
56 talloc_free(tmp);
57
58 return null_ctx;
59}
60
61/** Called with the fire_ctx is freed
62 *
63 */
65{
66 if (d->ds) {
67 talloc_set_destructor(d->ds, NULL); /* Disarm the disarmer */
68 TALLOC_FREE(d->ds); /* Free the disarm trigger ctx */
69 }
70
71 return d->func(d->fire, d->uctx);
72}
73
74/** Called when the disarm_ctx ctx is freed
75 *
76 */
78{
79 talloc_set_destructor(ds->d, NULL); /* Disarm the destructor */
80 return talloc_free(ds->d); /* Free memory allocated to the destructor */
81}
82
83/** Add an additional destructor to a talloc chunk
84 *
85 * @param[in] fire_ctx When this ctx is freed the destructor function
86 * will be called.
87 * @param[in] disarm_ctx When this ctx is freed the destructor will be
88 * disarmed. May be NULL. #talloc_destructor_disarm
89 * may be used to disarm the destructor too.
90 * @param[in] func to call when the fire_ctx is freed.
91 * @param[in] uctx data to pass to the above function.
92 * @return
93 * - A handle to access the destructor on success.
94 * - NULL on failure.
95 */
96fr_talloc_destructor_t *talloc_destructor_add(TALLOC_CTX *fire_ctx, TALLOC_CTX *disarm_ctx,
97 fr_talloc_free_func_t func, void const *uctx)
98{
100
101 if (!fire_ctx) {
102 fr_strerror_const("No firing ctx provided when setting destructor");
103 return NULL;
104 }
105
106 d = talloc(fire_ctx, fr_talloc_destructor_t);
107 if (!d) {
108 oom:
109 fr_strerror_const("Out of Memory");
110 return NULL;
111 }
112
113 d->fire = fire_ctx;
114 d->func = func;
115 memcpy(&d->uctx, &uctx, sizeof(d->uctx));
116
117 if (disarm_ctx) {
119
120 ds = talloc(disarm_ctx, fr_talloc_destructor_disarm_t);
121 if (!ds) {
122 talloc_free(d);
123 goto oom;
124 }
125 ds->d = d;
126 d->ds = ds;
127 talloc_set_destructor(ds, _talloc_destructor_disarm);
128 }
129
130 talloc_set_destructor(d, _talloc_destructor_fire);
131
132 return d;
133}
134
135/** Disarm a destructor and free all memory allocated in the trigger ctxs
136 *
137 */
139{
140 if (d->ds) {
141 talloc_set_destructor(d->ds, NULL); /* Disarm the disarmer */
142 TALLOC_FREE(d->ds); /* Free the disarmer ctx */
143 }
144
145 talloc_set_destructor(d, NULL); /* Disarm the destructor */
146 talloc_free(d); /* Free the destructor ctx */
147}
148
149static int _talloc_link_ctx_free(UNUSED void *parent, void *child)
150{
151 talloc_free(child);
152
153 return 0;
154}
155
156/** Link two different parent and child contexts, so the child is freed before the parent
157 *
158 * @note This is not thread safe. Do not free parent before threads are joined, do not call from a
159 * child thread.
160 *
161 * @param parent who's fate the child should share.
162 * @param child bound to parent's lifecycle.
163 * @return
164 * - 0 on success.
165 * - -1 on failure.
166 */
167int talloc_link_ctx(TALLOC_CTX *parent, TALLOC_CTX *child)
168{
169 if (!talloc_destructor_add(parent, child, _talloc_link_ctx_free, child)) return -1;
170
171 return 0;
172}
173
174/** Return a page aligned talloc memory array
175 *
176 * Because we can't intercept talloc's malloc() calls, we need to do some tricks
177 * in order to get the first allocation in the array page aligned, and to limit
178 * the size of the array to a multiple of the page size.
179 *
180 * The reason for wanting a page aligned talloc array, is it allows us to
181 * mprotect() the pages that belong to the array.
182 *
183 * Talloc chunks appear to be allocated within the protected region, so this should
184 * catch frees too.
185 *
186 * @param[in] ctx to allocate array memory in.
187 * @param[out] start The first aligned address in the array.
188 * @param[in] alignment What alignment the memory chunk should have.
189 * @param[in] size How big to make the array. Will be corrected to a multiple
190 * of the page size. The actual array size will be size
191 * rounded to a multiple of the (page_size), + page_size
192 * @return
193 * - A talloc chunk on success.
194 * - NULL on failure.
195 */
196TALLOC_CTX *talloc_aligned_array(TALLOC_CTX *ctx, void **start, size_t alignment, size_t size)
197{
198 size_t rounded;
199 size_t array_size;
200 void *next;
201 TALLOC_CTX *array;
202
203 rounded = ROUND_UP(size, alignment); /* Round up to a multiple of the page size */
204 if (rounded == 0) rounded = alignment;
205
206 array_size = rounded + alignment;
207 array = talloc_array(ctx, uint8_t, array_size); /* Over allocate */
208 if (!array) {
209 fr_strerror_const("Out of memory");
210 return NULL;
211 }
212
213 next = (void *)ROUND_UP((uintptr_t)array, alignment); /* Round up address to the next multiple */
214 *start = next;
215
216 return array;
217}
218
219/** How big the chunk header is
220 *
221 * Non-zero portion will always fit in a uint8_t, so we don't need to worry about atomicity.
222 */
223static size_t t_hdr_size;
224
225/** Calculate the size of talloc chunk headers, once, on startup
226 *
227 */
228static void _talloc_hdr_size(void)
229{
230 TALLOC_CTX *pool;
231 void *chunk;
232
233 pool = talloc_pool(NULL, 1024); /* Allocate 1k of memory, this will always be bigger than the chunk header */
234 if (unlikely(pool == NULL)) {
235 oom:
236 fr_strerror_const("Out of memory");
237 return;
238 }
239 chunk = talloc_size(pool, 1); /* Get the starting address */
240 if (unlikely(chunk == NULL)) goto oom;
241
242 /*
243 * Sanity check... make sure the chunk is within the pool
244 * if it's not, we're in trouble.
245 */
246 if (!fr_cond_assert((chunk > pool) && ((uintptr_t)chunk < ((uintptr_t)pool + 1024)))) {
247 fr_strerror_const("Initial allocation outside of pool memory");
248 return;
249 }
250
251 /*
252 * Talloc returns the address after the chunk header, so
253 * the address of the pool is <malloc address> + <hdr_size>.
254 *
255 * If we allocate a chunk inside the pool, then the address
256 * of the chunk will be <malloc address> + <hdr_size> + <hdr_size>.
257 * If we subtrace the chunk from the pool address, we get
258 * the size of the talloc header.
259 */
260 t_hdr_size = (uintptr_t)chunk - (uintptr_t)pool;
261
262 talloc_free(pool); /* Free the memory we used */
263}
264
265/** Calculate the size of the talloc chunk header
266 *
267 * @return
268 * - >0 the size of the talloc chunk header.
269 * - -1 on error.
270 */
272{
273 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
274
275 if (t_hdr_size > 0) return t_hdr_size; /* We've already calculated it */
276
277 if (pthread_once(&once_control, _talloc_hdr_size) != 0) {
278 fr_strerror_printf("pthread_once failed: %s", fr_syserror(errno));
279 return -1;
280 }
281 if (t_hdr_size == 0) return -1; /* Callback should set error */
282
283 return t_hdr_size;
284}
285
286/** Return a page aligned talloc memory pool
287 *
288 * Because we can't intercept talloc's malloc() calls, we need to do some tricks
289 * in order to get the first allocation in the pool page aligned, and to limit
290 * the size of the pool to a multiple of the page size.
291 *
292 * The reason for wanting a page aligned talloc pool, is it allows us to
293 * mprotect() the pages that belong to the pool.
294 *
295 * Talloc chunks appear to be allocated within the protected region, so this should
296 * catch frees too.
297 *
298 * @param[in] ctx to allocate pool memory in.
299 * @param[out] start A page aligned address within the pool. This can be passed
300 * to mprotect().
301 * @param[out] end_len how many bytes to protect.
302 * @param[in] headers how much room we should allocate for talloc headers.
303 * This value should usually be >= 1.
304 * @param[in] size How big to make the pool. Will be corrected to a multiple
305 * of the page size. The actual pool size will be size
306 * rounded to a multiple of the (page_size), + page_size
307 */
308TALLOC_CTX *talloc_page_aligned_pool(TALLOC_CTX *ctx, void **start, size_t *end_len, unsigned int headers, size_t size)
309{
310 size_t rounded, alloced, page_size = (size_t)getpagesize();
311 size_t hdr_size;
312 void *next;
313 TALLOC_CTX *pool;
314
315 hdr_size = talloc_hdr_size();
316 size += (hdr_size * headers); /* Add more space for the chunks headers of the pool's children */
317 size += hdr_size; /* Add one more header to the pool for the padding allocation */
318
319 /*
320 * Allocate enough space for the padding header the other headers
321 * and the actual data, and sure it's a multiple of the page_size.
322 *
323 * |<--- page_size --->|<-- page_size -->|
324 * |<-- hdr_size -->|<-- size -->|
325 */
326 if (size % page_size == 0) {
327 rounded = size;
328 } else {
329 rounded = ROUND_UP(size, page_size);
330 }
331
332 /*
333 * Add another page, so that we can align the first allocation in
334 * the pool to a page boundary. We have no idea what chunk malloc
335 * will give to talloc, and what the first address after adding the
336 * pools header will be
337 */
338 alloced = rounded + page_size;
339 pool = talloc_pool(ctx, alloced);
340 if (!pool) {
341 fr_strerror_const("Out of memory");
342 return NULL;
343 }
344
345 /*
346 * If we didn't get lucky, and the first address in the pool is
347 * not the start of a page, we need to allocate some padding to
348 * get the first allocation in the pool to be on or after the
349 * start of the next page.
350 */
351 if ((uintptr_t)pool % page_size != 0) {
352 size_t pad_size;
353 void *padding;
354
355 next = (void *)ROUND_UP((uintptr_t)pool, page_size); /* Round up address to the next page */
356
357 /*
358 * We don't care if the first address if on a page
359 * boundary, just that it comes after one.
360 */
361 pad_size = ((uintptr_t)next - (uintptr_t)pool);
362 if (pad_size > hdr_size) {
363 pad_size -= hdr_size; /* Save ~111 bytes by not over-padding */
364 } else {
365 pad_size = 0; /* Allocate as few bytes as possible */
366 }
367
368 padding = talloc_size(pool, pad_size);
369 if (!fr_cond_assert(((uintptr_t)padding + (uintptr_t)pad_size) >= (uintptr_t)next)) {
370 fr_strerror_const("Failed padding pool memory");
371 return NULL;
372 }
373 } else {
374 next = pool;
375 }
376
377 *start = next; /* This is the address we feed into mprotect */
378 *end_len = rounded; /* This is how much memory we protect */
379
380 /*
381 * Start address must be page aligned
382 */
383 fr_assert(((uintptr_t)*start % page_size) == 0);
384
385 /*
386 * For our sanity, length must be a multiple of the page size.
387 * mprotect will silently protect an entire additional page
388 * if length is not a multiple of page size.
389 */
390 fr_assert(((uintptr_t)*end_len % page_size) == 0);
391
392 /*
393 * We can't protect pages before the pool
394 */
395 fr_assert(*start >= pool);
396
397 /*
398 * We can't protect pages after the pool
399 */
400 fr_assert(((uintptr_t)*start + *end_len) <= ((uintptr_t)pool + alloced));
401
402 return pool;
403}
404
405/** Version of talloc_realloc which zeroes out freshly allocated memory
406 *
407 * @param[in] ctx talloc ctx to allocate in.
408 * @param[in] ptr the pointer to the old memory.
409 * @param[in] elem_size the size of each element in the array.
410 * @param[in] count the number of elements in the array.
411 * @param[in] name the name of the new chunk.
412 * @return
413 * - A pointer to the new memory.
414 * - NULL on error.
415 */
416void *_talloc_realloc_zero(const void *ctx, void *ptr, size_t elem_size, unsigned count, const char *name)
417{
418 size_t old_size = talloc_get_size(ptr);
419 size_t new_size = elem_size * count;
420
421 void *new = _talloc_realloc_array(ctx, ptr, elem_size, count, name);
422 if (!new) return NULL;
423
424 if (new_size > old_size) {
425 memset((uint8_t *)new + old_size, 0, new_size - old_size);
426 }
427
428 return new;
429}
430
431/** Call talloc_memdup, setting the type on the new chunk correctly
432 *
433 * @param[in] ctx The talloc context to hang the result off.
434 * @param[in] in The data you want to duplicate.
435 * @param[in] inlen the length of the data to be duplicated.
436 * @return
437 * - Duplicated data.
438 * - NULL on error.
439 *
440 * @hidecallergraph
441 */
442uint8_t *talloc_typed_memdup(TALLOC_CTX *ctx, uint8_t const *in, size_t inlen)
443{
444 uint8_t *n;
445
446 n = talloc_memdup(ctx, in, inlen);
447 if (unlikely(!n)) return NULL;
448 talloc_set_type(n, uint8_t);
449
450 return n;
451}
452
453/** Call talloc_strdup, setting the type on the new chunk correctly
454 *
455 * For some bizarre reason the talloc string functions don't set the
456 * memory chunk type to char, which causes all kinds of issues with
457 * verifying fr_pair_ts.
458 *
459 * @param[in] ctx The talloc context to hang the result off.
460 * @param[in] p The string you want to duplicate.
461 * @return
462 * - Duplicated string.
463 * - NULL on error.
464 *
465 * @hidecallergraph
466 */
467char *talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
468{
469 char *n;
470
471 n = talloc_strdup(ctx, p);
472 if (unlikely(!n)) return NULL;
473 talloc_set_type(n, char);
474
475 return n;
476}
477
478/** Call talloc_strndup, setting the type on the new chunk correctly
479 *
480 * This function is similar to talloc_typed_strdup but gets the chunk
481 * length using talloc functions.
482 *
483 * @param[in] ctx The talloc context to hang the result off.
484 * @param[in] p The string you want to duplicate.
485 * @return
486 * - Duplicated string.
487 * - NULL on error.
488 *
489 * @hidecallergraph
490 */
491char *talloc_typed_strdup_buffer(TALLOC_CTX *ctx, char const *p)
492{
493 char *n;
494
495 n = talloc_strndup(ctx, p, talloc_array_length(p) - 1);
496 if (unlikely(!n)) return NULL;
497 talloc_set_type(n, char);
498
499 return n;
500}
501
502/** Call talloc vasprintf, setting the type on the new chunk correctly
503 *
504 * For some bizarre reason the talloc string functions don't set the
505 * memory chunk type to char, which causes all kinds of issues with
506 * verifying fr_pair_ts.
507 *
508 * @param[in] ctx The talloc context to hang the result off.
509 * @param[in] fmt The format string.
510 * @return
511 * - Formatted string.
512 * - NULL on error.
513 */
514char *talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt, ...)
515{
516 char *n;
517 va_list ap;
518
519 va_start(ap, fmt);
520 n = talloc_vasprintf(ctx, fmt, ap);
521 va_end(ap);
522 if (unlikely(!n)) return NULL;
523 talloc_set_type(n, char);
524
525 return n;
526}
527
528/** Call talloc vasprintf, setting the type on the new chunk correctly
529 *
530 * For some bizarre reason the talloc string functions don't set the
531 * memory chunk type to char, which causes all kinds of issues with
532 * verifying fr_pair_ts.
533 *
534 * @param[in] ctx The talloc context to hang the result off.
535 * @param[in] fmt The format string.
536 * @param[in] ap varadic arguments.
537 * @return
538 * - Formatted string.
539 * - NULL on error.
540 */
541char *talloc_typed_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
542{
543 char *n;
544
545 n = talloc_vasprintf(ctx, fmt, ap);
546 if (unlikely(!n)) return NULL;
547 talloc_set_type(n, char);
548
549 return n;
550}
551
552/** Binary safe strdup function
553 *
554 * @param[in] ctx the talloc context to allocate new buffer in.
555 * @param[in] in String to dup, may contain embedded '\0'.
556 * @return duped string.
557 */
558char *talloc_bstrdup(TALLOC_CTX *ctx, char const *in)
559{
560 char *p;
561 size_t inlen = talloc_array_length(in);
562
563 if (inlen == 0) inlen = 1;
564
565 p = talloc_array(ctx, char, inlen);
566 if (unlikely(!p)) return NULL;
567
568 /*
569 * C99 (7.21.1/2) - Length zero results in noop
570 *
571 * But ubsan still flags this, grrr.
572 */
573 if (inlen > 0) memcpy(p, in, inlen - 1);
574 p[inlen - 1] = '\0';
575
576 return p;
577}
578
579/** Binary safe strndup function
580 *
581 * @param[in] ctx he talloc context to allocate new buffer in.
582 * @param[in] in String to dup, may contain embedded '\0'.
583 * @param[in] inlen Number of bytes to dup.
584 * @return duped string.
585 */
586char *talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
587{
588 char *p;
589
590 p = talloc_array(ctx, char, inlen + 1);
591 if (unlikely(!p)) return NULL;
592
593 /*
594 * C99 (7.21.1/2) - Length zero results in noop
595 *
596 * But ubsan still flags this, grrr.
597 */
598 if (inlen > 0) memcpy(p, in, inlen);
599 p[inlen] = '\0';
600
601 return p;
602}
603
604/** Append a bstr to a bstr
605 *
606 * @param[in] ctx to allocated.
607 * @param[in] to string to append to.
608 * @param[in] from string to append from.
609 * @param[in] from_len Length of from.
610 * @return
611 * - Realloced buffer containing both to and from.
612 * - NULL on failure. To will still be valid.
613 */
614char *talloc_bstr_append(TALLOC_CTX *ctx, char *to, char const *from, size_t from_len)
615{
616 char *n;
617 size_t to_len = 0;
618
619 if (to) {
620 to_len = talloc_array_length(to);
621 if (to[to_len - 1] == '\0') to_len--; /* Inlen should be length of input string */
622 }
623
624 n = talloc_realloc_size(ctx, to, to_len + from_len + 1);
625 if (!n) {
626 fr_strerror_printf("Extending bstr buffer to %zu bytes failed", to_len + from_len + 1);
627 return NULL;
628 }
629
630 memcpy(n + to_len, from, from_len);
631 n[to_len + from_len] = '\0';
632 talloc_set_type(n, char);
633
634 return n;
635}
636
637/** Trim a bstr (char) buffer
638 *
639 * Reallocs to inlen + 1 and '\0' terminates the string buffer.
640 *
641 * @param[in] ctx to realloc buffer into.
642 * @param[in] in string to trim. Will be invalid after
643 * this function returns. If NULL a new zero terminated
644 * buffer of inlen bytes will be allocated.
645 * @param[in] inlen Length to trim string to.
646 * @return
647 * - The realloced string on success. in then points to invalid memory.
648 * - NULL on failure. In will still be valid.
649 */
650char *talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
651{
652 char *n;
653
654 if (!in) {
655 n = talloc_array(ctx, char, inlen);
656 n[0] = '\0';
657 return n;
658 }
659
660 n = talloc_realloc_size(ctx, in, inlen + 1);
661 if (unlikely(!n)) return NULL;
662
663 n[inlen] = '\0';
664 talloc_set_type(n, char);
665
666 return n;
667}
668
669/** Concatenate to + from
670 *
671 * @param[in] ctx to allocate realloced buffer in.
672 * @param[in] to talloc string buffer to append to.
673 * @param[in] from talloc string buffer to append.
674 * @return
675 * - NULL if to or from are NULL or if the realloc fails.
676 * Note: You'll still need to free to if this function
677 * returns NULL.
678 * - The concatenation of to + from. After this function
679 * returns to may point to invalid memory and should
680 * not be used.
681 */
682char *talloc_buffer_append_buffer(TALLOC_CTX *ctx, char *to, char const *from)
683{
684 size_t to_len, from_len, total_len;
685 char *out;
686
687 if (!to || !from) return NULL;
688
689 to_len = talloc_array_length(to);
690 from_len = talloc_array_length(from);
691 total_len = to_len + (from_len - 1);
692
693 out = talloc_realloc(ctx, to, char, total_len);
694 if (!out) return NULL;
695
696 memcpy(out + (to_len - 1), from, from_len);
697 out[total_len - 1] = '\0';
698
699 return out;
700}
701
702/** Concatenate to + ...
703 *
704 * @param[in] ctx to allocate realloced buffer in.
705 * @param[in] to talloc string buffer to append to.
706 * @param[in] argc how many variadic arguments were passed.
707 * @param[in] ... talloc string buffer(s) to append.
708 * Arguments can be NULL to simplify
709 * calling logic.
710 * @return
711 * - NULL if to or from are NULL or if the realloc fails.
712 * Note: You'll still need to free to if this function
713 * returns NULL.
714 * - The concatenation of to + from. After this function
715 * returns to may point to invalid memory and should
716 * not be used.
717 */
718char *talloc_buffer_append_variadic_buffer(TALLOC_CTX *ctx, char *to, int argc, ...)
719{
720 va_list ap_val, ap_len;
721 int i;
722
723 size_t to_len, total_len = 0;
724 char *out, *p;
725
726 if (!to) return NULL;
727
728 va_start(ap_val, argc);
729 va_copy(ap_len, ap_val);
730
731 total_len += to_len = talloc_array_length(to) - 1;
732
733 /*
734 * Figure out how much we need to realloc
735 */
736 for (i = 0; i < argc; i++) {
737 char *arg;
738
739 arg = va_arg(ap_len, char *);
740 if (!arg) continue;
741
742 total_len += (talloc_array_length(arg) - 1);
743 }
744
745 /*
746 * It's a noop...
747 */
748 if (total_len == to_len) {
749 va_end(ap_val);
750 va_end(ap_len);
751 return to;
752 }
753
754 out = talloc_realloc(ctx, to, char, total_len + 1);
755 if (!out) goto finish;
756
757 p = out + to_len;
758
759 /*
760 * Copy the args in
761 */
762 for (i = 0; i < argc; i++) {
763 char *arg;
764 size_t len;
765
766 arg = va_arg(ap_val, char *);
767 if (!arg) continue;
768
769 len = talloc_array_length(arg) - 1;
770
771 memcpy(p, arg, len);
772 p += len;
773 }
774 *p = '\0';
775
776finish:
777 va_end(ap_val);
778 va_end(ap_len);
779
780 return out;
781}
782
783/** Compares two talloced uint8_t arrays with memcmp
784 *
785 * Talloc arrays carry their length as part of the structure, so can be passed to a generic
786 * comparison function.
787 *
788 * @param a Pointer to first array.
789 * @param b Pointer to second array.
790 * @return
791 * - 0 if the arrays match.
792 * - a positive or negative integer otherwise.
793 */
794int talloc_memcmp_array(uint8_t const *a, uint8_t const *b)
795{
796 size_t a_len, b_len;
797
798 a_len = talloc_array_length(a);
799 b_len = talloc_array_length(b);
800
801 if (a_len > b_len) return +1;
802 if (a_len < b_len) return -1;
803
804 return memcmp(a, b, a_len);
805}
806
807/** Compares two talloced char arrays with memcmp
808 *
809 * Talloc arrays carry their length as part of the structure, so can be passed to a generic
810 * comparison function.
811 *
812 * @param a Pointer to first array.
813 * @param b Pointer to second array.
814 * @return
815 * - 0 if the arrays match.
816 * - a positive or negative integer otherwise.
817 */
818int talloc_memcmp_bstr(char const *a, char const *b)
819{
820 size_t a_len, b_len;
821
822 a_len = talloc_array_length(a);
823 b_len = talloc_array_length(b);
824
825 if (a_len > b_len) return +1;
826 if (a_len < b_len) return -1;
827
828 return memcmp(a, b, a_len);
829}
830
831/** Decrease the reference count on a ptr
832 *
833 * Ptr will be freed if count reaches zero.
834 *
835 * This is equivalent to talloc 1.0 behaviour of talloc_free.
836 *
837 * @param ptr to decrement ref count for.
838 * @return
839 * - 0 The memory was freed.
840 * - >0 How many references remain.
841 */
842int talloc_decrease_ref_count(void const *ptr)
843{
844 size_t ref_count;
845 void *to_free;
846
847 if (!ptr) return 0;
848
849 memcpy(&to_free, &ptr, sizeof(to_free));
850
851 ref_count = talloc_reference_count(to_free);
852 if (ref_count == 0) {
853 talloc_free(to_free);
854 } else {
855 talloc_unlink(talloc_parent(ptr), to_free);
856 }
857
858 return ref_count;
859}
860
861/** Add a NULL pointer to an array of pointers
862 *
863 * This is needed by some 3rd party libraries which take NULL terminated
864 * arrays for arguments.
865 *
866 * If allocation fails, NULL will be returned and the original array
867 * will not be touched.
868 *
869 * @param[in] array to null terminate. Will be invalidated (realloced).
870 * @return
871 * - NULL if array is NULL, or if reallocation fails.
872 * - A realloced version of array with an additional NULL element.
873 */
874void **talloc_array_null_terminate(void **array)
875{
876 size_t len;
877 TALLOC_CTX *ctx;
878 void **new;
879 size_t size;
880
881 if (!array) return NULL;
882
883 len = talloc_array_length(array);
884 ctx = talloc_parent(array);
885 size = talloc_get_size(array) / talloc_array_length(array);
886
887 new = _talloc_realloc_array(ctx, array, size, len + 1, talloc_get_name(array));
888 if (!new) return NULL;
889
890 new[len] = NULL;
891
892 return new;
893}
894
895/** Remove a NULL termination pointer from an array of pointers
896 *
897 * If the end of the array is not NULL, NULL will be returned (error).
898 *
899 * @param[in] array to null strip. Will be invalidated (realloced).
900 * @return
901 * - NULL if array is NULL, if terminating element is not NULL, or reallocation fails.
902 * - A realloced version of array without the terminating NULL element.
903 */
904void **talloc_array_null_strip(void **array)
905{
906 size_t len;
907 TALLOC_CTX *ctx;
908 void **new;
909 size_t size;
910
911 if (!array) return NULL;
912
913 len = talloc_array_length(array);
914 ctx = talloc_parent(array);
915 size = talloc_get_size(array) / talloc_array_length(array);
916
917 if ((len - 1) == 0) return NULL;
918
919 if (array[len - 1] != NULL) return NULL;
920
921 new = _talloc_realloc_array(ctx, array, size, len - 1, talloc_get_name(array));
922 if (!new) return NULL;
923
924 return new;
925}
926
927/** Concat an array of strings (not NULL terminated), with a string separator
928 *
929 * @param[out] out Where to write the resulting string.
930 * @param[in] array of strings to concat.
931 * @param[in] sep to insert between elements. May be NULL.
932 * @return
933 * - >= 0 on success - length of the string created.
934 * - <0 on failure. How many bytes we would need.
935 */
936fr_slen_t talloc_array_concat(fr_sbuff_t *out, char const * const *array, char const *sep)
937{
938 fr_sbuff_t our_out = FR_SBUFF(out);
939 size_t len = talloc_array_length(array);
940 char const * const * p;
941 char const * const * end;
942 fr_sbuff_escape_rules_t e_rules = {
943 .name = __FUNCTION__,
944 .chr = '\\'
945 };
946
947 if (sep) e_rules.subs[(uint8_t)*sep] = *sep;
948
949 for (p = array, end = array + len;
950 (p < end);
951 p++) {
952 if (*p) FR_SBUFF_RETURN(fr_sbuff_in_escape, &our_out, *p, strlen(*p), &e_rules);
953
954 if (sep && ((p + 1) < end)) {
955 FR_SBUFF_RETURN(fr_sbuff_in_strcpy, &our_out, sep);
956 }
957 }
958
959 FR_SBUFF_SET_RETURN(out, &our_out);
960}
961
962/** Callback to free the autofree ctx on global exit
963 *
964 */
965static int _autofree_on_exit(void *af)
966{
967 talloc_set_destructor(af, NULL);
968 return talloc_free(af);
969}
970
971/** Ensures in the autofree ctx is manually freed, things don't explode atexit
972 *
973 */
974static int _autofree_global_destructor(TALLOC_CTX *af)
975{
977}
978
980{
981 TALLOC_CTX *af = global_ctx;
982
983 if (!af) {
984 af = talloc_init_const("global_autofree_context");
985 talloc_set_destructor(af, _autofree_global_destructor);
986 if (unlikely(!af)) return NULL;
987
989 global_ctx = af;
990 }
991
992 return af;
993}
994
995/** Ensures in the autofree ctx is manually freed, things don't explode atexit
996 *
997 */
998static int _autofree_thread_local_destructor(TALLOC_CTX *af)
999{
1001}
1002
1003/** Get a thread-safe autofreed ctx that will be freed when the thread or process exits
1004 *
1005 * @note This should be used in place of talloc_autofree_context (which is now deprecated)
1006 * @note Will not be thread-safe if NULL tracking is enabled.
1007 *
1008 * @return A talloc ctx which will be freed when the thread or process exits.
1009 */
1011{
1012 TALLOC_CTX *af = thread_local_ctx;
1013
1014 if (!af) {
1015 af = talloc_init_const("thread_local_autofree_context");
1016 talloc_set_destructor(af, _autofree_thread_local_destructor);
1017 if (unlikely(!af)) return NULL;
1018
1020 }
1021
1022 return af;
1023}
1024
1025
1029
1031{
1032 while (list->next != NULL) {
1033 TALLOC_CHILD_CTX *entry = list->next;
1034 TALLOC_CHILD_CTX *next = entry->next;
1035
1036 if (talloc_free(entry) < 0) return -1;
1037
1038 list->next = next;
1039 }
1040
1041 return 0;
1042}
1043
1044/** Allocate and initialize a TALLOC_CHILD_CTX
1045 *
1046 * The TALLOC_CHILD_CTX ensures ordering for allocators and
1047 * destructors. When a TALLOC_CHILD_CTX is created, it is added to
1048 * parent, in LIFO order. In contrast, the basic talloc operations
1049 * do not guarantee any kind of order.
1050 *
1051 * When the TALLOC_CHILD_CTX is freed, the children are freed in FILO
1052 * order. That process ensures that the children are freed before
1053 * the parent, and that the younger siblings are freed before the
1054 * older siblings.
1055 *
1056 * The idea is that if we have an initializer for A, which in turn
1057 * initializes B and C. When the memory is freed, we should do the
1058 * operations in the reverse order.
1059 */
1061{
1062 TALLOC_CHILD_CTX *child;
1063
1064 child = talloc_zero(ctx, TALLOC_CHILD_CTX);
1065 if (!child) return NULL;
1066
1067 talloc_set_destructor(child, _child_ctx_free);
1068 return child;
1069}
1070
1071/** Allocate a TALLOC_CHILD_CTX from a parent.
1072 *
1073 */
1075{
1076 TALLOC_CHILD_CTX *child;
1077
1078 child = talloc(parent, TALLOC_CHILD_CTX);
1079 if (!child) return NULL;
1080
1081 child->next = parent->next;
1082 parent->next = child;
1083 return child;
1084}
va_end(args)
int n
Definition acutest.h:577
static int const char * fmt
Definition acutest.h:573
va_start(args, fmt)
unsigned int fr_atexit_global_disarm(bool uctx_scope, fr_atexit_t func, void const *uctx)
Remove a specific global destructor (without executing it)
Definition atexit.c:229
#define fr_atexit_thread_local_disarm(...)
Definition atexit.h:231
#define fr_atexit_global(_func, _uctx)
Add a free function to the global free list.
Definition atexit.h:59
#define fr_atexit_thread_local(_name, _free, _uctx)
Definition atexit.h:221
#define RCSID(id)
Definition build.h:485
#define unlikely(_x)
Definition build.h:383
#define UNUSED
Definition build.h:317
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:139
static fr_slen_t in
Definition dict.h:840
talloc_free(reap)
#define ROUND_UP(_num, _mul)
Round up - Works in all cases, but is slower.
Definition math.h:148
long int ssize_t
unsigned char uint8_t
ssize_t fr_slen_t
unsigned long int size_t
#define fr_assert(_expr)
Definition rad_assert.h:38
static char const * name
ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
Definition sbuff.c:1456
ssize_t fr_sbuff_in_escape(fr_sbuff_t *sbuff, char const *in, size_t inlen, fr_sbuff_escape_rules_t const *e_rules)
Print an escaped string to an sbuff.
Definition sbuff.c:1622
#define FR_SBUFF_RETURN(_func, _sbuff,...)
#define FR_SBUFF_SET_RETURN(_dst, _src)
#define FR_SBUFF(_sbuff_or_marker)
return count
Definition module.c:155
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
void ** talloc_array_null_terminate(void **array)
Add a NULL pointer to an array of pointers.
Definition talloc.c:874
static int _talloc_destructor_fire(fr_talloc_destructor_t *d)
Called with the fire_ctx is freed.
Definition talloc.c:64
char * talloc_bstrdup(TALLOC_CTX *ctx, char const *in)
Binary safe strdup function.
Definition talloc.c:558
static int _talloc_link_ctx_free(UNUSED void *parent, void *child)
Definition talloc.c:149
TALLOC_CHILD_CTX * talloc_child_ctx_alloc(TALLOC_CHILD_CTX *parent)
Allocate a TALLOC_CHILD_CTX from a parent.
Definition talloc.c:1074
static TALLOC_CTX * global_ctx
Definition talloc.c:32
static int _autofree_on_exit(void *af)
Callback to free the autofree ctx on global exit.
Definition talloc.c:965
char * talloc_typed_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition talloc.c:541
struct talloc_child_ctx_s * next
Definition talloc.c:1027
fr_talloc_destructor_t * talloc_destructor_add(TALLOC_CTX *fire_ctx, TALLOC_CTX *disarm_ctx, fr_talloc_free_func_t func, void const *uctx)
Add an additional destructor to a talloc chunk.
Definition talloc.c:96
char * talloc_typed_strdup_buffer(TALLOC_CTX *ctx, char const *p)
Call talloc_strndup, setting the type on the new chunk correctly.
Definition talloc.c:491
fr_slen_t talloc_array_concat(fr_sbuff_t *out, char const *const *array, char const *sep)
Concat an array of strings (not NULL terminated), with a string separator.
Definition talloc.c:936
ssize_t talloc_hdr_size(void)
Calculate the size of the talloc chunk header.
Definition talloc.c:271
TALLOC_CTX * talloc_autofree_context_global(void)
Definition talloc.c:979
static int _autofree_thread_local_destructor(TALLOC_CTX *af)
Ensures in the autofree ctx is manually freed, things don't explode atexit.
Definition talloc.c:998
TALLOC_CHILD_CTX * talloc_child_ctx_init(TALLOC_CTX *ctx)
Allocate and initialize a TALLOC_CHILD_CTX.
Definition talloc.c:1060
int talloc_memcmp_array(uint8_t const *a, uint8_t const *b)
Compares two talloced uint8_t arrays with memcmp.
Definition talloc.c:794
char * talloc_buffer_append_variadic_buffer(TALLOC_CTX *ctx, char *to, int argc,...)
Concatenate to + ...
Definition talloc.c:718
void * _talloc_realloc_zero(const void *ctx, void *ptr, size_t elem_size, unsigned count, const char *name)
Version of talloc_realloc which zeroes out freshly allocated memory.
Definition talloc.c:416
char * talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
Trim a bstr (char) buffer.
Definition talloc.c:650
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition talloc.c:514
TALLOC_CTX * talloc_aligned_array(TALLOC_CTX *ctx, void **start, size_t alignment, size_t size)
Return a page aligned talloc memory array.
Definition talloc.c:196
static int _talloc_destructor_disarm(fr_talloc_destructor_disarm_t *ds)
Called when the disarm_ctx ctx is freed.
Definition talloc.c:77
int talloc_link_ctx(TALLOC_CTX *parent, TALLOC_CTX *child)
Link two different parent and child contexts, so the child is freed before the parent.
Definition talloc.c:167
static void _talloc_hdr_size(void)
Calculate the size of talloc chunk headers, once, on startup.
Definition talloc.c:228
uint8_t * talloc_typed_memdup(TALLOC_CTX *ctx, uint8_t const *in, size_t inlen)
Call talloc_memdup, setting the type on the new chunk correctly.
Definition talloc.c:442
static _Thread_local TALLOC_CTX * thread_local_ctx
Definition talloc.c:33
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
Definition talloc.c:586
static size_t t_hdr_size
How big the chunk header is.
Definition talloc.c:223
static int _child_ctx_free(TALLOC_CHILD_CTX *list)
Definition talloc.c:1030
void * talloc_null_ctx(void)
Retrieve the current talloc NULL ctx.
Definition talloc.c:49
TALLOC_CTX * talloc_page_aligned_pool(TALLOC_CTX *ctx, void **start, size_t *end_len, unsigned int headers, size_t size)
Return a page aligned talloc memory pool.
Definition talloc.c:308
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition talloc.c:467
void talloc_free_data(void *data)
A wrapper that can be passed to tree or hash alloc functions that take a fr_free_t.
Definition talloc.c:37
int talloc_decrease_ref_count(void const *ptr)
Decrease the reference count on a ptr.
Definition talloc.c:842
TALLOC_CTX * talloc_autofree_context_thread_local(void)
Get a thread-safe autofreed ctx that will be freed when the thread or process exits.
Definition talloc.c:1010
char * talloc_buffer_append_buffer(TALLOC_CTX *ctx, char *to, char const *from)
Concatenate to + from.
Definition talloc.c:682
void ** talloc_array_null_strip(void **array)
Remove a NULL termination pointer from an array of pointers.
Definition talloc.c:904
char * talloc_bstr_append(TALLOC_CTX *ctx, char *to, char const *from, size_t from_len)
Append a bstr to a bstr.
Definition talloc.c:614
void talloc_destructor_disarm(fr_talloc_destructor_t *d)
Disarm a destructor and free all memory allocated in the trigger ctxs.
Definition talloc.c:138
int talloc_memcmp_bstr(char const *a, char const *b)
Compares two talloced char arrays with memcmp.
Definition talloc.c:818
static int _autofree_global_destructor(TALLOC_CTX *af)
Ensures in the autofree ctx is manually freed, things don't explode atexit.
Definition talloc.c:974
fr_talloc_free_func_t func
Free function.
Definition talloc.h:92
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
Definition talloc.h:112
fr_talloc_destructor_t * d
Destructor to disarm.
Definition talloc.h:102
void * uctx
uctx to pass to free function.
Definition talloc.h:93
void * fire
Parent chunk.
Definition talloc.h:90
int(* fr_talloc_free_func_t)(void *fire_ctx, void *uctx)
Definition talloc.h:80
fr_talloc_destructor_disarm_t * ds
Chunk to free.
Definition talloc.h:94
Structure to record a destructor to disarm if a child talloc chunk is freed.
Definition talloc.h:101
Structure to record a destructor operation on a specific talloc chunk.
Definition talloc.h:89
static fr_slen_t parent
Definition pair.h:839
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
static fr_slen_t data
Definition value.h:1288
static size_t char fr_sbuff_t size_t inlen
Definition value.h:1020
static size_t char ** out
Definition value.h:1020