The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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  */
24 RCSID("$Id: 9254b6d9c64568c0938e827812400cd36e3ae410 $")
25 
26 #include <freeradius-devel/util/atexit.h>
27 #include <freeradius-devel/util/debug.h>
28 #include <freeradius-devel/util/dlist.h>
29 #include <freeradius-devel/util/sbuff.h>
30 #include <freeradius-devel/util/strerror.h>
31 
32 static TALLOC_CTX *global_ctx;
33 static _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  */
49 void *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  */
96 fr_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 
149 static 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  */
167 int 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  */
196 TALLOC_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 /** Return a page aligned talloc memory pool
220  *
221  * Because we can't intercept talloc's malloc() calls, we need to do some tricks
222  * in order to get the first allocation in the pool page aligned, and to limit
223  * the size of the pool to a multiple of the page size.
224  *
225  * The reason for wanting a page aligned talloc pool, is it allows us to
226  * mprotect() the pages that belong to the pool.
227  *
228  * Talloc chunks appear to be allocated within the protected region, so this should
229  * catch frees too.
230  *
231  * @param[in] ctx to allocate pool memory in.
232  * @param[out] start A page aligned address within the pool. This can be passed
233  * to mprotect().
234  * @param[out] end of the pages that should be protected.
235  * @param[in] size How big to make the pool. Will be corrected to a multiple
236  * of the page size. The actual pool size will be size
237  * rounded to a multiple of the (page_size), + page_size
238  */
239 TALLOC_CTX *talloc_page_aligned_pool(TALLOC_CTX *ctx, void **start, void **end, size_t size)
240 {
241  size_t rounded, page_size = (size_t)getpagesize();
242  size_t hdr_size, pool_size;
243  void *next, *chunk;
244  TALLOC_CTX *pool;
245 
246  rounded = ROUND_UP(size, page_size); /* Round up to a multiple of the page size */
247  if (rounded == 0) rounded = page_size;
248 
249  pool_size = rounded + page_size;
250  pool = talloc_pool(ctx, pool_size); /* Over allocate */
251  if (!pool) {
252  fr_strerror_const("Out of memory");
253  return NULL;
254  }
255 
256  chunk = talloc_size(pool, 1); /* Get the starting address */
257  if (!fr_cond_assert((chunk > pool) && ((uintptr_t)chunk < ((uintptr_t)pool + rounded)))) {
258  fr_strerror_const("Initial allocation outside of pool memory");
259  error:
260  talloc_free(pool);
261  return NULL;
262  }
263  hdr_size = (uintptr_t)chunk - (uintptr_t)pool;
264 
265  next = (void *)ROUND_UP((uintptr_t)chunk, page_size); /* Round up address to the next page */
266 
267  /*
268  * Depending on how talloc allocates the chunk headers,
269  * the memory allocated here might not align to a page
270  * boundary, but that's ok, we just need future allocations
271  * to occur on or after 'next'.
272  */
273  if (((uintptr_t)next - (uintptr_t)chunk) > 0) {
274  size_t pad_size;
275  void *padding;
276 
277  pad_size = ((uintptr_t)next - (uintptr_t)chunk);
278  if (pad_size > hdr_size) {
279  pad_size -= hdr_size; /* Save ~111 bytes by not over-padding */
280  } else {
281  pad_size = 1;
282  }
283 
284  padding = talloc_size(pool, pad_size);
285  if (!fr_cond_assert(((uintptr_t)padding + (uintptr_t)pad_size) >= (uintptr_t)next)) {
286  fr_strerror_const("Failed padding pool memory");
287  goto error;
288  }
289  }
290 
291  *start = next; /* This is the address we feed into mprotect */
292  *end = (void *)((uintptr_t)next + (uintptr_t)rounded);
293 
294  return pool;
295 }
296 
297 /** Call talloc_memdup, setting the type on the new chunk correctly
298  *
299  * @param[in] ctx The talloc context to hang the result off.
300  * @param[in] in The data you want to duplicate.
301  * @param[in] inlen the length of the data to be duplicated.
302  * @return
303  * - Duplicated data.
304  * - NULL on error.
305  *
306  * @hidecallergraph
307  */
308 uint8_t *talloc_typed_memdup(TALLOC_CTX *ctx, uint8_t const *in, size_t inlen)
309 {
310  uint8_t *n;
311 
312  n = talloc_memdup(ctx, in, inlen);
313  if (unlikely(!n)) return NULL;
314  talloc_set_type(n, uint8_t);
315 
316  return n;
317 }
318 
319 /** Call talloc_strdup, setting the type on the new chunk correctly
320  *
321  * For some bizarre reason the talloc string functions don't set the
322  * memory chunk type to char, which causes all kinds of issues with
323  * verifying fr_pair_ts.
324  *
325  * @param[in] ctx The talloc context to hang the result off.
326  * @param[in] p The string you want to duplicate.
327  * @return
328  * - Duplicated string.
329  * - NULL on error.
330  *
331  * @hidecallergraph
332  */
333 char *talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
334 {
335  char *n;
336 
337  n = talloc_strdup(ctx, p);
338  if (unlikely(!n)) return NULL;
339  talloc_set_type(n, char);
340 
341  return n;
342 }
343 
344 /** Call talloc_strndup, setting the type on the new chunk correctly
345  *
346  * This function is similar to talloc_typed_strdup but gets the chunk
347  * length using talloc functions.
348  *
349  * @param[in] ctx The talloc context to hang the result off.
350  * @param[in] p The string you want to duplicate.
351  * @return
352  * - Duplicated string.
353  * - NULL on error.
354  *
355  * @hidecallergraph
356  */
357 char *talloc_typed_strdup_buffer(TALLOC_CTX *ctx, char const *p)
358 {
359  char *n;
360 
361  n = talloc_strndup(ctx, p, talloc_array_length(p) - 1);
362  if (unlikely(!n)) return NULL;
363  talloc_set_type(n, char);
364 
365  return n;
366 }
367 
368 /** Call talloc vasprintf, setting the type on the new chunk correctly
369  *
370  * For some bizarre reason the talloc string functions don't set the
371  * memory chunk type to char, which causes all kinds of issues with
372  * verifying fr_pair_ts.
373  *
374  * @param[in] ctx The talloc context to hang the result off.
375  * @param[in] fmt The format string.
376  * @return
377  * - Formatted string.
378  * - NULL on error.
379  */
380 char *talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt, ...)
381 {
382  char *n;
383  va_list ap;
384 
385  va_start(ap, fmt);
386  n = talloc_vasprintf(ctx, fmt, ap);
387  va_end(ap);
388  if (unlikely(!n)) return NULL;
389  talloc_set_type(n, char);
390 
391  return n;
392 }
393 
394 /** Call talloc vasprintf, setting the type on the new chunk correctly
395  *
396  * For some bizarre reason the talloc string functions don't set the
397  * memory chunk type to char, which causes all kinds of issues with
398  * verifying fr_pair_ts.
399  *
400  * @param[in] ctx The talloc context to hang the result off.
401  * @param[in] fmt The format string.
402  * @param[in] ap varadic arguments.
403  * @return
404  * - Formatted string.
405  * - NULL on error.
406  */
407 char *talloc_typed_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
408 {
409  char *n;
410 
411  n = talloc_vasprintf(ctx, fmt, ap);
412  if (unlikely(!n)) return NULL;
413  talloc_set_type(n, char);
414 
415  return n;
416 }
417 
418 /** Binary safe strdup function
419  *
420  * @param[in] ctx the talloc context to allocate new buffer in.
421  * @param[in] in String to dup, may contain embedded '\0'.
422  * @return duped string.
423  */
424 char *talloc_bstrdup(TALLOC_CTX *ctx, char const *in)
425 {
426  char *p;
427  size_t inlen = talloc_array_length(in);
428 
429  if (inlen == 0) inlen = 1;
430 
431  p = talloc_array(ctx, char, inlen);
432  if (unlikely(!p)) return NULL;
433 
434  /*
435  * C99 (7.21.1/2) - Length zero results in noop
436  *
437  * But ubsan still flags this, grrr.
438  */
439  if (inlen > 0) memcpy(p, in, inlen - 1);
440  p[inlen - 1] = '\0';
441 
442  return p;
443 }
444 
445 /** Binary safe strndup function
446  *
447  * @param[in] ctx he talloc context to allocate new buffer in.
448  * @param[in] in String to dup, may contain embedded '\0'.
449  * @param[in] inlen Number of bytes to dup.
450  * @return duped string.
451  */
452 char *talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
453 {
454  char *p;
455 
456  p = talloc_array(ctx, char, inlen + 1);
457  if (unlikely(!p)) return NULL;
458 
459  /*
460  * C99 (7.21.1/2) - Length zero results in noop
461  *
462  * But ubsan still flags this, grrr.
463  */
464  if (inlen > 0) memcpy(p, in, inlen);
465  p[inlen] = '\0';
466 
467  return p;
468 }
469 
470 /** Append a bstr to a bstr
471  *
472  * @param[in] ctx to allocated.
473  * @param[in] to string to append to.
474  * @param[in] from string to append from.
475  * @param[in] from_len Length of from.
476  * @return
477  * - Realloced buffer containing both to and from.
478  * - NULL on failure. To will still be valid.
479  */
480 char *talloc_bstr_append(TALLOC_CTX *ctx, char *to, char const *from, size_t from_len)
481 {
482  char *n;
483  size_t to_len = 0;
484 
485  if (to) {
486  to_len = talloc_array_length(to);
487  if (to[to_len - 1] == '\0') to_len--; /* Inlen should be length of input string */
488  }
489 
490  n = talloc_realloc_size(ctx, to, to_len + from_len + 1);
491  if (!n) {
492  fr_strerror_printf("Extending bstr buffer to %zu bytes failed", to_len + from_len + 1);
493  return NULL;
494  }
495 
496  memcpy(n + to_len, from, from_len);
497  n[to_len + from_len] = '\0';
498  talloc_set_type(n, char);
499 
500  return n;
501 }
502 
503 /** Trim a bstr (char) buffer
504  *
505  * Reallocs to inlen + 1 and '\0' terminates the string buffer.
506  *
507  * @param[in] ctx to realloc buffer into.
508  * @param[in] in string to trim. Will be invalid after
509  * this function returns. If NULL a new zero terminated
510  * buffer of inlen bytes will be allocated.
511  * @param[in] inlen Length to trim string to.
512  * @return
513  * - The realloced string on success. in then points to invalid memory.
514  * - NULL on failure. In will still be valid.
515  */
516 char *talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
517 {
518  char *n;
519 
520  if (!in) {
521  n = talloc_array(ctx, char, inlen);
522  n[0] = '\0';
523  return n;
524  }
525 
526  n = talloc_realloc_size(ctx, in, inlen + 1);
527  if (unlikely(!n)) return NULL;
528 
529  n[inlen] = '\0';
530  talloc_set_type(n, char);
531 
532  return n;
533 }
534 
535 /** Concatenate to + from
536  *
537  * @param[in] ctx to allocate realloced buffer in.
538  * @param[in] to talloc string buffer to append to.
539  * @param[in] from talloc string buffer to append.
540  * @return
541  * - NULL if to or from are NULL or if the realloc fails.
542  * Note: You'll still need to free to if this function
543  * returns NULL.
544  * - The concatenation of to + from. After this function
545  * returns to may point to invalid memory and should
546  * not be used.
547  */
548 char *talloc_buffer_append_buffer(TALLOC_CTX *ctx, char *to, char const *from)
549 {
550  size_t to_len, from_len, total_len;
551  char *out;
552 
553  if (!to || !from) return NULL;
554 
555  to_len = talloc_array_length(to);
556  from_len = talloc_array_length(from);
557  total_len = to_len + (from_len - 1);
558 
559  out = talloc_realloc(ctx, to, char, total_len);
560  if (!out) return NULL;
561 
562  memcpy(out + (to_len - 1), from, from_len);
563  out[total_len - 1] = '\0';
564 
565  return out;
566 }
567 
568 /** Concatenate to + ...
569  *
570  * @param[in] ctx to allocate realloced buffer in.
571  * @param[in] to talloc string buffer to append to.
572  * @param[in] argc how many variadic arguments were passed.
573  * @param[in] ... talloc string buffer(s) to append.
574  * Arguments can be NULL to simplify
575  * calling logic.
576  * @return
577  * - NULL if to or from are NULL or if the realloc fails.
578  * Note: You'll still need to free to if this function
579  * returns NULL.
580  * - The concatenation of to + from. After this function
581  * returns to may point to invalid memory and should
582  * not be used.
583  */
584 char *talloc_buffer_append_variadic_buffer(TALLOC_CTX *ctx, char *to, int argc, ...)
585 {
586  va_list ap_val, ap_len;
587  int i;
588 
589  size_t to_len, total_len = 0;
590  char *out, *p;
591 
592  if (!to) return NULL;
593 
594  va_start(ap_val, argc);
595  va_copy(ap_len, ap_val);
596 
597  total_len += to_len = talloc_array_length(to) - 1;
598 
599  /*
600  * Figure out how much we need to realloc
601  */
602  for (i = 0; i < argc; i++) {
603  char *arg;
604 
605  arg = va_arg(ap_len, char *);
606  if (!arg) continue;
607 
608  total_len += (talloc_array_length(arg) - 1);
609  }
610 
611  /*
612  * It's a noop...
613  */
614  if (total_len == to_len) {
615  va_end(ap_val);
616  va_end(ap_len);
617  return to;
618  }
619 
620  out = talloc_realloc(ctx, to, char, total_len + 1);
621  if (!out) goto finish;
622 
623  p = out + to_len;
624 
625  /*
626  * Copy the args in
627  */
628  for (i = 0; i < argc; i++) {
629  char *arg;
630  size_t len;
631 
632  arg = va_arg(ap_val, char *);
633  if (!arg) continue;
634 
635  len = talloc_array_length(arg) - 1;
636 
637  memcpy(p, arg, len);
638  p += len;
639  }
640  *p = '\0';
641 
642 finish:
643  va_end(ap_val);
644  va_end(ap_len);
645 
646  return out;
647 }
648 
649 /** Compares two talloced uint8_t arrays with memcmp
650  *
651  * Talloc arrays carry their length as part of the structure, so can be passed to a generic
652  * comparison function.
653  *
654  * @param a Pointer to first array.
655  * @param b Pointer to second array.
656  * @return
657  * - 0 if the arrays match.
658  * - a positive or negative integer otherwise.
659  */
660 int talloc_memcmp_array(uint8_t const *a, uint8_t const *b)
661 {
662  size_t a_len, b_len;
663 
664  a_len = talloc_array_length(a);
665  b_len = talloc_array_length(b);
666 
667  if (a_len > b_len) return +1;
668  if (a_len < b_len) return -1;
669 
670  return memcmp(a, b, a_len);
671 }
672 
673 /** Compares two talloced char arrays with memcmp
674  *
675  * Talloc arrays carry their length as part of the structure, so can be passed to a generic
676  * comparison function.
677  *
678  * @param a Pointer to first array.
679  * @param b Pointer to second array.
680  * @return
681  * - 0 if the arrays match.
682  * - a positive or negative integer otherwise.
683  */
684 int talloc_memcmp_bstr(char const *a, char const *b)
685 {
686  size_t a_len, b_len;
687 
688  a_len = talloc_array_length(a);
689  b_len = talloc_array_length(b);
690 
691  if (a_len > b_len) return +1;
692  if (a_len < b_len) return -1;
693 
694  return memcmp(a, b, a_len);
695 }
696 
697 /** Decrease the reference count on a ptr
698  *
699  * Ptr will be freed if count reaches zero.
700  *
701  * This is equivalent to talloc 1.0 behaviour of talloc_free.
702  *
703  * @param ptr to decrement ref count for.
704  * @return
705  * - 0 The memory was freed.
706  * - >0 How many references remain.
707  */
708 int talloc_decrease_ref_count(void const *ptr)
709 {
710  size_t ref_count;
711  void *to_free;
712 
713  if (!ptr) return 0;
714 
715  memcpy(&to_free, &ptr, sizeof(to_free));
716 
717  ref_count = talloc_reference_count(to_free);
718  if (ref_count == 0) {
719  talloc_free(to_free);
720  } else {
721  talloc_unlink(talloc_parent(ptr), to_free);
722  }
723 
724  return ref_count;
725 }
726 
727 /** Add a NULL pointer to an array of pointers
728  *
729  * This is needed by some 3rd party libraries which take NULL terminated
730  * arrays for arguments.
731  *
732  * If allocation fails, NULL will be returned and the original array
733  * will not be touched.
734  *
735  * @param[in] array to null terminate. Will be invalidated (realloced).
736  * @return
737  * - NULL if array is NULL, or if reallocation fails.
738  * - A realloced version of array with an additional NULL element.
739  */
741 {
742  size_t len;
743  TALLOC_CTX *ctx;
744  void **new;
745  size_t size;
746 
747  if (!array) return NULL;
748 
749  len = talloc_array_length(array);
750  ctx = talloc_parent(array);
751  size = talloc_get_size(array) / talloc_array_length(array);
752 
753  new = _talloc_realloc_array(ctx, array, size, len + 1, talloc_get_name(array));
754  if (!new) return NULL;
755 
756  new[len] = NULL;
757 
758  return new;
759 }
760 
761 /** Remove a NULL termination pointer from an array of pointers
762  *
763  * If the end of the array is not NULL, NULL will be returned (error).
764  *
765  * @param[in] array to null strip. Will be invalidated (realloced).
766  * @return
767  * - NULL if array is NULL, if terminating element is not NULL, or reallocation fails.
768  * - A realloced version of array without the terminating NULL element.
769  */
771 {
772  size_t len;
773  TALLOC_CTX *ctx;
774  void **new;
775  size_t size;
776 
777  if (!array) return NULL;
778 
779  len = talloc_array_length(array);
780  ctx = talloc_parent(array);
781  size = talloc_get_size(array) / talloc_array_length(array);
782 
783  if ((len - 1) == 0) return NULL;
784 
785  if (array[len - 1] != NULL) return NULL;
786 
787  new = _talloc_realloc_array(ctx, array, size, len - 1, talloc_get_name(array));
788  if (!new) return NULL;
789 
790  return new;
791 }
792 
793 /** Concat an array of strings (not NULL terminated), with a string separator
794  *
795  * @param[out] out Where to write the resulting string.
796  * @param[in] array of strings to concat.
797  * @param[in] sep to insert between elements. May be NULL.
798  * @return
799  * - >= 0 on success - length of the string created.
800  * - <0 on failure. How many bytes we would need.
801  */
802 fr_slen_t talloc_array_concat(fr_sbuff_t *out, char const * const *array, char const *sep)
803 {
804  fr_sbuff_t our_out = FR_SBUFF(out);
805  size_t len = talloc_array_length(array);
806  char const * const * p;
807  char const * const * end;
808  fr_sbuff_escape_rules_t e_rules = {
809  .name = __FUNCTION__,
810  .chr = '\\'
811  };
812 
813  if (sep) e_rules.subs[(uint8_t)*sep] = *sep;
814 
815  for (p = array, end = array + len;
816  (p < end);
817  p++) {
818  if (*p) FR_SBUFF_RETURN(fr_sbuff_in_escape, &our_out, *p, strlen(*p), &e_rules);
819 
820  if (sep && ((p + 1) < end)) {
821  FR_SBUFF_RETURN(fr_sbuff_in_strcpy, &our_out, sep);
822  }
823  }
824 
825  FR_SBUFF_SET_RETURN(out, &our_out);
826 }
827 
828 /** Callback to free the autofree ctx on global exit
829  *
830  */
831 static int _autofree_on_exit(void *af)
832 {
833  talloc_set_destructor(af, NULL);
834  return talloc_free(af);
835 }
836 
837 /** Ensures in the autofree ctx is manually freed, things don't explode atexit
838  *
839  */
840 static int _autofree_global_destructor(TALLOC_CTX *af)
841 {
842  return fr_atexit_global_disarm(true, _autofree_on_exit, af);
843 }
844 
846 {
847  TALLOC_CTX *af = global_ctx;
848 
849  if (!af) {
850  af = talloc_init_const("global_autofree_context");
851  talloc_set_destructor(af, _autofree_global_destructor);
852  if (unlikely(!af)) return NULL;
853 
855  global_ctx = af;
856  }
857 
858  return af;
859 }
860 
861 /** Ensures in the autofree ctx is manually freed, things don't explode atexit
862  *
863  */
864 static int _autofree_thread_local_destructor(TALLOC_CTX *af)
865 {
867 }
868 
869 /** Get a thread-safe autofreed ctx that will be freed when the thread or process exits
870  *
871  * @note This should be used in place of talloc_autofree_context (which is now deprecated)
872  * @note Will not be thread-safe if NULL tracking is enabled.
873  *
874  * @return A talloc ctx which will be freed when the thread or process exits.
875  */
877 {
878  TALLOC_CTX *af = thread_local_ctx;
879 
880  if (!af) {
881  af = talloc_init_const("thread_local_autofree_context");
882  talloc_set_destructor(af, _autofree_thread_local_destructor);
883  if (unlikely(!af)) return NULL;
884 
886  }
887 
888  return af;
889 }
890 
891 
894 };
895 
897 {
898  while (list->next != NULL) {
899  TALLOC_CHILD_CTX *entry = list->next;
900  TALLOC_CHILD_CTX *next = entry->next;
901 
902  if (talloc_free(entry) < 0) return -1;
903 
904  list->next = next;
905  }
906 
907  return 0;
908 }
909 
910 /** Allocate and initialize a TALLOC_CHILD_CTX
911  *
912  * The TALLOC_CHILD_CTX ensures ordering for allocators and
913  * destructors. When a TALLOC_CHILD_CTX is created, it is added to
914  * parent, in LIFO order. In contrast, the basic talloc operations
915  * do not guarantee any kind of order.
916  *
917  * When the TALLOC_CHILD_CTX is freed, the children are freed in FILO
918  * order. That process ensures that the children are freed before
919  * the parent, and that the younger siblings are freed before the
920  * older siblings.
921  *
922  * The idea is that if we have an initializer for A, which in turn
923  * initializes B and C. When the memory is freed, we should do the
924  * operations in the reverse order.
925  */
927 {
928  TALLOC_CHILD_CTX *child;
929 
930  child = talloc_zero(ctx, TALLOC_CHILD_CTX);
931  if (!child) return NULL;
932 
933  talloc_set_destructor(child, _child_ctx_free);
934  return child;
935 }
936 
937 /** Allocate a TALLOC_CHILD_CTX from a parent.
938  *
939  */
941 {
942  TALLOC_CHILD_CTX *child;
943 
944  child = talloc(parent, TALLOC_CHILD_CTX);
945  if (!child) return NULL;
946 
947  child->next = parent->next;
948  parent->next = child;
949  return child;
950 }
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:444
#define unlikely(_x)
Definition: build.h:378
#define UNUSED
Definition: build.h:313
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:137
static fr_slen_t in
Definition: dict.h:645
talloc_free(reap)
#define ROUND_UP(_num, _mul)
Round up - Works in all cases, but is slower.
Definition: math.h:148
unsigned char uint8_t
Definition: merged_model.c:30
ssize_t fr_slen_t
Definition: merged_model.c:35
unsigned long int size_t
Definition: merged_model.c:25
static size_t array[MY_ARRAY_SIZE]
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:1419
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:1579
#define FR_SBUFF_RETURN(_func, _sbuff,...)
#define FR_SBUFF(_sbuff_or_marker)
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: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:424
TALLOC_CHILD_CTX * talloc_child_ctx_init(TALLOC_CTX *ctx)
Allocate and initialize a TALLOC_CHILD_CTX.
Definition: talloc.c:926
static int _talloc_link_ctx_free(UNUSED void *parent, void *child)
Definition: talloc.c:149
TALLOC_CTX * talloc_page_aligned_pool(TALLOC_CTX *ctx, void **start, void **end, size_t size)
Return a page aligned talloc memory pool.
Definition: talloc.c:239
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:407
static TALLOC_CTX * global_ctx
Definition: talloc.c:32
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:308
static int _autofree_on_exit(void *af)
Callback to free the autofree ctx on global exit.
Definition: talloc.c:831
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition: talloc.c:333
char * talloc_buffer_append_variadic_buffer(TALLOC_CTX *ctx, char *to, int argc,...)
Concatenate to + ...
Definition: talloc.c:584
void * talloc_null_ctx(void)
Retrieve the current talloc NULL ctx.
Definition: talloc.c:49
struct talloc_child_ctx_s * next
Definition: talloc.c:893
char * talloc_buffer_append_buffer(TALLOC_CTX *ctx, char *to, char const *from)
Concatenate to + from.
Definition: talloc.c:548
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:802
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:864
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
Definition: talloc.c:452
int talloc_memcmp_array(uint8_t const *a, uint8_t const *b)
Compares two talloced uint8_t arrays with memcmp.
Definition: talloc.c:660
TALLOC_CHILD_CTX * talloc_child_ctx_alloc(TALLOC_CHILD_CTX *parent)
Allocate a TALLOC_CHILD_CTX from a parent.
Definition: talloc.c:940
TALLOC_CTX * talloc_autofree_context_global(void)
Definition: talloc.c:845
char * talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
Trim a bstr (char) buffer.
Definition: talloc.c:516
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
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:480
static _Thread_local TALLOC_CTX * thread_local_ctx
Definition: talloc.c:33
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:357
void ** talloc_array_null_strip(void **array)
Remove a NULL termination pointer from an array of pointers.
Definition: talloc.c:770
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 _child_ctx_free(TALLOC_CHILD_CTX *list)
Definition: talloc.c:896
void ** talloc_array_null_terminate(void **array)
Add a NULL pointer to an array of pointers.
Definition: talloc.c:740
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition: talloc.c:380
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:708
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
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
int talloc_memcmp_bstr(char const *a, char const *b)
Compares two talloced char arrays with memcmp.
Definition: talloc.c:684
static int _autofree_global_destructor(TALLOC_CTX *af)
Ensures in the autofree ctx is manually freed, things don't explode atexit.
Definition: talloc.c:840
fr_talloc_free_func_t func
Free function.
Definition: talloc.h:92
fr_talloc_destructor_t * d
Destructor to disarm.
Definition: talloc.h:102
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
Definition: talloc.h:112
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:844
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_const(_msg)
Definition: strerror.h:223
FR_SBUFF_SET_RETURN(sbuff, &our_sbuff)
static fr_slen_t data
Definition: value.h:1259
static size_t char fr_sbuff_t size_t inlen
Definition: value.h:984
static size_t char ** out
Definition: value.h:984