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