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