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: 0741bed95911bfcd5e371c7491b17b3f931ab23d $")
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/** Call talloc_memdup, setting the type on the new chunk correctly
406 *
407 * @param[in] ctx The talloc context to hang the result off.
408 * @param[in] in The data you want to duplicate.
409 * @param[in] inlen the length of the data to be duplicated.
410 * @return
411 * - Duplicated data.
412 * - NULL on error.
413 *
414 * @hidecallergraph
415 */
416uint8_t *talloc_typed_memdup(TALLOC_CTX *ctx, uint8_t const *in, size_t inlen)
417{
418 uint8_t *n;
419
420 n = talloc_memdup(ctx, in, inlen);
421 if (unlikely(!n)) return NULL;
422 talloc_set_type(n, uint8_t);
423
424 return n;
425}
426
427/** Call talloc_strdup, setting the type on the new chunk correctly
428 *
429 * For some bizarre reason the talloc string functions don't set the
430 * memory chunk type to char, which causes all kinds of issues with
431 * verifying fr_pair_ts.
432 *
433 * @param[in] ctx The talloc context to hang the result off.
434 * @param[in] p The string you want to duplicate.
435 * @return
436 * - Duplicated string.
437 * - NULL on error.
438 *
439 * @hidecallergraph
440 */
441char *talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
442{
443 char *n;
444
445 n = talloc_strdup(ctx, p);
446 if (unlikely(!n)) return NULL;
447 talloc_set_type(n, char);
448
449 return n;
450}
451
452/** Call talloc_strndup, setting the type on the new chunk correctly
453 *
454 * This function is similar to talloc_typed_strdup but gets the chunk
455 * length using talloc functions.
456 *
457 * @param[in] ctx The talloc context to hang the result off.
458 * @param[in] p The string you want to duplicate.
459 * @return
460 * - Duplicated string.
461 * - NULL on error.
462 *
463 * @hidecallergraph
464 */
465char *talloc_typed_strdup_buffer(TALLOC_CTX *ctx, char const *p)
466{
467 char *n;
468
469 n = talloc_strndup(ctx, p, talloc_array_length(p) - 1);
470 if (unlikely(!n)) return NULL;
471 talloc_set_type(n, char);
472
473 return n;
474}
475
476/** Call talloc vasprintf, setting the type on the new chunk correctly
477 *
478 * For some bizarre reason the talloc string functions don't set the
479 * memory chunk type to char, which causes all kinds of issues with
480 * verifying fr_pair_ts.
481 *
482 * @param[in] ctx The talloc context to hang the result off.
483 * @param[in] fmt The format string.
484 * @return
485 * - Formatted string.
486 * - NULL on error.
487 */
488char *talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt, ...)
489{
490 char *n;
491 va_list ap;
492
493 va_start(ap, fmt);
494 n = talloc_vasprintf(ctx, fmt, ap);
495 va_end(ap);
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 * @param[in] ap varadic arguments.
511 * @return
512 * - Formatted string.
513 * - NULL on error.
514 */
515char *talloc_typed_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
516{
517 char *n;
518
519 n = talloc_vasprintf(ctx, fmt, ap);
520 if (unlikely(!n)) return NULL;
521 talloc_set_type(n, char);
522
523 return n;
524}
525
526/** Binary safe strdup function
527 *
528 * @param[in] ctx the talloc context to allocate new buffer in.
529 * @param[in] in String to dup, may contain embedded '\0'.
530 * @return duped string.
531 */
532char *talloc_bstrdup(TALLOC_CTX *ctx, char const *in)
533{
534 char *p;
535 size_t inlen = talloc_array_length(in);
536
537 if (inlen == 0) inlen = 1;
538
539 p = talloc_array(ctx, char, inlen);
540 if (unlikely(!p)) return NULL;
541
542 /*
543 * C99 (7.21.1/2) - Length zero results in noop
544 *
545 * But ubsan still flags this, grrr.
546 */
547 if (inlen > 0) memcpy(p, in, inlen - 1);
548 p[inlen - 1] = '\0';
549
550 return p;
551}
552
553/** Binary safe strndup function
554 *
555 * @param[in] ctx he talloc context to allocate new buffer in.
556 * @param[in] in String to dup, may contain embedded '\0'.
557 * @param[in] inlen Number of bytes to dup.
558 * @return duped string.
559 */
560char *talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
561{
562 char *p;
563
564 p = talloc_array(ctx, char, inlen + 1);
565 if (unlikely(!p)) return NULL;
566
567 /*
568 * C99 (7.21.1/2) - Length zero results in noop
569 *
570 * But ubsan still flags this, grrr.
571 */
572 if (inlen > 0) memcpy(p, in, inlen);
573 p[inlen] = '\0';
574
575 return p;
576}
577
578/** Append a bstr to a bstr
579 *
580 * @param[in] ctx to allocated.
581 * @param[in] to string to append to.
582 * @param[in] from string to append from.
583 * @param[in] from_len Length of from.
584 * @return
585 * - Realloced buffer containing both to and from.
586 * - NULL on failure. To will still be valid.
587 */
588char *talloc_bstr_append(TALLOC_CTX *ctx, char *to, char const *from, size_t from_len)
589{
590 char *n;
591 size_t to_len = 0;
592
593 if (to) {
594 to_len = talloc_array_length(to);
595 if (to[to_len - 1] == '\0') to_len--; /* Inlen should be length of input string */
596 }
597
598 n = talloc_realloc_size(ctx, to, to_len + from_len + 1);
599 if (!n) {
600 fr_strerror_printf("Extending bstr buffer to %zu bytes failed", to_len + from_len + 1);
601 return NULL;
602 }
603
604 memcpy(n + to_len, from, from_len);
605 n[to_len + from_len] = '\0';
606 talloc_set_type(n, char);
607
608 return n;
609}
610
611/** Trim a bstr (char) buffer
612 *
613 * Reallocs to inlen + 1 and '\0' terminates the string buffer.
614 *
615 * @param[in] ctx to realloc buffer into.
616 * @param[in] in string to trim. Will be invalid after
617 * this function returns. If NULL a new zero terminated
618 * buffer of inlen bytes will be allocated.
619 * @param[in] inlen Length to trim string to.
620 * @return
621 * - The realloced string on success. in then points to invalid memory.
622 * - NULL on failure. In will still be valid.
623 */
624char *talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
625{
626 char *n;
627
628 if (!in) {
629 n = talloc_array(ctx, char, inlen);
630 n[0] = '\0';
631 return n;
632 }
633
634 n = talloc_realloc_size(ctx, in, inlen + 1);
635 if (unlikely(!n)) return NULL;
636
637 n[inlen] = '\0';
638 talloc_set_type(n, char);
639
640 return n;
641}
642
643/** Concatenate to + from
644 *
645 * @param[in] ctx to allocate realloced buffer in.
646 * @param[in] to talloc string buffer to append to.
647 * @param[in] from talloc string buffer to append.
648 * @return
649 * - NULL if to or from are NULL or if the realloc fails.
650 * Note: You'll still need to free to if this function
651 * returns NULL.
652 * - The concatenation of to + from. After this function
653 * returns to may point to invalid memory and should
654 * not be used.
655 */
656char *talloc_buffer_append_buffer(TALLOC_CTX *ctx, char *to, char const *from)
657{
658 size_t to_len, from_len, total_len;
659 char *out;
660
661 if (!to || !from) return NULL;
662
663 to_len = talloc_array_length(to);
664 from_len = talloc_array_length(from);
665 total_len = to_len + (from_len - 1);
666
667 out = talloc_realloc(ctx, to, char, total_len);
668 if (!out) return NULL;
669
670 memcpy(out + (to_len - 1), from, from_len);
671 out[total_len - 1] = '\0';
672
673 return out;
674}
675
676/** Concatenate to + ...
677 *
678 * @param[in] ctx to allocate realloced buffer in.
679 * @param[in] to talloc string buffer to append to.
680 * @param[in] argc how many variadic arguments were passed.
681 * @param[in] ... talloc string buffer(s) to append.
682 * Arguments can be NULL to simplify
683 * calling logic.
684 * @return
685 * - NULL if to or from are NULL or if the realloc fails.
686 * Note: You'll still need to free to if this function
687 * returns NULL.
688 * - The concatenation of to + from. After this function
689 * returns to may point to invalid memory and should
690 * not be used.
691 */
692char *talloc_buffer_append_variadic_buffer(TALLOC_CTX *ctx, char *to, int argc, ...)
693{
694 va_list ap_val, ap_len;
695 int i;
696
697 size_t to_len, total_len = 0;
698 char *out, *p;
699
700 if (!to) return NULL;
701
702 va_start(ap_val, argc);
703 va_copy(ap_len, ap_val);
704
705 total_len += to_len = talloc_array_length(to) - 1;
706
707 /*
708 * Figure out how much we need to realloc
709 */
710 for (i = 0; i < argc; i++) {
711 char *arg;
712
713 arg = va_arg(ap_len, char *);
714 if (!arg) continue;
715
716 total_len += (talloc_array_length(arg) - 1);
717 }
718
719 /*
720 * It's a noop...
721 */
722 if (total_len == to_len) {
723 va_end(ap_val);
724 va_end(ap_len);
725 return to;
726 }
727
728 out = talloc_realloc(ctx, to, char, total_len + 1);
729 if (!out) goto finish;
730
731 p = out + to_len;
732
733 /*
734 * Copy the args in
735 */
736 for (i = 0; i < argc; i++) {
737 char *arg;
738 size_t len;
739
740 arg = va_arg(ap_val, char *);
741 if (!arg) continue;
742
743 len = talloc_array_length(arg) - 1;
744
745 memcpy(p, arg, len);
746 p += len;
747 }
748 *p = '\0';
749
750finish:
751 va_end(ap_val);
752 va_end(ap_len);
753
754 return out;
755}
756
757/** Compares two talloced uint8_t arrays with memcmp
758 *
759 * Talloc arrays carry their length as part of the structure, so can be passed to a generic
760 * comparison function.
761 *
762 * @param a Pointer to first array.
763 * @param b Pointer to second array.
764 * @return
765 * - 0 if the arrays match.
766 * - a positive or negative integer otherwise.
767 */
768int talloc_memcmp_array(uint8_t const *a, uint8_t const *b)
769{
770 size_t a_len, b_len;
771
772 a_len = talloc_array_length(a);
773 b_len = talloc_array_length(b);
774
775 if (a_len > b_len) return +1;
776 if (a_len < b_len) return -1;
777
778 return memcmp(a, b, a_len);
779}
780
781/** Compares two talloced char arrays with memcmp
782 *
783 * Talloc arrays carry their length as part of the structure, so can be passed to a generic
784 * comparison function.
785 *
786 * @param a Pointer to first array.
787 * @param b Pointer to second array.
788 * @return
789 * - 0 if the arrays match.
790 * - a positive or negative integer otherwise.
791 */
792int talloc_memcmp_bstr(char const *a, char const *b)
793{
794 size_t a_len, b_len;
795
796 a_len = talloc_array_length(a);
797 b_len = talloc_array_length(b);
798
799 if (a_len > b_len) return +1;
800 if (a_len < b_len) return -1;
801
802 return memcmp(a, b, a_len);
803}
804
805/** Decrease the reference count on a ptr
806 *
807 * Ptr will be freed if count reaches zero.
808 *
809 * This is equivalent to talloc 1.0 behaviour of talloc_free.
810 *
811 * @param ptr to decrement ref count for.
812 * @return
813 * - 0 The memory was freed.
814 * - >0 How many references remain.
815 */
816int talloc_decrease_ref_count(void const *ptr)
817{
818 size_t ref_count;
819 void *to_free;
820
821 if (!ptr) return 0;
822
823 memcpy(&to_free, &ptr, sizeof(to_free));
824
825 ref_count = talloc_reference_count(to_free);
826 if (ref_count == 0) {
827 talloc_free(to_free);
828 } else {
829 talloc_unlink(talloc_parent(ptr), to_free);
830 }
831
832 return ref_count;
833}
834
835/** Add a NULL pointer to an array of pointers
836 *
837 * This is needed by some 3rd party libraries which take NULL terminated
838 * arrays for arguments.
839 *
840 * If allocation fails, NULL will be returned and the original array
841 * will not be touched.
842 *
843 * @param[in] array to null terminate. Will be invalidated (realloced).
844 * @return
845 * - NULL if array is NULL, or if reallocation fails.
846 * - A realloced version of array with an additional NULL element.
847 */
848void **talloc_array_null_terminate(void **array)
849{
850 size_t len;
851 TALLOC_CTX *ctx;
852 void **new;
853 size_t size;
854
855 if (!array) return NULL;
856
857 len = talloc_array_length(array);
858 ctx = talloc_parent(array);
859 size = talloc_get_size(array) / talloc_array_length(array);
860
861 new = _talloc_realloc_array(ctx, array, size, len + 1, talloc_get_name(array));
862 if (!new) return NULL;
863
864 new[len] = NULL;
865
866 return new;
867}
868
869/** Remove a NULL termination pointer from an array of pointers
870 *
871 * If the end of the array is not NULL, NULL will be returned (error).
872 *
873 * @param[in] array to null strip. Will be invalidated (realloced).
874 * @return
875 * - NULL if array is NULL, if terminating element is not NULL, or reallocation fails.
876 * - A realloced version of array without the terminating NULL element.
877 */
878void **talloc_array_null_strip(void **array)
879{
880 size_t len;
881 TALLOC_CTX *ctx;
882 void **new;
883 size_t size;
884
885 if (!array) return NULL;
886
887 len = talloc_array_length(array);
888 ctx = talloc_parent(array);
889 size = talloc_get_size(array) / talloc_array_length(array);
890
891 if ((len - 1) == 0) return NULL;
892
893 if (array[len - 1] != NULL) return NULL;
894
895 new = _talloc_realloc_array(ctx, array, size, len - 1, talloc_get_name(array));
896 if (!new) return NULL;
897
898 return new;
899}
900
901/** Concat an array of strings (not NULL terminated), with a string separator
902 *
903 * @param[out] out Where to write the resulting string.
904 * @param[in] array of strings to concat.
905 * @param[in] sep to insert between elements. May be NULL.
906 * @return
907 * - >= 0 on success - length of the string created.
908 * - <0 on failure. How many bytes we would need.
909 */
910fr_slen_t talloc_array_concat(fr_sbuff_t *out, char const * const *array, char const *sep)
911{
912 fr_sbuff_t our_out = FR_SBUFF(out);
913 size_t len = talloc_array_length(array);
914 char const * const * p;
915 char const * const * end;
916 fr_sbuff_escape_rules_t e_rules = {
917 .name = __FUNCTION__,
918 .chr = '\\'
919 };
920
921 if (sep) e_rules.subs[(uint8_t)*sep] = *sep;
922
923 for (p = array, end = array + len;
924 (p < end);
925 p++) {
926 if (*p) FR_SBUFF_RETURN(fr_sbuff_in_escape, &our_out, *p, strlen(*p), &e_rules);
927
928 if (sep && ((p + 1) < end)) {
929 FR_SBUFF_RETURN(fr_sbuff_in_strcpy, &our_out, sep);
930 }
931 }
932
933 FR_SBUFF_SET_RETURN(out, &our_out);
934}
935
936/** Callback to free the autofree ctx on global exit
937 *
938 */
939static int _autofree_on_exit(void *af)
940{
941 talloc_set_destructor(af, NULL);
942 return talloc_free(af);
943}
944
945/** Ensures in the autofree ctx is manually freed, things don't explode atexit
946 *
947 */
948static int _autofree_global_destructor(TALLOC_CTX *af)
949{
951}
952
954{
955 TALLOC_CTX *af = global_ctx;
956
957 if (!af) {
958 af = talloc_init_const("global_autofree_context");
959 talloc_set_destructor(af, _autofree_global_destructor);
960 if (unlikely(!af)) return NULL;
961
963 global_ctx = af;
964 }
965
966 return af;
967}
968
969/** Ensures in the autofree ctx is manually freed, things don't explode atexit
970 *
971 */
972static int _autofree_thread_local_destructor(TALLOC_CTX *af)
973{
975}
976
977/** Get a thread-safe autofreed ctx that will be freed when the thread or process exits
978 *
979 * @note This should be used in place of talloc_autofree_context (which is now deprecated)
980 * @note Will not be thread-safe if NULL tracking is enabled.
981 *
982 * @return A talloc ctx which will be freed when the thread or process exits.
983 */
985{
986 TALLOC_CTX *af = thread_local_ctx;
987
988 if (!af) {
989 af = talloc_init_const("thread_local_autofree_context");
990 talloc_set_destructor(af, _autofree_thread_local_destructor);
991 if (unlikely(!af)) return NULL;
992
994 }
995
996 return af;
997}
998
999
1003
1005{
1006 while (list->next != NULL) {
1007 TALLOC_CHILD_CTX *entry = list->next;
1008 TALLOC_CHILD_CTX *next = entry->next;
1009
1010 if (talloc_free(entry) < 0) return -1;
1011
1012 list->next = next;
1013 }
1014
1015 return 0;
1016}
1017
1018/** Allocate and initialize a TALLOC_CHILD_CTX
1019 *
1020 * The TALLOC_CHILD_CTX ensures ordering for allocators and
1021 * destructors. When a TALLOC_CHILD_CTX is created, it is added to
1022 * parent, in LIFO order. In contrast, the basic talloc operations
1023 * do not guarantee any kind of order.
1024 *
1025 * When the TALLOC_CHILD_CTX is freed, the children are freed in FILO
1026 * order. That process ensures that the children are freed before
1027 * the parent, and that the younger siblings are freed before the
1028 * older siblings.
1029 *
1030 * The idea is that if we have an initializer for A, which in turn
1031 * initializes B and C. When the memory is freed, we should do the
1032 * operations in the reverse order.
1033 */
1035{
1036 TALLOC_CHILD_CTX *child;
1037
1038 child = talloc_zero(ctx, TALLOC_CHILD_CTX);
1039 if (!child) return NULL;
1040
1041 talloc_set_destructor(child, _child_ctx_free);
1042 return child;
1043}
1044
1045/** Allocate a TALLOC_CHILD_CTX from a parent.
1046 *
1047 */
1049{
1050 TALLOC_CHILD_CTX *child;
1051
1052 child = talloc(parent, TALLOC_CHILD_CTX);
1053 if (!child) return NULL;
1054
1055 child->next = parent->next;
1056 parent->next = child;
1057 return child;
1058}
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:833
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: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)
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:848
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:532
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:1048
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:939
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:515
struct talloc_child_ctx_s * next
Definition talloc.c:1001
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:465
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:910
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:953
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:972
TALLOC_CHILD_CTX * talloc_child_ctx_init(TALLOC_CTX *ctx)
Allocate and initialize a TALLOC_CHILD_CTX.
Definition talloc.c:1034
int talloc_memcmp_array(uint8_t const *a, uint8_t const *b)
Compares two talloced uint8_t arrays with memcmp.
Definition talloc.c:768
char * talloc_buffer_append_variadic_buffer(TALLOC_CTX *ctx, char *to, int argc,...)
Concatenate to + ...
Definition talloc.c:692
char * talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
Trim a bstr (char) buffer.
Definition talloc.c:624
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition talloc.c:488
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:416
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:560
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:1004
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:441
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:816
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:984
char * talloc_buffer_append_buffer(TALLOC_CTX *ctx, char *to, char const *from)
Concatenate to + from.
Definition talloc.c:656
void ** talloc_array_null_strip(void **array)
Remove a NULL termination pointer from an array of pointers.
Definition talloc.c:878
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:588
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:792
static int _autofree_global_destructor(TALLOC_CTX *af)
Ensures in the autofree ctx is manually freed, things don't explode atexit.
Definition talloc.c:948
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:845
#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:1274
static size_t char fr_sbuff_t size_t inlen
Definition value.h:1012
static size_t char ** out
Definition value.h:1012