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: bc2a12488c2f12b006078df9375ece98e19e6b16 $")
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 ssize_t hdr_size;
312 void *next;
313 TALLOC_CTX *pool;
314
315 hdr_size = talloc_hdr_size();
316 if (hdr_size < 0) return NULL;
317
318 size += (hdr_size * headers); /* Add more space for the chunks headers of the pool's children */
319 size += hdr_size; /* Add one more header to the pool for the padding allocation */
320
321 /*
322 * Allocate enough space for the padding header the other headers
323 * and the actual data, and sure it's a multiple of the page_size.
324 *
325 * |<--- page_size --->|<-- page_size -->|
326 * |<-- hdr_size -->|<-- size -->|
327 */
328 if (size % page_size == 0) {
329 rounded = size;
330 } else {
331 rounded = ROUND_UP(size, page_size);
332 }
333
334 /*
335 * Add another page, so that we can align the first allocation in
336 * the pool to a page boundary. We have no idea what chunk malloc
337 * will give to talloc, and what the first address after adding the
338 * pools header will be
339 */
340 alloced = rounded + page_size;
341 pool = talloc_pool(ctx, alloced);
342 if (!pool) {
343 fr_strerror_const("Out of memory");
344 return NULL;
345 }
346
347 /*
348 * If we didn't get lucky, and the first address in the pool is
349 * not the start of a page, we need to allocate some padding to
350 * get the first allocation in the pool to be on or after the
351 * start of the next page.
352 */
353 if ((uintptr_t)pool % page_size != 0) {
354 size_t pad_size;
355 void *padding;
356
357 next = (void *)ROUND_UP((uintptr_t)pool, page_size); /* Round up address to the next page */
358
359 /*
360 * We don't care if the first address if on a page
361 * boundary, just that it comes after one.
362 */
363 pad_size = ((uintptr_t)next - (uintptr_t)pool);
364 if (pad_size > (size_t) hdr_size) {
365 pad_size -= hdr_size; /* Save ~111 bytes by not over-padding */
366 } else {
367 pad_size = 0; /* Allocate as few bytes as possible */
368 }
369
370 padding = talloc_size(pool, pad_size);
371 if (!fr_cond_assert(((uintptr_t)padding + (uintptr_t)pad_size) >= (uintptr_t)next)) {
372 fr_strerror_const("Failed padding pool memory");
373 return NULL;
374 }
375 } else {
376 next = pool;
377 }
378
379 *start = next; /* This is the address we feed into mprotect */
380 *end_len = rounded; /* This is how much memory we protect */
381
382 /*
383 * Start address must be page aligned
384 */
385 fr_assert(((uintptr_t)*start % page_size) == 0);
386
387 /*
388 * For our sanity, length must be a multiple of the page size.
389 * mprotect will silently protect an entire additional page
390 * if length is not a multiple of page size.
391 */
392 fr_assert(((uintptr_t)*end_len % page_size) == 0);
393
394 /*
395 * We can't protect pages before the pool
396 */
397 fr_assert(*start >= pool);
398
399 /*
400 * We can't protect pages after the pool
401 */
402 fr_assert(((uintptr_t)*start + *end_len) <= ((uintptr_t)pool + alloced));
403
404 return pool;
405}
406
407/** Version of talloc_realloc which zeroes out freshly allocated memory
408 *
409 * @param[in] ctx talloc ctx to allocate in.
410 * @param[in] ptr the pointer to the old memory.
411 * @param[in] elem_size the size of each element in the array.
412 * @param[in] count the number of elements in the array.
413 * @param[in] name the name of the new chunk.
414 * @return
415 * - A pointer to the new memory.
416 * - NULL on error.
417 */
418void *_talloc_realloc_zero(const void *ctx, void *ptr, size_t elem_size, unsigned count, const char *name)
419{
420 size_t old_size = talloc_get_size(ptr);
421 size_t new_size;
422
423 void *new = _talloc_realloc_array(ctx, ptr, elem_size, count, name);
424 if (!new) return NULL;
425
426 new_size = talloc_array_length((uint8_t *) new);
427 if (new_size > old_size) {
428 memset((uint8_t *)new + old_size, 0, new_size - old_size);
429 }
430
431 return new;
432}
433
434/** Call talloc_memdup, setting the type on the new chunk correctly
435 *
436 * @param[in] ctx The talloc context to hang the result off.
437 * @param[in] in The data you want to duplicate.
438 * @param[in] inlen the length of the data to be duplicated.
439 * @return
440 * - Duplicated data.
441 * - NULL on error.
442 *
443 * @hidecallergraph
444 */
445uint8_t *talloc_typed_memdup(TALLOC_CTX *ctx, uint8_t const *in, size_t inlen)
446{
447 uint8_t *n;
448
449 n = talloc_memdup(ctx, in, inlen);
450 if (unlikely(!n)) return NULL;
451 talloc_set_type(n, uint8_t);
452
453 return n;
454}
455
456/** Call talloc_strdup, setting the type on the new chunk correctly
457 *
458 * For some bizarre reason the talloc string functions don't set the
459 * memory chunk type to char, which causes all kinds of issues with
460 * verifying fr_pair_ts.
461 *
462 * @param[in] ctx The talloc context to hang the result off.
463 * @param[in] p The string you want to duplicate.
464 * @return
465 * - Duplicated string.
466 * - NULL on error.
467 *
468 * @hidecallergraph
469 */
470char *talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
471{
472 char *n;
473
474#undef talloc_strdup
475 n = talloc_strdup(ctx, p);
476 if (unlikely(!n)) return NULL;
477 talloc_set_type(n, char);
478
479 return n;
480}
481
482/** Call talloc_strndup, setting the type on the new chunk correctly
483 *
484 * This function is similar to talloc_typed_strdup but gets the chunk
485 * length using talloc functions.
486 *
487 * @param[in] ctx The talloc context to hang the result off.
488 * @param[in] p The string you want to duplicate.
489 * @return
490 * - Duplicated string.
491 * - NULL on error.
492 *
493 * @hidecallergraph
494 */
495char *talloc_typed_strdup_buffer(TALLOC_CTX *ctx, char const *p)
496{
497 char *n;
498
499 n = talloc_strndup(ctx, p, talloc_strlen(p));
500 if (unlikely(!n)) return NULL;
501 talloc_set_type(n, char);
502
503 return n;
504}
505
506/** Call talloc_strndup, 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] p The string you want to duplicate.
514 * @param[in] len The length of the string
515 * @return
516 * - Duplicated string.
517 * - NULL on error.
518 *
519 * @hidecallergraph
520 */
521char *talloc_typed_strndup(TALLOC_CTX *ctx, char const *p, size_t len)
522{
523 char *n;
524
525#undef talloc_strndup
526 n = talloc_strndup(ctx, p, len);
527 if (unlikely(!n)) return NULL;
528 talloc_set_type(n, char);
529
530 return n;
531}
532
533/** Call talloc vasprintf, setting the type on the new chunk correctly
534 *
535 * For some bizarre reason the talloc string functions don't set the
536 * memory chunk type to char, which causes all kinds of issues with
537 * verifying fr_pair_ts.
538 *
539 * @param[in] ctx The talloc context to hang the result off.
540 * @param[in] fmt The format string.
541 * @return
542 * - Formatted string.
543 * - NULL on error.
544 */
545char *talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt, ...)
546{
547 char *n;
548 va_list ap;
549
550 va_start(ap, fmt);
551 n = talloc_vasprintf(ctx, fmt, ap);
552 va_end(ap);
553 if (unlikely(!n)) return NULL;
554 talloc_set_type(n, char);
555
556 return n;
557}
558
559/** Call talloc vasprintf, setting the type on the new chunk correctly
560 *
561 * For some bizarre reason the talloc string functions don't set the
562 * memory chunk type to char, which causes all kinds of issues with
563 * verifying fr_pair_ts.
564 *
565 * @param[in] ctx The talloc context to hang the result off.
566 * @param[in] fmt The format string.
567 * @param[in] ap varadic arguments.
568 * @return
569 * - Formatted string.
570 * - NULL on error.
571 */
572char *talloc_typed_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
573{
574 char *n;
575
576 n = talloc_vasprintf(ctx, fmt, ap);
577 if (unlikely(!n)) return NULL;
578 talloc_set_type(n, char);
579
580 return n;
581}
582
583/** Binary safe strdup function
584 *
585 * @param[in] ctx the talloc context to allocate new buffer in.
586 * @param[in] in String to dup, may contain embedded '\0'.
587 * @return duped string.
588 */
589char *talloc_bstrdup(TALLOC_CTX *ctx, char const *in)
590{
591 char *p;
592 size_t inlen = talloc_array_length(in);
593
594 if (inlen == 0) inlen = 1;
595
596 p = talloc_array(ctx, char, inlen);
597 if (unlikely(!p)) return NULL;
598
599 /*
600 * C99 (7.21.1/2) - Length zero results in noop
601 *
602 * But ubsan still flags this, grrr.
603 */
604 if (inlen > 0) memcpy(p, in, inlen - 1);
605 p[inlen - 1] = '\0';
606
607 return p;
608}
609
610/** Binary safe strndup function
611 *
612 * @param[in] ctx he talloc context to allocate new buffer in.
613 * @param[in] in String to dup, may contain embedded '\0'.
614 * @param[in] inlen Number of bytes to dup.
615 * @return duped string.
616 */
617char *talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
618{
619 char *p;
620
621 p = talloc_array(ctx, char, inlen + 1);
622 if (unlikely(!p)) return NULL;
623
624 /*
625 * C99 (7.21.1/2) - Length zero results in noop
626 *
627 * But ubsan still flags this, grrr.
628 */
629 if (inlen > 0) memcpy(p, in, inlen);
630 p[inlen] = '\0';
631
632 return p;
633}
634
635/** Append a bstr to a bstr
636 *
637 * @param[in] ctx to allocated.
638 * @param[in] to string to append to.
639 * @param[in] from string to append from.
640 * @param[in] from_len Length of from.
641 * @return
642 * - Realloced buffer containing both to and from.
643 * - NULL on failure. To will still be valid.
644 */
645char *talloc_bstr_append(TALLOC_CTX *ctx, char *to, char const *from, size_t from_len)
646{
647 char *n;
648 size_t to_len = 0;
649
650 if (to) {
651 to_len = talloc_array_length(to);
652 if (to[to_len - 1] == '\0') to_len--; /* Inlen should be length of input string */
653 }
654
655 n = talloc_realloc_size(ctx, to, to_len + from_len + 1);
656 if (!n) {
657 fr_strerror_printf("Extending bstr buffer to %zu bytes failed", to_len + from_len + 1);
658 return NULL;
659 }
660
661 memcpy(n + to_len, from, from_len);
662 n[to_len + from_len] = '\0';
663 talloc_set_type(n, char);
664
665 return n;
666}
667
668/** Trim a bstr (char) buffer
669 *
670 * Reallocs to inlen + 1 and '\0' terminates the string buffer.
671 *
672 * @param[in] ctx to realloc buffer into.
673 * @param[in] in string to trim. Will be invalid after
674 * this function returns. If NULL a new zero terminated
675 * buffer of inlen bytes will be allocated.
676 * @param[in] inlen Length to trim string to.
677 * @return
678 * - The realloced string on success. in then points to invalid memory.
679 * - NULL on failure. In will still be valid.
680 */
681char *talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
682{
683 char *n;
684
685 if (!in) {
686 n = talloc_array(ctx, char, inlen + 1);
687 if (!n) return NULL;
688 n[0] = '\0';
689 return n;
690 }
691
692 n = talloc_realloc_size(ctx, in, inlen + 1);
693 if (unlikely(!n)) return NULL;
694
695 n[inlen] = '\0';
696 talloc_set_type(n, char);
697
698 return n;
699}
700
701/** Concatenate to + from
702 *
703 * @param[in] ctx to allocate realloced buffer in.
704 * @param[in] to talloc string buffer to append to.
705 * @param[in] from talloc string buffer to append.
706 * @return
707 * - NULL if to or from are NULL or if the realloc fails.
708 * Note: You'll still need to free to if this function
709 * returns NULL.
710 * - The concatenation of to + from. After this function
711 * returns to may point to invalid memory and should
712 * not be used.
713 */
714char *talloc_buffer_append_buffer(TALLOC_CTX *ctx, char *to, char const *from)
715{
716 size_t to_len, from_len, total_len;
717 char *out;
718
719 if (!to || !from) return NULL;
720
721 to_len = talloc_array_length(to);
722 from_len = talloc_array_length(from);
723 total_len = to_len + (from_len - 1);
724
725 out = talloc_realloc(ctx, to, char, total_len);
726 if (!out) return NULL;
727
728 memcpy(out + (to_len - 1), from, from_len);
729 out[total_len - 1] = '\0';
730
731 return out;
732}
733
734/** Concatenate to + ...
735 *
736 * @param[in] ctx to allocate realloced buffer in.
737 * @param[in] to talloc string buffer to append to.
738 * @param[in] argc how many variadic arguments were passed.
739 * @param[in] ... talloc string buffer(s) to append.
740 * Arguments can be NULL to simplify
741 * calling logic.
742 * @return
743 * - NULL if to or from are NULL or if the realloc fails.
744 * Note: You'll still need to free to if this function
745 * returns NULL.
746 * - The concatenation of to + from. After this function
747 * returns to may point to invalid memory and should
748 * not be used.
749 */
750char *talloc_buffer_append_variadic_buffer(TALLOC_CTX *ctx, char *to, int argc, ...)
751{
752 va_list ap_val, ap_len;
753 int i;
754
755 size_t to_len, total_len = 0;
756 char *out, *p;
757
758 if (!to) return NULL;
759
760 va_start(ap_val, argc);
761 va_copy(ap_len, ap_val);
762
763 total_len += to_len = talloc_strlen(to);
764
765 /*
766 * Figure out how much we need to realloc
767 */
768 for (i = 0; i < argc; i++) {
769 char *arg;
770
771 arg = va_arg(ap_len, char *);
772 if (!arg) continue;
773
774 total_len += (talloc_strlen(arg));
775 }
776
777 /*
778 * It's a noop...
779 */
780 if (total_len == to_len) {
781 va_end(ap_val);
782 va_end(ap_len);
783 return to;
784 }
785
786 out = talloc_realloc(ctx, to, char, total_len + 1);
787 if (!out) goto finish;
788
789 p = out + to_len;
790
791 /*
792 * Copy the args in
793 */
794 for (i = 0; i < argc; i++) {
795 char *arg;
796 size_t len;
797
798 arg = va_arg(ap_val, char *);
799 if (!arg) continue;
800
801 len = talloc_strlen(arg);
802
803 memcpy(p, arg, len);
804 p += len;
805 }
806 *p = '\0';
807
808finish:
809 va_end(ap_val);
810 va_end(ap_len);
811
812 return out;
813}
814
815/** Compares two talloced uint8_t arrays with memcmp
816 *
817 * Talloc arrays carry their length as part of the structure, so can be passed to a generic
818 * comparison function.
819 *
820 * @param a Pointer to first array.
821 * @param b Pointer to second array.
822 * @return
823 * - 0 if the arrays match.
824 * - a positive or negative integer otherwise.
825 */
826int talloc_memcmp_array(uint8_t const *a, uint8_t const *b)
827{
828 size_t a_len, b_len;
829
830 a_len = talloc_array_length(a);
831 b_len = talloc_array_length(b);
832
833 if (a_len > b_len) return +1;
834 if (a_len < b_len) return -1;
835
836 return memcmp(a, b, a_len);
837}
838
839/** Compares two talloced char arrays with memcmp
840 *
841 * Talloc arrays carry their length as part of the structure, so can be passed to a generic
842 * comparison function.
843 *
844 * @param a Pointer to first array.
845 * @param b Pointer to second array.
846 * @return
847 * - 0 if the arrays match.
848 * - a positive or negative integer otherwise.
849 */
850int talloc_memcmp_bstr(char const *a, char const *b)
851{
852 size_t a_len, b_len;
853
854 a_len = talloc_array_length(a);
855 b_len = talloc_array_length(b);
856
857 if (a_len > b_len) return +1;
858 if (a_len < b_len) return -1;
859
860 return memcmp(a, b, a_len);
861}
862
863/** Decrease the reference count on a ptr
864 *
865 * Ptr will be freed if count reaches zero.
866 *
867 * This is equivalent to talloc 1.0 behaviour of talloc_free.
868 *
869 * @param ptr to decrement ref count for.
870 * @return
871 * - 0 The memory was freed.
872 * - >0 How many references remain.
873 */
874int talloc_decrease_ref_count(void const *ptr)
875{
876 size_t ref_count;
877 void *to_free;
878
879 if (!ptr) return 0;
880
881 memcpy(&to_free, &ptr, sizeof(to_free));
882
883 ref_count = talloc_reference_count(to_free);
884 if (ref_count == 0) {
885 talloc_free(to_free);
886 } else {
887 talloc_unlink(talloc_parent(ptr), to_free);
888 }
889
890 return ref_count;
891}
892
893/** Add a NULL pointer to an array of pointers
894 *
895 * This is needed by some 3rd party libraries which take NULL terminated
896 * arrays for arguments.
897 *
898 * If allocation fails, NULL will be returned and the original array
899 * will not be touched.
900 *
901 * @param[in] array to null terminate. Will be invalidated (realloced).
902 * @return
903 * - NULL if array is NULL, or if reallocation fails.
904 * - A realloced version of array with an additional NULL element.
905 */
906void **talloc_array_null_terminate(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 new = _talloc_realloc_array(ctx, array, size, len + 1, talloc_get_name(array));
920 if (!new) return NULL;
921
922 new[len] = NULL;
923
924 return new;
925}
926
927/** Remove a NULL termination pointer from an array of pointers
928 *
929 * If the end of the array is not NULL, NULL will be returned (error).
930 *
931 * @param[in] array to null strip. Will be invalidated (realloced).
932 * @return
933 * - NULL if array is NULL, if terminating element is not NULL, or reallocation fails.
934 * - A realloced version of array without the terminating NULL element.
935 */
936void **talloc_array_null_strip(void **array)
937{
938 size_t len;
939 TALLOC_CTX *ctx;
940 void **new;
941 size_t size;
942
943 if (!array) return NULL;
944
945 len = talloc_array_length(array);
946 ctx = talloc_parent(array);
947 size = talloc_get_size(array) / talloc_array_length(array);
948
949 if ((len - 1) == 0) return NULL;
950
951 if (array[len - 1] != NULL) return NULL;
952
953 new = _talloc_realloc_array(ctx, array, size, len - 1, talloc_get_name(array));
954 if (!new) return NULL;
955
956 return new;
957}
958
959/** Callback to free the autofree ctx on global exit
960 *
961 */
962static int _autofree_on_exit(void *af)
963{
964 talloc_set_destructor(af, NULL);
965 return talloc_free(af);
966}
967
968/** Ensures in the autofree ctx is manually freed, things don't explode atexit
969 *
970 */
971static int _autofree_global_destructor(TALLOC_CTX *af)
972{
974}
975
977{
978 TALLOC_CTX *af = global_ctx;
979
980 if (!af) {
981 af = talloc_init_const("global_autofree_context");
982 if (unlikely(!af)) return NULL;
983
984 talloc_set_destructor(af, _autofree_global_destructor);
985
987 global_ctx = af;
988 }
989
990 return af;
991}
992
993/** Ensures in the autofree ctx is manually freed, things don't explode atexit
994 *
995 */
996static int _autofree_thread_local_destructor(TALLOC_CTX *af)
997{
999}
1000
1001/** Get a thread-safe autofreed ctx that will be freed when the thread or process exits
1002 *
1003 * @note This should be used in place of talloc_autofree_context (which is now deprecated)
1004 * @note Will not be thread-safe if NULL tracking is enabled.
1005 *
1006 * @return A talloc ctx which will be freed when the thread or process exits.
1007 */
1009{
1010 TALLOC_CTX *af = thread_local_ctx;
1011
1012 if (!af) {
1013 af = talloc_init_const("thread_local_autofree_context");
1014 if (unlikely(!af)) return NULL;
1015
1016 talloc_set_destructor(af, _autofree_thread_local_destructor);
1017
1019 }
1020
1021 return af;
1022}
1023
1024
1028
1030{
1031 while (list->next != NULL) {
1032 TALLOC_CHILD_CTX *entry = list->next;
1033 TALLOC_CHILD_CTX *next = entry->next;
1034
1035 if (talloc_free(entry) < 0) return -1;
1036
1037 list->next = next;
1038 }
1039
1040 return 0;
1041}
1042
1043/** Allocate and initialize a TALLOC_CHILD_CTX
1044 *
1045 * The TALLOC_CHILD_CTX ensures ordering for allocators and
1046 * destructors. When a TALLOC_CHILD_CTX is created, it is added to
1047 * parent, in LIFO order. In contrast, the basic talloc operations
1048 * do not guarantee any kind of order.
1049 *
1050 * When the TALLOC_CHILD_CTX is freed, the children are freed in FILO
1051 * order. That process ensures that the children are freed before
1052 * the parent, and that the younger siblings are freed before the
1053 * older siblings.
1054 *
1055 * The idea is that if we have an initializer for A, which in turn
1056 * initializes B and C. When the memory is freed, we should do the
1057 * operations in the reverse order.
1058 */
1060{
1061 TALLOC_CHILD_CTX *child;
1062
1063 child = talloc_zero(ctx, TALLOC_CHILD_CTX);
1064 if (!child) return NULL;
1065
1066 talloc_set_destructor(child, _child_ctx_free);
1067 return child;
1068}
1069
1070/** Allocate a TALLOC_CHILD_CTX from a parent.
1071 *
1072 */
1074{
1075 TALLOC_CHILD_CTX *child;
1076
1077 child = talloc(parent, TALLOC_CHILD_CTX);
1078 if (!child) return NULL;
1079
1080 child->next = parent->next;
1081 parent->next = child;
1082 return child;
1083}
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:228
#define fr_atexit_thread_local_disarm(...)
Definition atexit.h:230
#define fr_atexit_global(_func, _uctx)
Add a free function to the global free list.
Definition atexit.h:58
#define fr_atexit_thread_local(_name, _free, _uctx)
Definition atexit.h:220
#define RCSID(id)
Definition build.h:488
#define unlikely(_x)
Definition build.h:384
#define UNUSED
Definition build.h:318
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:141
static fr_slen_t in
Definition dict.h:882
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
unsigned long int size_t
#define fr_assert(_expr)
Definition rad_assert.h:37
static char const * name
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:906
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:589
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:1073
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:962
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:572
struct talloc_child_ctx_s * next
Definition talloc.c:1026
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:495
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:976
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:996
TALLOC_CHILD_CTX * talloc_child_ctx_init(TALLOC_CTX *ctx)
Allocate and initialize a TALLOC_CHILD_CTX.
Definition talloc.c:1059
int talloc_memcmp_array(uint8_t const *a, uint8_t const *b)
Compares two talloced uint8_t arrays with memcmp.
Definition talloc.c:826
char * talloc_buffer_append_variadic_buffer(TALLOC_CTX *ctx, char *to, int argc,...)
Concatenate to + ...
Definition talloc.c:750
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:418
char * talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
Trim a bstr (char) buffer.
Definition talloc.c:681
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition talloc.c:545
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:445
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:617
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:1029
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:470
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:874
char * talloc_typed_strndup(TALLOC_CTX *ctx, char const *p, size_t len)
Call talloc_strndup, setting the type on the new chunk correctly.
Definition talloc.c:521
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:1008
char * talloc_buffer_append_buffer(TALLOC_CTX *ctx, char *to, char const *from)
Concatenate to + from.
Definition talloc.c:714
void ** talloc_array_null_strip(void **array)
Remove a NULL termination pointer from an array of pointers.
Definition talloc.c:936
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:645
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:850
static int _autofree_global_destructor(TALLOC_CTX *af)
Ensures in the autofree ctx is manually freed, things don't explode atexit.
Definition talloc.c:971
#define talloc_strndup(_ctx, _str, _len)
Definition talloc.h:143
fr_talloc_free_func_t func
Free function.
Definition talloc.h:89
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
Definition talloc.h:120
fr_talloc_destructor_t * d
Destructor to disarm.
Definition talloc.h:99
void * uctx
uctx to pass to free function.
Definition talloc.h:90
void * fire
Parent chunk.
Definition talloc.h:87
int(* fr_talloc_free_func_t)(void *fire_ctx, void *uctx)
Definition talloc.h:77
fr_talloc_destructor_disarm_t * ds
Chunk to free.
Definition talloc.h:91
#define talloc_strdup(_ctx, _str)
Definition talloc.h:142
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Definition talloc.h:136
Structure to record a destructor to disarm if a child talloc chunk is freed.
Definition talloc.h:98
Structure to record a destructor operation on a specific talloc chunk.
Definition talloc.h:86
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:1340
static size_t char fr_sbuff_t size_t inlen
Definition value.h:1030
static size_t char ** out
Definition value.h:1030