1 /*
2 Samba Unix SMB/CIFS implementation.
3
4 Samba trivial allocation library - new interface
5
6 NOTE: Please read talloc_guide.txt for full documentation
7
8 Copyright (C) Andrew Tridgell 2004
9 Copyright (C) Stefan Metzmacher 2006
10
11 ** NOTE! The following LGPL license applies to the talloc
12 ** library. This does NOT imply that all of Samba is released
13 ** under the LGPL
14
15 This library is free software; you can redistribute it and/or
16 modify it under the terms of the GNU Lesser General Public
17 License as published by the Free Software Foundation; either
18 version 3 of the License, or (at your option) any later version.
19
20 This library is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 Lesser General Public License for more details.
24
25 You should have received a copy of the GNU Lesser General Public
26 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 */
28
29 /*
30 inspired by http://swapped.cc/halloc/
31 */
32
33 #include "config.h"
34
35 #include <stdbool.h>
36 #include <stdint.h>
37 #include <stddef.h>
38 #include <string.h>
39
40 #include <atalk/compat.h>
41 #include <atalk/util.h>
42 #include <atalk/talloc.h>
43
44 #define _PUBLIC_ extern
45
46 /**
47 * pointer difference macro
48 */
49 #define PTR_DIFF(p1,p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
50
51
52 #ifdef TALLOC_BUILD_VERSION_MAJOR
53 #if (TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR)
54 #error "TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR"
55 #endif
56 #endif
57
58 #ifdef TALLOC_BUILD_VERSION_MINOR
59 #if (TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR)
60 #error "TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR"
61 #endif
62 #endif
63
64 /* Special macros that are no-ops except when run under Valgrind on
65 * x86. They've moved a little bit from valgrind 1.0.4 to 1.9.4 */
66 #ifdef HAVE_VALGRIND_MEMCHECK_H
67 /* memcheck.h includes valgrind.h */
68 #include <valgrind/memcheck.h>
69 #elif defined(HAVE_VALGRIND_H)
70 #include <valgrind.h>
71 #endif
72
73 /* use this to force every realloc to change the pointer, to stress test
74 code that might not cope */
75 #define ALWAYS_REALLOC 0
76
77
78 #define MAX_TALLOC_SIZE 0x10000000
79 #define TALLOC_MAGIC_BASE 0xe814ec70
80 #define TALLOC_MAGIC ( \
81 TALLOC_MAGIC_BASE + \
82 (TALLOC_VERSION_MAJOR << 12) + \
83 (TALLOC_VERSION_MINOR << 4) \
84 )
85
86 #define TALLOC_FLAG_FREE 0x01
87 #define TALLOC_FLAG_LOOP 0x02
88 #define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */
89 #define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */
90 #define TALLOC_MAGIC_REFERENCE ((const char *)1)
91
92 /* by default we abort when given a bad pointer (such as when talloc_free() is called
93 on a pointer that came from malloc() */
94 #ifndef TALLOC_ABORT
95 #define TALLOC_ABORT(reason) abort()
96 #endif
97
98 #ifndef discard_const_p
99 #if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
100 # define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
101 #else
102 # define discard_const_p(type, ptr) ((type *)(ptr))
103 #endif
104 #endif
105
106 /* these macros gain us a few percent of speed on gcc */
107 #if (__GNUC__ >= 3)
108 /* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
109 as its first argument */
110 #ifndef likely
111 #define likely(x) __builtin_expect(!!(x), 1)
112 #endif
113 #ifndef unlikely
114 #define unlikely(x) __builtin_expect(!!(x), 0)
115 #endif
116 #else
117 #ifndef likely
118 #define likely(x) (x)
119 #endif
120 #ifndef unlikely
121 #define unlikely(x) (x)
122 #endif
123 #endif
124
125 /* this null_context is only used if talloc_enable_leak_report() or
126 talloc_enable_leak_report_full() is called, otherwise it remains
127 NULL
128 */
129 static void *null_context;
130 static void *autofree_context;
131
132 /* used to enable fill of memory on free, which can be useful for
133 * catching use after free errors when valgrind is too slow
134 */
135 static struct {
136 bool initialised;
137 bool enabled;
138 uint8_t fill_value;
139 } talloc_fill;
140
141 #define TALLOC_FILL_ENV "TALLOC_FREE_FILL"
142
143 /*
144 * do not wipe the header, to allow the
145 * double-free logic to still work
146 */
147 #define TC_INVALIDATE_FULL_FILL_CHUNK(_tc) do { \
148 if (unlikely(talloc_fill.enabled)) { \
149 size_t _flen = (_tc)->size; \
150 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
151 memset(_fptr, talloc_fill.fill_value, _flen); \
152 } \
153 } while (0)
154
155 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
156 /* Mark the whole chunk as not accessable */
157 #define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { \
158 size_t _flen = TC_HDR_SIZE + (_tc)->size; \
159 char *_fptr = (char *)(_tc); \
160 VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
161 } while(0)
162 #else
163 #define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { } while (0)
164 #endif
165
166 #define TC_INVALIDATE_FULL_CHUNK(_tc) do { \
167 TC_INVALIDATE_FULL_FILL_CHUNK(_tc); \
168 TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc); \
169 } while (0)
170
171 #define TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
172 if (unlikely(talloc_fill.enabled)) { \
173 size_t _flen = (_tc)->size - (_new_size); \
174 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
175 _fptr += (_new_size); \
176 memset(_fptr, talloc_fill.fill_value, _flen); \
177 } \
178 } while (0)
179
180 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
181 /* Mark the unused bytes not accessable */
182 #define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
183 size_t _flen = (_tc)->size - (_new_size); \
184 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
185 _fptr += (_new_size); \
186 VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
187 } while (0)
188 #else
189 #define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
190 #endif
191
192 #define TC_INVALIDATE_SHRINK_CHUNK(_tc, _new_size) do { \
193 TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size); \
194 TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
195 } while (0)
196
197 #define TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \
198 if (unlikely(talloc_fill.enabled)) { \
199 size_t _flen = (_tc)->size - (_new_size); \
200 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
201 _fptr += (_new_size); \
202 memset(_fptr, talloc_fill.fill_value, _flen); \
203 } \
204 } while (0)
205
206 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
207 /* Mark the unused bytes as undefined */
208 #define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \
209 size_t _flen = (_tc)->size - (_new_size); \
210 char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \
211 _fptr += (_new_size); \
212 VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
213 } while (0)
214 #else
215 #define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
216 #endif
217
218 #define TC_UNDEFINE_SHRINK_CHUNK(_tc, _new_size) do { \
219 TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size); \
220 TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \
221 } while (0)
222
223 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
224 /* Mark the new bytes as undefined */
225 #define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { \
226 size_t _old_used = TC_HDR_SIZE + (_tc)->size; \
227 size_t _new_used = TC_HDR_SIZE + (_new_size); \
228 size_t _flen = _new_used - _old_used; \
229 char *_fptr = _old_used + (char *)(_tc); \
230 VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \
231 } while (0)
232 #else
233 #define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { } while (0)
234 #endif
235
236 #define TC_UNDEFINE_GROW_CHUNK(_tc, _new_size) do { \
237 TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size); \
238 } while (0)
239
240 struct talloc_reference_handle {
241 struct talloc_reference_handle *next, *prev;
242 void *ptr;
243 const char *location;
244 };
245
246 typedef int (*talloc_destructor_t)(void *);
247
248 struct talloc_chunk {
249 struct talloc_chunk *next, *prev;
250 struct talloc_chunk *parent, *child;
251 struct talloc_reference_handle *refs;
252 talloc_destructor_t destructor;
253 const char *name;
254 size_t size;
255 unsigned flags;
256
257 /*
258 * "pool" has dual use:
259 *
260 * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
261 * marks the end of the currently allocated area.
262 *
263 * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
264 * is a pointer to the struct talloc_chunk of the pool that it was
265 * allocated from. This way children can quickly find the pool to chew
266 * from.
267 */
268 void *pool;
269 };
270
271 /* 16 byte alignment seems to keep everyone happy */
272 #define TC_ALIGN16(s) (((s)+15)&~15)
273 #define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk))
274 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
275
talloc_version_major(void)276 _PUBLIC_ int talloc_version_major(void)
277 {
278 return TALLOC_VERSION_MAJOR;
279 }
280
talloc_version_minor(void)281 _PUBLIC_ int talloc_version_minor(void)
282 {
283 return TALLOC_VERSION_MINOR;
284 }
285
286 static void (*talloc_log_fn)(const char *message);
287
talloc_set_log_fn(void (* log_fn)(const char * message))288 _PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message))
289 {
290 talloc_log_fn = log_fn;
291 }
292
293 static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
talloc_log(const char * fmt,...)294 static void talloc_log(const char *fmt, ...)
295 {
296 va_list ap;
297 char *message;
298
299 if (!talloc_log_fn) {
300 return;
301 }
302
303 va_start(ap, fmt);
304 message = talloc_vasprintf(NULL, fmt, ap);
305 va_end(ap);
306
307 talloc_log_fn(message);
308 talloc_free(message);
309 }
310
talloc_log_stderr(const char * message)311 static void talloc_log_stderr(const char *message)
312 {
313 fprintf(stderr, "%s", message);
314 }
315
talloc_set_log_stderr(void)316 _PUBLIC_ void talloc_set_log_stderr(void)
317 {
318 talloc_set_log_fn(talloc_log_stderr);
319 }
320
321 static void (*talloc_abort_fn)(const char *reason);
322
talloc_set_abort_fn(void (* abort_fn)(const char * reason))323 _PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
324 {
325 talloc_abort_fn = abort_fn;
326 }
327
talloc_abort(const char * reason)328 static void talloc_abort(const char *reason)
329 {
330 talloc_log("%s\n", reason);
331
332 if (!talloc_abort_fn) {
333 TALLOC_ABORT(reason);
334 }
335
336 talloc_abort_fn(reason);
337 }
338
talloc_abort_magic(unsigned magic)339 static void talloc_abort_magic(unsigned magic)
340 {
341 unsigned striped = magic - TALLOC_MAGIC_BASE;
342 unsigned major = (striped & 0xFFFFF000) >> 12;
343 unsigned minor = (striped & 0x00000FF0) >> 4;
344 talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n",
345 magic, major, minor,
346 TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR);
347 talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
348 }
349
talloc_abort_access_after_free(void)350 static void talloc_abort_access_after_free(void)
351 {
352 talloc_abort("Bad talloc magic value - access after free");
353 }
354
talloc_abort_unknown_value(void)355 static void talloc_abort_unknown_value(void)
356 {
357 talloc_abort("Bad talloc magic value - unknown value");
358 }
359
360 /* panic if we get a bad magic value */
talloc_chunk_from_ptr(const void * ptr)361 static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
362 {
363 const char *pp = (const char *)ptr;
364 struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
365 if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) {
366 if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) {
367 talloc_abort_magic(tc->flags & (~0xF));
368 return NULL;
369 }
370
371 if (tc->flags & TALLOC_FLAG_FREE) {
372 talloc_log("talloc: access after free error - first free may be at %s\n", tc->name);
373 talloc_abort_access_after_free();
374 return NULL;
375 } else {
376 talloc_abort_unknown_value();
377 return NULL;
378 }
379 }
380 return tc;
381 }
382
383 /* hook into the front of the list */
384 #define _TLIST_ADD(list, p) \
385 do { \
386 if (!(list)) { \
387 (list) = (p); \
388 (p)->next = (p)->prev = NULL; \
389 } else { \
390 (list)->prev = (p); \
391 (p)->next = (list); \
392 (p)->prev = NULL; \
393 (list) = (p); \
394 }\
395 } while (0)
396
397 /* remove an element from a list - element doesn't have to be in list. */
398 #define _TLIST_REMOVE(list, p) \
399 do { \
400 if ((p) == (list)) { \
401 (list) = (p)->next; \
402 if (list) (list)->prev = NULL; \
403 } else { \
404 if ((p)->prev) (p)->prev->next = (p)->next; \
405 if ((p)->next) (p)->next->prev = (p)->prev; \
406 } \
407 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
408 } while (0)
409
410
411 /*
412 return the parent chunk of a pointer
413 */
talloc_parent_chunk(const void * ptr)414 static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
415 {
416 struct talloc_chunk *tc;
417
418 if (unlikely(ptr == NULL)) {
419 return NULL;
420 }
421
422 tc = talloc_chunk_from_ptr(ptr);
423 while (tc->prev) tc=tc->prev;
424
425 return tc->parent;
426 }
427
talloc_parent(const void * ptr)428 _PUBLIC_ void *talloc_parent(const void *ptr)
429 {
430 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
431 return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
432 }
433
434 /*
435 find parents name
436 */
talloc_parent_name(const void * ptr)437 _PUBLIC_ const char *talloc_parent_name(const void *ptr)
438 {
439 struct talloc_chunk *tc = talloc_parent_chunk(ptr);
440 return tc? tc->name : NULL;
441 }
442
443 /*
444 A pool carries an in-pool object count count in the first 16 bytes.
445 bytes. This is done to support talloc_steal() to a parent outside of the
446 pool. The count includes the pool itself, so a talloc_free() on a pool will
447 only destroy the pool if the count has dropped to zero. A talloc_free() of a
448 pool member will reduce the count, and eventually also call free(3) on the
449 pool memory.
450
451 The object count is not put into "struct talloc_chunk" because it is only
452 relevant for talloc pools and the alignment to 16 bytes would increase the
453 memory footprint of each talloc chunk by those 16 bytes.
454 */
455
456 #define TALLOC_POOL_HDR_SIZE 16
457
458 #define TC_POOL_SPACE_LEFT(_pool_tc) \
459 PTR_DIFF(TC_HDR_SIZE + (_pool_tc)->size + (char *)(_pool_tc), \
460 (_pool_tc)->pool)
461
462 #define TC_POOL_FIRST_CHUNK(_pool_tc) \
463 ((void *)(TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE + (char *)(_pool_tc)))
464
465 #define TC_POOLMEM_CHUNK_SIZE(_tc) \
466 TC_ALIGN16(TC_HDR_SIZE + (_tc)->size)
467
468 #define TC_POOLMEM_NEXT_CHUNK(_tc) \
469 ((void *)(TC_POOLMEM_CHUNK_SIZE(tc) + (char*)(_tc)))
470
471 /* Mark the whole remaining pool as not accessable */
472 #define TC_INVALIDATE_FILL_POOL(_pool_tc) do { \
473 if (unlikely(talloc_fill.enabled)) { \
474 size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \
475 char *_fptr = (char *)(_pool_tc)->pool; \
476 memset(_fptr, talloc_fill.fill_value, _flen); \
477 } \
478 } while(0)
479
480 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
481 /* Mark the whole remaining pool as not accessable */
482 #define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { \
483 size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \
484 char *_fptr = (char *)(_pool_tc)->pool; \
485 VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \
486 } while(0)
487 #else
488 #define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { } while (0)
489 #endif
490
491 #define TC_INVALIDATE_POOL(_pool_tc) do { \
492 TC_INVALIDATE_FILL_POOL(_pool_tc); \
493 TC_INVALIDATE_VALGRIND_POOL(_pool_tc); \
494 } while (0)
495
talloc_pool_objectcount(struct talloc_chunk * tc)496 static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc)
497 {
498 return (unsigned int *)((char *)tc + TC_HDR_SIZE);
499 }
500
501 /*
502 Allocate from a pool
503 */
504
talloc_alloc_pool(struct talloc_chunk * parent,size_t size)505 static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
506 size_t size)
507 {
508 struct talloc_chunk *pool_ctx = NULL;
509 size_t space_left;
510 struct talloc_chunk *result;
511 size_t chunk_size;
512
513 if (parent == NULL) {
514 return NULL;
515 }
516
517 if (parent->flags & TALLOC_FLAG_POOL) {
518 pool_ctx = parent;
519 }
520 else if (parent->flags & TALLOC_FLAG_POOLMEM) {
521 pool_ctx = (struct talloc_chunk *)parent->pool;
522 }
523
524 if (pool_ctx == NULL) {
525 return NULL;
526 }
527
528 space_left = TC_POOL_SPACE_LEFT(pool_ctx);
529
530 /*
531 * Align size to 16 bytes
532 */
533 chunk_size = TC_ALIGN16(size);
534
535 if (space_left < chunk_size) {
536 return NULL;
537 }
538
539 result = (struct talloc_chunk *)pool_ctx->pool;
540
541 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
542 VALGRIND_MAKE_MEM_UNDEFINED(result, size);
543 #endif
544
545 pool_ctx->pool = (void *)((char *)result + chunk_size);
546
547 result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
548 result->pool = pool_ctx;
549
550 *talloc_pool_objectcount(pool_ctx) += 1;
551
552 return result;
553 }
554
555 /*
556 Allocate a bit of memory as a child of an existing pointer
557 */
__talloc(const void * context,size_t size)558 static inline void *__talloc(const void *context, size_t size)
559 {
560 struct talloc_chunk *tc = NULL;
561
562 if (unlikely(context == NULL)) {
563 context = null_context;
564 }
565
566 if (unlikely(size >= MAX_TALLOC_SIZE)) {
567 return NULL;
568 }
569
570 if (context != NULL) {
571 tc = talloc_alloc_pool(talloc_chunk_from_ptr(context),
572 TC_HDR_SIZE+size);
573 }
574
575 if (tc == NULL) {
576 tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
577 if (unlikely(tc == NULL)) return NULL;
578 tc->flags = TALLOC_MAGIC;
579 tc->pool = NULL;
580 }
581
582 tc->size = size;
583 tc->destructor = NULL;
584 tc->child = NULL;
585 tc->name = NULL;
586 tc->refs = NULL;
587
588 if (likely(context)) {
589 struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
590
591 if (parent->child) {
592 parent->child->parent = NULL;
593 tc->next = parent->child;
594 tc->next->prev = tc;
595 } else {
596 tc->next = NULL;
597 }
598 tc->parent = parent;
599 tc->prev = NULL;
600 parent->child = tc;
601 } else {
602 tc->next = tc->prev = tc->parent = NULL;
603 }
604
605 return TC_PTR_FROM_CHUNK(tc);
606 }
607
608 /*
609 * Create a talloc pool
610 */
611
talloc_pool(const void * context,size_t size)612 _PUBLIC_ void *talloc_pool(const void *context, size_t size)
613 {
614 void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE);
615 struct talloc_chunk *tc;
616
617 if (unlikely(result == NULL)) {
618 return NULL;
619 }
620
621 tc = talloc_chunk_from_ptr(result);
622
623 tc->flags |= TALLOC_FLAG_POOL;
624 tc->pool = TC_POOL_FIRST_CHUNK(tc);
625
626 *talloc_pool_objectcount(tc) = 1;
627
628 TC_INVALIDATE_POOL(tc);
629
630 return result;
631 }
632
633 /*
634 setup a destructor to be called on free of a pointer
635 the destructor should return 0 on success, or -1 on failure.
636 if the destructor fails then the free is failed, and the memory can
637 be continued to be used
638 */
_talloc_set_destructor(const void * ptr,int (* destructor)(void *))639 _PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
640 {
641 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
642 tc->destructor = destructor;
643 }
644
645 /*
646 increase the reference count on a piece of memory.
647 */
talloc_increase_ref_count(const void * ptr)648 _PUBLIC_ int talloc_increase_ref_count(const void *ptr)
649 {
650 if (unlikely(!talloc_reference(null_context, ptr))) {
651 return -1;
652 }
653 return 0;
654 }
655
656 /*
657 helper for talloc_reference()
658
659 this is referenced by a function pointer and should not be inline
660 */
talloc_reference_destructor(struct talloc_reference_handle * handle)661 static int talloc_reference_destructor(struct talloc_reference_handle *handle)
662 {
663 struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
664 _TLIST_REMOVE(ptr_tc->refs, handle);
665 return 0;
666 }
667
668 /*
669 more efficient way to add a name to a pointer - the name must point to a
670 true string constant
671 */
_talloc_set_name_const(const void * ptr,const char * name)672 static inline void _talloc_set_name_const(const void *ptr, const char *name)
673 {
674 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
675 tc->name = name;
676 }
677
678 /*
679 internal talloc_named_const()
680 */
_talloc_named_const(const void * context,size_t size,const char * name)681 static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
682 {
683 void *ptr;
684
685 ptr = __talloc(context, size);
686 if (unlikely(ptr == NULL)) {
687 return NULL;
688 }
689
690 _talloc_set_name_const(ptr, name);
691
692 return ptr;
693 }
694
695 /*
696 make a secondary reference to a pointer, hanging off the given context.
697 the pointer remains valid until both the original caller and this given
698 context are freed.
699
700 the major use for this is when two different structures need to reference the
701 same underlying data, and you want to be able to free the two instances separately,
702 and in either order
703 */
_talloc_reference_loc(const void * context,const void * ptr,const char * location)704 _PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)
705 {
706 struct talloc_chunk *tc;
707 struct talloc_reference_handle *handle;
708 if (unlikely(ptr == NULL)) return NULL;
709
710 tc = talloc_chunk_from_ptr(ptr);
711 handle = (struct talloc_reference_handle *)_talloc_named_const(context,
712 sizeof(struct talloc_reference_handle),
713 TALLOC_MAGIC_REFERENCE);
714 if (unlikely(handle == NULL)) return NULL;
715
716 /* note that we hang the destructor off the handle, not the
717 main context as that allows the caller to still setup their
718 own destructor on the context if they want to */
719 talloc_set_destructor(handle, talloc_reference_destructor);
720 handle->ptr = discard_const_p(void, ptr);
721 handle->location = location;
722 _TLIST_ADD(tc->refs, handle);
723 return handle->ptr;
724 }
725
726 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
727
_talloc_free_poolmem(struct talloc_chunk * tc,const char * location)728 static inline void _talloc_free_poolmem(struct talloc_chunk *tc,
729 const char *location)
730 {
731 struct talloc_chunk *pool;
732 void *next_tc;
733 unsigned int *pool_object_count;
734
735 pool = (struct talloc_chunk *)tc->pool;
736 next_tc = TC_POOLMEM_NEXT_CHUNK(tc);
737
738 tc->flags |= TALLOC_FLAG_FREE;
739
740 /* we mark the freed memory with where we called the free
741 * from. This means on a double free error we can report where
742 * the first free came from
743 */
744 tc->name = location;
745
746 TC_INVALIDATE_FULL_CHUNK(tc);
747
748 pool_object_count = talloc_pool_objectcount(pool);
749
750 if (unlikely(*pool_object_count == 0)) {
751 talloc_abort("Pool object count zero!");
752 return;
753 }
754
755 *pool_object_count -= 1;
756
757 if (unlikely(*pool_object_count == 1 && !(pool->flags & TALLOC_FLAG_FREE))) {
758 /*
759 * if there is just one object left in the pool
760 * and pool->flags does not have TALLOC_FLAG_FREE,
761 * it means this is the pool itself and
762 * the rest is available for new objects
763 * again.
764 */
765 pool->pool = TC_POOL_FIRST_CHUNK(pool);
766 TC_INVALIDATE_POOL(pool);
767 } else if (unlikely(*pool_object_count == 0)) {
768 /*
769 * we mark the freed memory with where we called the free
770 * from. This means on a double free error we can report where
771 * the first free came from
772 */
773 pool->name = location;
774
775 TC_INVALIDATE_FULL_CHUNK(pool);
776 free(pool);
777 } else if (pool->pool == next_tc) {
778 /*
779 * if pool->pool still points to end of
780 * 'tc' (which is stored in the 'next_tc' variable),
781 * we can reclaim the memory of 'tc'.
782 */
783 pool->pool = tc;
784 }
785 }
786
787 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
788 void *ptr,
789 const char *location);
790
791 /*
792 internal talloc_free call
793 */
_talloc_free_internal(void * ptr,const char * location)794 static inline int _talloc_free_internal(void *ptr, const char *location)
795 {
796 struct talloc_chunk *tc;
797
798 if (unlikely(ptr == NULL)) {
799 return -1;
800 }
801
802 /* possibly initialised the talloc fill value */
803 if (unlikely(!talloc_fill.initialised)) {
804 const char *fill = getenv(TALLOC_FILL_ENV);
805 if (fill != NULL) {
806 talloc_fill.enabled = true;
807 talloc_fill.fill_value = strtoul(fill, NULL, 0);
808 }
809 talloc_fill.initialised = true;
810 }
811
812 tc = talloc_chunk_from_ptr(ptr);
813
814 if (unlikely(tc->refs)) {
815 int is_child;
816 /* check if this is a reference from a child or
817 * grandchild back to it's parent or grandparent
818 *
819 * in that case we need to remove the reference and
820 * call another instance of talloc_free() on the current
821 * pointer.
822 */
823 is_child = talloc_is_parent(tc->refs, ptr);
824 _talloc_free_internal(tc->refs, location);
825 if (is_child) {
826 return _talloc_free_internal(ptr, location);
827 }
828 return -1;
829 }
830
831 if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
832 /* we have a free loop - stop looping */
833 return 0;
834 }
835
836 if (unlikely(tc->destructor)) {
837 talloc_destructor_t d = tc->destructor;
838 if (d == (talloc_destructor_t)-1) {
839 return -1;
840 }
841 tc->destructor = (talloc_destructor_t)-1;
842 if (d(ptr) == -1) {
843 tc->destructor = d;
844 return -1;
845 }
846 tc->destructor = NULL;
847 }
848
849 if (tc->parent) {
850 _TLIST_REMOVE(tc->parent->child, tc);
851 if (tc->parent->child) {
852 tc->parent->child->parent = tc->parent;
853 }
854 } else {
855 if (tc->prev) tc->prev->next = tc->next;
856 if (tc->next) tc->next->prev = tc->prev;
857 tc->prev = tc->next = NULL;
858 }
859
860 tc->flags |= TALLOC_FLAG_LOOP;
861
862 _talloc_free_children_internal(tc, ptr, location);
863
864 tc->flags |= TALLOC_FLAG_FREE;
865
866 /* we mark the freed memory with where we called the free
867 * from. This means on a double free error we can report where
868 * the first free came from
869 */
870 tc->name = location;
871
872 if (tc->flags & TALLOC_FLAG_POOL) {
873 unsigned int *pool_object_count;
874
875 pool_object_count = talloc_pool_objectcount(tc);
876
877 if (unlikely(*pool_object_count == 0)) {
878 talloc_abort("Pool object count zero!");
879 return 0;
880 }
881
882 *pool_object_count -= 1;
883
884 if (unlikely(*pool_object_count == 0)) {
885 TC_INVALIDATE_FULL_CHUNK(tc);
886 free(tc);
887 }
888 } else if (tc->flags & TALLOC_FLAG_POOLMEM) {
889 _talloc_free_poolmem(tc, location);
890 } else {
891 TC_INVALIDATE_FULL_CHUNK(tc);
892 free(tc);
893 }
894 return 0;
895 }
896
897 /*
898 move a lump of memory from one talloc context to another return the
899 ptr on success, or NULL if it could not be transferred.
900 passing NULL as ptr will always return NULL with no side effects.
901 */
_talloc_steal_internal(const void * new_ctx,const void * ptr)902 static void *_talloc_steal_internal(const void *new_ctx, const void *ptr)
903 {
904 struct talloc_chunk *tc, *new_tc;
905
906 if (unlikely(!ptr)) {
907 return NULL;
908 }
909
910 if (unlikely(new_ctx == NULL)) {
911 new_ctx = null_context;
912 }
913
914 tc = talloc_chunk_from_ptr(ptr);
915
916 if (unlikely(new_ctx == NULL)) {
917 if (tc->parent) {
918 _TLIST_REMOVE(tc->parent->child, tc);
919 if (tc->parent->child) {
920 tc->parent->child->parent = tc->parent;
921 }
922 } else {
923 if (tc->prev) tc->prev->next = tc->next;
924 if (tc->next) tc->next->prev = tc->prev;
925 }
926
927 tc->parent = tc->next = tc->prev = NULL;
928 return discard_const_p(void, ptr);
929 }
930
931 new_tc = talloc_chunk_from_ptr(new_ctx);
932
933 if (unlikely(tc == new_tc || tc->parent == new_tc)) {
934 return discard_const_p(void, ptr);
935 }
936
937 if (tc->parent) {
938 _TLIST_REMOVE(tc->parent->child, tc);
939 if (tc->parent->child) {
940 tc->parent->child->parent = tc->parent;
941 }
942 } else {
943 if (tc->prev) tc->prev->next = tc->next;
944 if (tc->next) tc->next->prev = tc->prev;
945 tc->prev = tc->next = NULL;
946 }
947
948 tc->parent = new_tc;
949 if (new_tc->child) new_tc->child->parent = NULL;
950 _TLIST_ADD(new_tc->child, tc);
951
952 return discard_const_p(void, ptr);
953 }
954
955 /*
956 move a lump of memory from one talloc context to another return the
957 ptr on success, or NULL if it could not be transferred.
958 passing NULL as ptr will always return NULL with no side effects.
959 */
_talloc_steal_loc(const void * new_ctx,const void * ptr,const char * location)960 _PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
961 {
962 struct talloc_chunk *tc;
963
964 if (unlikely(ptr == NULL)) {
965 return NULL;
966 }
967
968 tc = talloc_chunk_from_ptr(ptr);
969
970 if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) {
971 struct talloc_reference_handle *h;
972
973 talloc_log("WARNING: talloc_steal with references at %s\n",
974 location);
975
976 for (h=tc->refs; h; h=h->next) {
977 talloc_log("\treference at %s\n",
978 h->location);
979 }
980 }
981
982 #if 0
983 /* this test is probably too expensive to have on in the
984 normal build, but it useful for debugging */
985 if (talloc_is_parent(new_ctx, ptr)) {
986 talloc_log("WARNING: stealing into talloc child at %s\n", location);
987 }
988 #endif
989
990 return _talloc_steal_internal(new_ctx, ptr);
991 }
992
993 /*
994 this is like a talloc_steal(), but you must supply the old
995 parent. This resolves the ambiguity in a talloc_steal() which is
996 called on a context that has more than one parent (via references)
997
998 The old parent can be either a reference or a parent
999 */
talloc_reparent(const void * old_parent,const void * new_parent,const void * ptr)1000 _PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
1001 {
1002 struct talloc_chunk *tc;
1003 struct talloc_reference_handle *h;
1004
1005 if (unlikely(ptr == NULL)) {
1006 return NULL;
1007 }
1008
1009 if (old_parent == talloc_parent(ptr)) {
1010 return _talloc_steal_internal(new_parent, ptr);
1011 }
1012
1013 tc = talloc_chunk_from_ptr(ptr);
1014 for (h=tc->refs;h;h=h->next) {
1015 if (talloc_parent(h) == old_parent) {
1016 if (_talloc_steal_internal(new_parent, h) != h) {
1017 return NULL;
1018 }
1019 return discard_const_p(void, ptr);
1020 }
1021 }
1022
1023 /* it wasn't a parent */
1024 return NULL;
1025 }
1026
1027 /*
1028 remove a secondary reference to a pointer. This undo's what
1029 talloc_reference() has done. The context and pointer arguments
1030 must match those given to a talloc_reference()
1031 */
talloc_unreference(const void * context,const void * ptr)1032 static inline int talloc_unreference(const void *context, const void *ptr)
1033 {
1034 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1035 struct talloc_reference_handle *h;
1036
1037 if (unlikely(context == NULL)) {
1038 context = null_context;
1039 }
1040
1041 for (h=tc->refs;h;h=h->next) {
1042 struct talloc_chunk *p = talloc_parent_chunk(h);
1043 if (p == NULL) {
1044 if (context == NULL) break;
1045 } else if (TC_PTR_FROM_CHUNK(p) == context) {
1046 break;
1047 }
1048 }
1049 if (h == NULL) {
1050 return -1;
1051 }
1052
1053 return _talloc_free_internal(h, __location__);
1054 }
1055
1056 /*
1057 remove a specific parent context from a pointer. This is a more
1058 controlled varient of talloc_free()
1059 */
talloc_unlink(const void * context,void * ptr)1060 _PUBLIC_ int talloc_unlink(const void *context, void *ptr)
1061 {
1062 struct talloc_chunk *tc_p, *new_p;
1063 void *new_parent;
1064
1065 if (ptr == NULL) {
1066 return -1;
1067 }
1068
1069 if (context == NULL) {
1070 context = null_context;
1071 }
1072
1073 if (talloc_unreference(context, ptr) == 0) {
1074 return 0;
1075 }
1076
1077 if (context == NULL) {
1078 if (talloc_parent_chunk(ptr) != NULL) {
1079 return -1;
1080 }
1081 } else {
1082 if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
1083 return -1;
1084 }
1085 }
1086
1087 tc_p = talloc_chunk_from_ptr(ptr);
1088
1089 if (tc_p->refs == NULL) {
1090 return _talloc_free_internal(ptr, __location__);
1091 }
1092
1093 new_p = talloc_parent_chunk(tc_p->refs);
1094 if (new_p) {
1095 new_parent = TC_PTR_FROM_CHUNK(new_p);
1096 } else {
1097 new_parent = NULL;
1098 }
1099
1100 if (talloc_unreference(new_parent, ptr) != 0) {
1101 return -1;
1102 }
1103
1104 _talloc_steal_internal(new_parent, ptr);
1105
1106 return 0;
1107 }
1108
1109 /*
1110 add a name to an existing pointer - va_list version
1111 */
1112 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
1113
talloc_set_name_v(const void * ptr,const char * fmt,va_list ap)1114 static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
1115 {
1116 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1117 tc->name = talloc_vasprintf(ptr, fmt, ap);
1118 if (likely(tc->name)) {
1119 _talloc_set_name_const(tc->name, ".name");
1120 }
1121 return tc->name;
1122 }
1123
1124 /*
1125 add a name to an existing pointer
1126 */
talloc_set_name(const void * ptr,const char * fmt,...)1127 _PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...)
1128 {
1129 const char *name;
1130 va_list ap;
1131 va_start(ap, fmt);
1132 name = talloc_set_name_v(ptr, fmt, ap);
1133 va_end(ap);
1134 return name;
1135 }
1136
1137
1138 /*
1139 create a named talloc pointer. Any talloc pointer can be named, and
1140 talloc_named() operates just like talloc() except that it allows you
1141 to name the pointer.
1142 */
talloc_named(const void * context,size_t size,const char * fmt,...)1143 _PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...)
1144 {
1145 va_list ap;
1146 void *ptr;
1147 const char *name;
1148
1149 ptr = __talloc(context, size);
1150 if (unlikely(ptr == NULL)) return NULL;
1151
1152 va_start(ap, fmt);
1153 name = talloc_set_name_v(ptr, fmt, ap);
1154 va_end(ap);
1155
1156 if (unlikely(name == NULL)) {
1157 _talloc_free_internal(ptr, __location__);
1158 return NULL;
1159 }
1160
1161 return ptr;
1162 }
1163
1164 /*
1165 return the name of a talloc ptr, or "UNNAMED"
1166 */
talloc_get_name(const void * ptr)1167 _PUBLIC_ const char *talloc_get_name(const void *ptr)
1168 {
1169 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1170 if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
1171 return ".reference";
1172 }
1173 if (likely(tc->name)) {
1174 return tc->name;
1175 }
1176 return "UNNAMED";
1177 }
1178
1179
1180 /*
1181 check if a pointer has the given name. If it does, return the pointer,
1182 otherwise return NULL
1183 */
talloc_check_name(const void * ptr,const char * name)1184 _PUBLIC_ void *talloc_check_name(const void *ptr, const char *name)
1185 {
1186 const char *pname;
1187 if (unlikely(ptr == NULL)) return NULL;
1188 pname = talloc_get_name(ptr);
1189 if (likely(pname == name || strcmp(pname, name) == 0)) {
1190 return discard_const_p(void, ptr);
1191 }
1192 return NULL;
1193 }
1194
talloc_abort_type_missmatch(const char * location,const char * name,const char * expected)1195 static void talloc_abort_type_missmatch(const char *location,
1196 const char *name,
1197 const char *expected)
1198 {
1199 const char *reason;
1200
1201 reason = talloc_asprintf(NULL,
1202 "%s: Type mismatch: name[%s] expected[%s]",
1203 location,
1204 name?name:"NULL",
1205 expected);
1206 if (!reason) {
1207 reason = "Type mismatch";
1208 }
1209
1210 talloc_abort(reason);
1211 }
1212
_talloc_get_type_abort(const void * ptr,const char * name,const char * location)1213 _PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
1214 {
1215 const char *pname;
1216
1217 if (unlikely(ptr == NULL)) {
1218 talloc_abort_type_missmatch(location, NULL, name);
1219 return NULL;
1220 }
1221
1222 pname = talloc_get_name(ptr);
1223 if (likely(pname == name || strcmp(pname, name) == 0)) {
1224 return discard_const_p(void, ptr);
1225 }
1226
1227 talloc_abort_type_missmatch(location, pname, name);
1228 return NULL;
1229 }
1230
1231 /*
1232 this is for compatibility with older versions of talloc
1233 */
talloc_init(const char * fmt,...)1234 _PUBLIC_ void *talloc_init(const char *fmt, ...)
1235 {
1236 va_list ap;
1237 void *ptr;
1238 const char *name;
1239
1240 ptr = __talloc(NULL, 0);
1241 if (unlikely(ptr == NULL)) return NULL;
1242
1243 va_start(ap, fmt);
1244 name = talloc_set_name_v(ptr, fmt, ap);
1245 va_end(ap);
1246
1247 if (unlikely(name == NULL)) {
1248 _talloc_free_internal(ptr, __location__);
1249 return NULL;
1250 }
1251
1252 return ptr;
1253 }
1254
_talloc_free_children_internal(struct talloc_chunk * tc,void * ptr,const char * location)1255 static inline void _talloc_free_children_internal(struct talloc_chunk *tc,
1256 void *ptr,
1257 const char *location)
1258 {
1259 while (tc->child) {
1260 /* we need to work out who will own an abandoned child
1261 if it cannot be freed. In priority order, the first
1262 choice is owner of any remaining reference to this
1263 pointer, the second choice is our parent, and the
1264 final choice is the null context. */
1265 void *child = TC_PTR_FROM_CHUNK(tc->child);
1266 const void *new_parent = null_context;
1267 if (unlikely(tc->child->refs)) {
1268 struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
1269 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1270 }
1271 if (unlikely(_talloc_free_internal(child, location) == -1)) {
1272 if (new_parent == null_context) {
1273 struct talloc_chunk *p = talloc_parent_chunk(ptr);
1274 if (p) new_parent = TC_PTR_FROM_CHUNK(p);
1275 }
1276 _talloc_steal_internal(new_parent, child);
1277 }
1278 }
1279 }
1280
1281 /*
1282 this is a replacement for the Samba3 talloc_destroy_pool functionality. It
1283 should probably not be used in new code. It's in here to keep the talloc
1284 code consistent across Samba 3 and 4.
1285 */
talloc_free_children(void * ptr)1286 _PUBLIC_ void talloc_free_children(void *ptr)
1287 {
1288 struct talloc_chunk *tc_name = NULL;
1289 struct talloc_chunk *tc;
1290
1291 if (unlikely(ptr == NULL)) {
1292 return;
1293 }
1294
1295 tc = talloc_chunk_from_ptr(ptr);
1296
1297 /* we do not want to free the context name if it is a child .. */
1298 if (likely(tc->child)) {
1299 for (tc_name = tc->child; tc_name; tc_name = tc_name->next) {
1300 if (tc->name == TC_PTR_FROM_CHUNK(tc_name)) break;
1301 }
1302 if (tc_name) {
1303 _TLIST_REMOVE(tc->child, tc_name);
1304 if (tc->child) {
1305 tc->child->parent = tc;
1306 }
1307 }
1308 }
1309
1310 _talloc_free_children_internal(tc, ptr, __location__);
1311
1312 /* .. so we put it back after all other children have been freed */
1313 if (tc_name) {
1314 if (tc->child) {
1315 tc->child->parent = NULL;
1316 }
1317 tc_name->parent = tc;
1318 _TLIST_ADD(tc->child, tc_name);
1319 }
1320 }
1321
1322 /*
1323 Allocate a bit of memory as a child of an existing pointer
1324 */
_talloc(const void * context,size_t size)1325 _PUBLIC_ void *_talloc(const void *context, size_t size)
1326 {
1327 return __talloc(context, size);
1328 }
1329
1330 /*
1331 externally callable talloc_set_name_const()
1332 */
talloc_set_name_const(const void * ptr,const char * name)1333 _PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name)
1334 {
1335 _talloc_set_name_const(ptr, name);
1336 }
1337
1338 /*
1339 create a named talloc pointer. Any talloc pointer can be named, and
1340 talloc_named() operates just like talloc() except that it allows you
1341 to name the pointer.
1342 */
talloc_named_const(const void * context,size_t size,const char * name)1343 _PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name)
1344 {
1345 return _talloc_named_const(context, size, name);
1346 }
1347
1348 /*
1349 free a talloc pointer. This also frees all child pointers of this
1350 pointer recursively
1351
1352 return 0 if the memory is actually freed, otherwise -1. The memory
1353 will not be freed if the ref_count is > 1 or the destructor (if
1354 any) returns non-zero
1355 */
_talloc_free(void * ptr,const char * location)1356 _PUBLIC_ int _talloc_free(void *ptr, const char *location)
1357 {
1358 struct talloc_chunk *tc;
1359
1360 if (unlikely(ptr == NULL)) {
1361 return -1;
1362 }
1363
1364 tc = talloc_chunk_from_ptr(ptr);
1365
1366 if (unlikely(tc->refs != NULL)) {
1367 struct talloc_reference_handle *h;
1368
1369 if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) {
1370 /* in this case we do know which parent should
1371 get this pointer, as there is really only
1372 one parent */
1373 return talloc_unlink(null_context, ptr);
1374 }
1375
1376 talloc_log("ERROR: talloc_free with references at %s\n",
1377 location);
1378
1379 for (h=tc->refs; h; h=h->next) {
1380 talloc_log("\treference at %s\n",
1381 h->location);
1382 }
1383 return -1;
1384 }
1385
1386 return _talloc_free_internal(ptr, location);
1387 }
1388
1389
1390
1391 /*
1392 A talloc version of realloc. The context argument is only used if
1393 ptr is NULL
1394 */
_talloc_realloc(const void * context,void * ptr,size_t size,const char * name)1395 _PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
1396 {
1397 struct talloc_chunk *tc;
1398 void *new_ptr;
1399 bool malloced = false;
1400 struct talloc_chunk *pool_tc = NULL;
1401
1402 /* size zero is equivalent to free() */
1403 if (unlikely(size == 0)) {
1404 talloc_unlink(context, ptr);
1405 return NULL;
1406 }
1407
1408 if (unlikely(size >= MAX_TALLOC_SIZE)) {
1409 return NULL;
1410 }
1411
1412 /* realloc(NULL) is equivalent to malloc() */
1413 if (ptr == NULL) {
1414 return _talloc_named_const(context, size, name);
1415 }
1416
1417 tc = talloc_chunk_from_ptr(ptr);
1418
1419 /* don't allow realloc on referenced pointers */
1420 if (unlikely(tc->refs)) {
1421 return NULL;
1422 }
1423
1424 /* don't let anybody try to realloc a talloc_pool */
1425 if (unlikely(tc->flags & TALLOC_FLAG_POOL)) {
1426 return NULL;
1427 }
1428
1429 /* don't let anybody try to realloc a talloc_pool */
1430 if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) {
1431 pool_tc = (struct talloc_chunk *)tc->pool;
1432 }
1433
1434 #if (ALWAYS_REALLOC == 0)
1435 /* don't shrink if we have less than 1k to gain */
1436 if (size < tc->size) {
1437 if (pool_tc) {
1438 void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc);
1439 TC_INVALIDATE_SHRINK_CHUNK(tc, size);
1440 tc->size = size;
1441 if (next_tc == pool_tc->pool) {
1442 pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc);
1443 }
1444 return ptr;
1445 } else if ((tc->size - size) < 1024) {
1446 /*
1447 * if we call TC_INVALIDATE_SHRINK_CHUNK() here
1448 * we would need to call TC_UNDEFINE_GROW_CHUNK()
1449 * after each realloc call, which slows down
1450 * testing a lot :-(.
1451 *
1452 * That is why we only mark memory as undefined here.
1453 */
1454 TC_UNDEFINE_SHRINK_CHUNK(tc, size);
1455
1456 /* do not shrink if we have less than 1k to gain */
1457 tc->size = size;
1458 return ptr;
1459 }
1460 } else if (tc->size == size) {
1461 /*
1462 * do not change the pointer if it is exactly
1463 * the same size.
1464 */
1465 return ptr;
1466 }
1467 #endif
1468
1469 /* by resetting magic we catch users of the old memory */
1470 tc->flags |= TALLOC_FLAG_FREE;
1471
1472 #if ALWAYS_REALLOC
1473 if (pool_tc) {
1474 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1475 *talloc_pool_objectcount(pool_tc) -= 1;
1476
1477 if (new_ptr == NULL) {
1478 new_ptr = malloc(TC_HDR_SIZE+size);
1479 malloced = true;
1480 }
1481
1482 if (new_ptr) {
1483 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1484 TC_INVALIDATE_FULL_CHUNK(tc);
1485 }
1486 } else {
1487 new_ptr = malloc(size + TC_HDR_SIZE);
1488 if (new_ptr) {
1489 memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE);
1490 free(tc);
1491 }
1492 }
1493 #else
1494 if (pool_tc) {
1495 void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc);
1496 size_t old_chunk_size = TC_POOLMEM_CHUNK_SIZE(tc);
1497 size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size);
1498 size_t space_needed;
1499 size_t space_left;
1500 unsigned int chunk_count = *talloc_pool_objectcount(pool_tc);
1501
1502 if (!(pool_tc->flags & TALLOC_FLAG_FREE)) {
1503 chunk_count -= 1;
1504 }
1505
1506 if (chunk_count == 1) {
1507 /*
1508 * optimize for the case where 'tc' is the only
1509 * chunk in the pool.
1510 */
1511 space_needed = new_chunk_size;
1512 space_left = pool_tc->size - TALLOC_POOL_HDR_SIZE;
1513
1514 if (space_left >= space_needed) {
1515 size_t old_used = TC_HDR_SIZE + tc->size;
1516 size_t new_used = TC_HDR_SIZE + size;
1517 pool_tc->pool = TC_POOL_FIRST_CHUNK(pool_tc);
1518 #if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
1519 /*
1520 * we need to prepare the memmove into
1521 * the unaccessable area.
1522 */
1523 {
1524 size_t diff = PTR_DIFF(tc, pool_tc->pool);
1525 size_t flen = MIN(diff, old_used);
1526 char *fptr = (char *)pool_tc->pool;
1527 VALGRIND_MAKE_MEM_UNDEFINED(fptr, flen);
1528 }
1529 #endif
1530 memmove(pool_tc->pool, tc, old_used);
1531 new_ptr = pool_tc->pool;
1532
1533 tc = (struct talloc_chunk *)new_ptr;
1534 TC_UNDEFINE_GROW_CHUNK(tc, size);
1535
1536 /*
1537 * first we do not align the pool pointer
1538 * because we want to invalidate the padding
1539 * too.
1540 */
1541 pool_tc->pool = new_used + (char *)new_ptr;
1542 TC_INVALIDATE_POOL(pool_tc);
1543
1544 /* now the aligned pointer */
1545 pool_tc->pool = new_chunk_size + (char *)new_ptr;
1546 goto got_new_ptr;
1547 }
1548
1549 next_tc = NULL;
1550 }
1551
1552 if (new_chunk_size == old_chunk_size) {
1553 TC_UNDEFINE_GROW_CHUNK(tc, size);
1554 tc->flags &= ~TALLOC_FLAG_FREE;
1555 tc->size = size;
1556 return ptr;
1557 }
1558
1559 if (next_tc == pool_tc->pool) {
1560 /*
1561 * optimize for the case where 'tc' is the last
1562 * chunk in the pool.
1563 */
1564 space_needed = new_chunk_size - old_chunk_size;
1565 space_left = TC_POOL_SPACE_LEFT(pool_tc);
1566
1567 if (space_left >= space_needed) {
1568 TC_UNDEFINE_GROW_CHUNK(tc, size);
1569 tc->flags &= ~TALLOC_FLAG_FREE;
1570 tc->size = size;
1571 pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc);
1572 return ptr;
1573 }
1574 }
1575
1576 new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
1577
1578 if (new_ptr == NULL) {
1579 new_ptr = malloc(TC_HDR_SIZE+size);
1580 malloced = true;
1581 }
1582
1583 if (new_ptr) {
1584 memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
1585
1586 _talloc_free_poolmem(tc, __location__ "_talloc_realloc");
1587 }
1588 }
1589 else {
1590 new_ptr = realloc(tc, size + TC_HDR_SIZE);
1591 }
1592 got_new_ptr:
1593 #endif
1594 if (unlikely(!new_ptr)) {
1595 tc->flags &= ~TALLOC_FLAG_FREE;
1596 return NULL;
1597 }
1598
1599 tc = (struct talloc_chunk *)new_ptr;
1600 tc->flags &= ~TALLOC_FLAG_FREE;
1601 if (malloced) {
1602 tc->flags &= ~TALLOC_FLAG_POOLMEM;
1603 }
1604 if (tc->parent) {
1605 tc->parent->child = tc;
1606 }
1607 if (tc->child) {
1608 tc->child->parent = tc;
1609 }
1610
1611 if (tc->prev) {
1612 tc->prev->next = tc;
1613 }
1614 if (tc->next) {
1615 tc->next->prev = tc;
1616 }
1617
1618 tc->size = size;
1619 _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
1620
1621 return TC_PTR_FROM_CHUNK(tc);
1622 }
1623
1624 /*
1625 a wrapper around talloc_steal() for situations where you are moving a pointer
1626 between two structures, and want the old pointer to be set to NULL
1627 */
_talloc_move(const void * new_ctx,const void * _pptr)1628 _PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr)
1629 {
1630 const void **pptr = discard_const_p(const void *,_pptr);
1631 void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr));
1632 (*pptr) = NULL;
1633 return ret;
1634 }
1635
1636 /*
1637 return the total size of a talloc pool (subtree)
1638 */
talloc_total_size(const void * ptr)1639 _PUBLIC_ size_t talloc_total_size(const void *ptr)
1640 {
1641 size_t total = 0;
1642 struct talloc_chunk *c, *tc;
1643
1644 if (ptr == NULL) {
1645 ptr = null_context;
1646 }
1647 if (ptr == NULL) {
1648 return 0;
1649 }
1650
1651 tc = talloc_chunk_from_ptr(ptr);
1652
1653 if (tc->flags & TALLOC_FLAG_LOOP) {
1654 return 0;
1655 }
1656
1657 tc->flags |= TALLOC_FLAG_LOOP;
1658
1659 if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
1660 total = tc->size;
1661 }
1662 for (c=tc->child;c;c=c->next) {
1663 total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
1664 }
1665
1666 tc->flags &= ~TALLOC_FLAG_LOOP;
1667
1668 return total;
1669 }
1670
1671 /*
1672 return the total number of blocks in a talloc pool (subtree)
1673 */
talloc_total_blocks(const void * ptr)1674 _PUBLIC_ size_t talloc_total_blocks(const void *ptr)
1675 {
1676 size_t total = 0;
1677 struct talloc_chunk *c, *tc;
1678
1679 if (ptr == NULL) {
1680 ptr = null_context;
1681 }
1682 if (ptr == NULL) {
1683 return 0;
1684 }
1685
1686 tc = talloc_chunk_from_ptr(ptr);
1687
1688 if (tc->flags & TALLOC_FLAG_LOOP) {
1689 return 0;
1690 }
1691
1692 tc->flags |= TALLOC_FLAG_LOOP;
1693
1694 total++;
1695 for (c=tc->child;c;c=c->next) {
1696 total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
1697 }
1698
1699 tc->flags &= ~TALLOC_FLAG_LOOP;
1700
1701 return total;
1702 }
1703
1704 /*
1705 return the number of external references to a pointer
1706 */
talloc_reference_count(const void * ptr)1707 _PUBLIC_ size_t talloc_reference_count(const void *ptr)
1708 {
1709 struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
1710 struct talloc_reference_handle *h;
1711 size_t ret = 0;
1712
1713 for (h=tc->refs;h;h=h->next) {
1714 ret++;
1715 }
1716 return ret;
1717 }
1718
1719 /*
1720 report on memory usage by all children of a pointer, giving a full tree view
1721 */
talloc_report_depth_cb(const void * ptr,int depth,int max_depth,void (* callback)(const void * ptr,int depth,int max_depth,int is_ref,void * private_data),void * private_data)1722 _PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
1723 void (*callback)(const void *ptr,
1724 int depth, int max_depth,
1725 int is_ref,
1726 void *private_data),
1727 void *private_data)
1728 {
1729 struct talloc_chunk *c, *tc;
1730
1731 if (ptr == NULL) {
1732 ptr = null_context;
1733 }
1734 if (ptr == NULL) return;
1735
1736 tc = talloc_chunk_from_ptr(ptr);
1737
1738 if (tc->flags & TALLOC_FLAG_LOOP) {
1739 return;
1740 }
1741
1742 callback(ptr, depth, max_depth, 0, private_data);
1743
1744 if (max_depth >= 0 && depth >= max_depth) {
1745 return;
1746 }
1747
1748 tc->flags |= TALLOC_FLAG_LOOP;
1749 for (c=tc->child;c;c=c->next) {
1750 if (c->name == TALLOC_MAGIC_REFERENCE) {
1751 struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
1752 callback(h->ptr, depth + 1, max_depth, 1, private_data);
1753 } else {
1754 talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
1755 }
1756 }
1757 tc->flags &= ~TALLOC_FLAG_LOOP;
1758 }
1759
talloc_report_depth_FILE_helper(const void * ptr,int depth,int max_depth,int is_ref,void * _f)1760 static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
1761 {
1762 const char *name = talloc_get_name(ptr);
1763 FILE *f = (FILE *)_f;
1764
1765 if (is_ref) {
1766 fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
1767 return;
1768 }
1769
1770 if (depth == 0) {
1771 fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
1772 (max_depth < 0 ? "full " :""), name,
1773 (unsigned long)talloc_total_size(ptr),
1774 (unsigned long)talloc_total_blocks(ptr));
1775 return;
1776 }
1777
1778 fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
1779 depth*4, "",
1780 name,
1781 (unsigned long)talloc_total_size(ptr),
1782 (unsigned long)talloc_total_blocks(ptr),
1783 (int)talloc_reference_count(ptr), ptr);
1784
1785 #if 0
1786 fprintf(f, "content: ");
1787 if (talloc_total_size(ptr)) {
1788 int tot = talloc_total_size(ptr);
1789 int i;
1790
1791 for (i = 0; i < tot; i++) {
1792 if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
1793 fprintf(f, "%c", ((char *)ptr)[i]);
1794 } else {
1795 fprintf(f, "~%02x", ((char *)ptr)[i]);
1796 }
1797 }
1798 }
1799 fprintf(f, "\n");
1800 #endif
1801 }
1802
1803 /*
1804 report on memory usage by all children of a pointer, giving a full tree view
1805 */
talloc_report_depth_file(const void * ptr,int depth,int max_depth,FILE * f)1806 _PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
1807 {
1808 if (f) {
1809 talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
1810 fflush(f);
1811 }
1812 }
1813
1814 /*
1815 report on memory usage by all children of a pointer, giving a full tree view
1816 */
talloc_report_full(const void * ptr,FILE * f)1817 _PUBLIC_ void talloc_report_full(const void *ptr, FILE *f)
1818 {
1819 talloc_report_depth_file(ptr, 0, -1, f);
1820 }
1821
1822 /*
1823 report on memory usage by all children of a pointer
1824 */
talloc_report(const void * ptr,FILE * f)1825 _PUBLIC_ void talloc_report(const void *ptr, FILE *f)
1826 {
1827 talloc_report_depth_file(ptr, 0, 1, f);
1828 }
1829
1830 /*
1831 report on any memory hanging off the null context
1832 */
talloc_report_null(void)1833 static void talloc_report_null(void)
1834 {
1835 if (talloc_total_size(null_context) != 0) {
1836 talloc_report(null_context, stderr);
1837 }
1838 }
1839
1840 /*
1841 report on any memory hanging off the null context
1842 */
talloc_report_null_full(void)1843 static void talloc_report_null_full(void)
1844 {
1845 if (talloc_total_size(null_context) != 0) {
1846 talloc_report_full(null_context, stderr);
1847 }
1848 }
1849
1850 /*
1851 enable tracking of the NULL context
1852 */
talloc_enable_null_tracking(void)1853 _PUBLIC_ void talloc_enable_null_tracking(void)
1854 {
1855 if (null_context == NULL) {
1856 null_context = _talloc_named_const(NULL, 0, "null_context");
1857 if (autofree_context != NULL) {
1858 talloc_reparent(NULL, null_context, autofree_context);
1859 }
1860 }
1861 }
1862
1863 /*
1864 enable tracking of the NULL context, not moving the autofree context
1865 into the NULL context. This is needed for the talloc testsuite
1866 */
talloc_enable_null_tracking_no_autofree(void)1867 _PUBLIC_ void talloc_enable_null_tracking_no_autofree(void)
1868 {
1869 if (null_context == NULL) {
1870 null_context = _talloc_named_const(NULL, 0, "null_context");
1871 }
1872 }
1873
1874 /*
1875 disable tracking of the NULL context
1876 */
talloc_disable_null_tracking(void)1877 _PUBLIC_ void talloc_disable_null_tracking(void)
1878 {
1879 if (null_context != NULL) {
1880 /* we have to move any children onto the real NULL
1881 context */
1882 struct talloc_chunk *tc, *tc2;
1883 tc = talloc_chunk_from_ptr(null_context);
1884 for (tc2 = tc->child; tc2; tc2=tc2->next) {
1885 if (tc2->parent == tc) tc2->parent = NULL;
1886 if (tc2->prev == tc) tc2->prev = NULL;
1887 }
1888 for (tc2 = tc->next; tc2; tc2=tc2->next) {
1889 if (tc2->parent == tc) tc2->parent = NULL;
1890 if (tc2->prev == tc) tc2->prev = NULL;
1891 }
1892 tc->child = NULL;
1893 tc->next = NULL;
1894 }
1895 talloc_free(null_context);
1896 null_context = NULL;
1897 }
1898
1899 /*
1900 enable leak reporting on exit
1901 */
talloc_enable_leak_report(void)1902 _PUBLIC_ void talloc_enable_leak_report(void)
1903 {
1904 talloc_enable_null_tracking();
1905 atexit(talloc_report_null);
1906 }
1907
1908 /*
1909 enable full leak reporting on exit
1910 */
talloc_enable_leak_report_full(void)1911 _PUBLIC_ void talloc_enable_leak_report_full(void)
1912 {
1913 talloc_enable_null_tracking();
1914 atexit(talloc_report_null_full);
1915 }
1916
1917 /*
1918 talloc and zero memory.
1919 */
_talloc_zero(const void * ctx,size_t size,const char * name)1920 _PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name)
1921 {
1922 void *p = _talloc_named_const(ctx, size, name);
1923
1924 if (p) {
1925 memset(p, '\0', size);
1926 }
1927
1928 return p;
1929 }
1930
1931 /*
1932 memdup with a talloc.
1933 */
_talloc_memdup(const void * t,const void * p,size_t size,const char * name)1934 _PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
1935 {
1936 void *newp = _talloc_named_const(t, size, name);
1937
1938 if (likely(newp)) {
1939 memcpy(newp, p, size);
1940 }
1941
1942 return newp;
1943 }
1944
__talloc_strlendup(const void * t,const char * p,size_t len)1945 static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
1946 {
1947 char *ret;
1948
1949 ret = (char *)__talloc(t, len + 1);
1950 if (unlikely(!ret)) return NULL;
1951
1952 memcpy(ret, p, len);
1953 ret[len] = 0;
1954
1955 _talloc_set_name_const(ret, ret);
1956 return ret;
1957 }
1958
1959 /*
1960 strdup with a talloc
1961 */
talloc_strdup(const void * t,const char * p)1962 _PUBLIC_ char *talloc_strdup(const void *t, const char *p)
1963 {
1964 if (unlikely(!p)) return NULL;
1965 return __talloc_strlendup(t, p, strlen(p));
1966 }
1967
1968 /*
1969 strndup with a talloc
1970 */
talloc_strndup(const void * t,const char * p,size_t n)1971 _PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n)
1972 {
1973 if (unlikely(!p)) return NULL;
1974 return __talloc_strlendup(t, p, strnlen(p, n));
1975 }
1976
__talloc_strlendup_append(char * s,size_t slen,const char * a,size_t alen)1977 static inline char *__talloc_strlendup_append(char *s, size_t slen,
1978 const char *a, size_t alen)
1979 {
1980 char *ret;
1981
1982 ret = talloc_realloc(NULL, s, char, slen + alen + 1);
1983 if (unlikely(!ret)) return NULL;
1984
1985 /* append the string and the trailing \0 */
1986 memcpy(&ret[slen], a, alen);
1987 ret[slen+alen] = 0;
1988
1989 _talloc_set_name_const(ret, ret);
1990 return ret;
1991 }
1992
1993 /*
1994 * Appends at the end of the string.
1995 */
talloc_strdup_append(char * s,const char * a)1996 _PUBLIC_ char *talloc_strdup_append(char *s, const char *a)
1997 {
1998 if (unlikely(!s)) {
1999 return talloc_strdup(NULL, a);
2000 }
2001
2002 if (unlikely(!a)) {
2003 return s;
2004 }
2005
2006 return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
2007 }
2008
2009 /*
2010 * Appends at the end of the talloc'ed buffer,
2011 * not the end of the string.
2012 */
talloc_strdup_append_buffer(char * s,const char * a)2013 _PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a)
2014 {
2015 size_t slen;
2016
2017 if (unlikely(!s)) {
2018 return talloc_strdup(NULL, a);
2019 }
2020
2021 if (unlikely(!a)) {
2022 return s;
2023 }
2024
2025 slen = talloc_get_size(s);
2026 if (likely(slen > 0)) {
2027 slen--;
2028 }
2029
2030 return __talloc_strlendup_append(s, slen, a, strlen(a));
2031 }
2032
2033 /*
2034 * Appends at the end of the string.
2035 */
talloc_strndup_append(char * s,const char * a,size_t n)2036 _PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n)
2037 {
2038 if (unlikely(!s)) {
2039 return talloc_strdup(NULL, a);
2040 }
2041
2042 if (unlikely(!a)) {
2043 return s;
2044 }
2045
2046 return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
2047 }
2048
2049 /*
2050 * Appends at the end of the talloc'ed buffer,
2051 * not the end of the string.
2052 */
talloc_strndup_append_buffer(char * s,const char * a,size_t n)2053 _PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
2054 {
2055 size_t slen;
2056
2057 if (unlikely(!s)) {
2058 return talloc_strdup(NULL, a);
2059 }
2060
2061 if (unlikely(!a)) {
2062 return s;
2063 }
2064
2065 slen = talloc_get_size(s);
2066 if (likely(slen > 0)) {
2067 slen--;
2068 }
2069
2070 return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
2071 }
2072
talloc_vasprintf(const void * t,const char * fmt,va_list ap)2073 _PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
2074 {
2075 int len;
2076 char *ret;
2077 va_list ap2;
2078 char c;
2079
2080 /* this call looks strange, but it makes it work on older solaris boxes */
2081 va_copy(ap2, ap);
2082 len = vsnprintf(&c, 1, fmt, ap2);
2083 va_end(ap2);
2084 if (unlikely(len < 0)) {
2085 return NULL;
2086 }
2087
2088 ret = (char *)__talloc(t, len+1);
2089 if (unlikely(!ret)) return NULL;
2090
2091 va_copy(ap2, ap);
2092 vsnprintf(ret, len+1, fmt, ap2);
2093 va_end(ap2);
2094
2095 _talloc_set_name_const(ret, ret);
2096 return ret;
2097 }
2098
2099
2100 /*
2101 Perform string formatting, and return a pointer to newly allocated
2102 memory holding the result, inside a memory pool.
2103 */
talloc_asprintf(const void * t,const char * fmt,...)2104 _PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...)
2105 {
2106 va_list ap;
2107 char *ret;
2108
2109 va_start(ap, fmt);
2110 ret = talloc_vasprintf(t, fmt, ap);
2111 va_end(ap);
2112 return ret;
2113 }
2114
2115 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2116 const char *fmt, va_list ap)
2117 PRINTF_ATTRIBUTE(3,0);
2118
__talloc_vaslenprintf_append(char * s,size_t slen,const char * fmt,va_list ap)2119 static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
2120 const char *fmt, va_list ap)
2121 {
2122 ssize_t alen;
2123 va_list ap2;
2124 char c;
2125
2126 va_copy(ap2, ap);
2127 alen = vsnprintf(&c, 1, fmt, ap2);
2128 va_end(ap2);
2129
2130 if (alen <= 0) {
2131 /* Either the vsnprintf failed or the format resulted in
2132 * no characters being formatted. In the former case, we
2133 * ought to return NULL, in the latter we ought to return
2134 * the original string. Most current callers of this
2135 * function expect it to never return NULL.
2136 */
2137 return s;
2138 }
2139
2140 s = talloc_realloc(NULL, s, char, slen + alen + 1);
2141 if (!s) return NULL;
2142
2143 va_copy(ap2, ap);
2144 vsnprintf(s + slen, alen + 1, fmt, ap2);
2145 va_end(ap2);
2146
2147 _talloc_set_name_const(s, s);
2148 return s;
2149 }
2150
2151 /**
2152 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2153 * and return @p s, which may have moved. Good for gradually
2154 * accumulating output into a string buffer. Appends at the end
2155 * of the string.
2156 **/
talloc_vasprintf_append(char * s,const char * fmt,va_list ap)2157 _PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
2158 {
2159 if (unlikely(!s)) {
2160 return talloc_vasprintf(NULL, fmt, ap);
2161 }
2162
2163 return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
2164 }
2165
2166 /**
2167 * Realloc @p s to append the formatted result of @p fmt and @p ap,
2168 * and return @p s, which may have moved. Always appends at the
2169 * end of the talloc'ed buffer, not the end of the string.
2170 **/
talloc_vasprintf_append_buffer(char * s,const char * fmt,va_list ap)2171 _PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
2172 {
2173 size_t slen;
2174
2175 if (unlikely(!s)) {
2176 return talloc_vasprintf(NULL, fmt, ap);
2177 }
2178
2179 slen = talloc_get_size(s);
2180 if (likely(slen > 0)) {
2181 slen--;
2182 }
2183
2184 return __talloc_vaslenprintf_append(s, slen, fmt, ap);
2185 }
2186
2187 /*
2188 Realloc @p s to append the formatted result of @p fmt and return @p
2189 s, which may have moved. Good for gradually accumulating output
2190 into a string buffer.
2191 */
talloc_asprintf_append(char * s,const char * fmt,...)2192 _PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...)
2193 {
2194 va_list ap;
2195
2196 va_start(ap, fmt);
2197 s = talloc_vasprintf_append(s, fmt, ap);
2198 va_end(ap);
2199 return s;
2200 }
2201
2202 /*
2203 Realloc @p s to append the formatted result of @p fmt and return @p
2204 s, which may have moved. Good for gradually accumulating output
2205 into a buffer.
2206 */
talloc_asprintf_append_buffer(char * s,const char * fmt,...)2207 _PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
2208 {
2209 va_list ap;
2210
2211 va_start(ap, fmt);
2212 s = talloc_vasprintf_append_buffer(s, fmt, ap);
2213 va_end(ap);
2214 return s;
2215 }
2216
2217 /*
2218 alloc an array, checking for integer overflow in the array size
2219 */
_talloc_array(const void * ctx,size_t el_size,unsigned count,const char * name)2220 _PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2221 {
2222 if (count >= MAX_TALLOC_SIZE/el_size) {
2223 return NULL;
2224 }
2225 return _talloc_named_const(ctx, el_size * count, name);
2226 }
2227
2228 /*
2229 alloc an zero array, checking for integer overflow in the array size
2230 */
_talloc_zero_array(const void * ctx,size_t el_size,unsigned count,const char * name)2231 _PUBLIC_ void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
2232 {
2233 if (count >= MAX_TALLOC_SIZE/el_size) {
2234 return NULL;
2235 }
2236 return _talloc_zero(ctx, el_size * count, name);
2237 }
2238
2239 /*
2240 realloc an array, checking for integer overflow in the array size
2241 */
_talloc_realloc_array(const void * ctx,void * ptr,size_t el_size,unsigned count,const char * name)2242 _PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
2243 {
2244 if (count >= MAX_TALLOC_SIZE/el_size) {
2245 return NULL;
2246 }
2247 return _talloc_realloc(ctx, ptr, el_size * count, name);
2248 }
2249
2250 /*
2251 a function version of talloc_realloc(), so it can be passed as a function pointer
2252 to libraries that want a realloc function (a realloc function encapsulates
2253 all the basic capabilities of an allocation library, which is why this is useful)
2254 */
talloc_realloc_fn(const void * context,void * ptr,size_t size)2255 _PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
2256 {
2257 return _talloc_realloc(context, ptr, size, NULL);
2258 }
2259
2260
talloc_autofree_destructor(void * ptr)2261 static int talloc_autofree_destructor(void *ptr)
2262 {
2263 autofree_context = NULL;
2264 return 0;
2265 }
2266
talloc_autofree(void)2267 static void talloc_autofree(void)
2268 {
2269 talloc_free(autofree_context);
2270 }
2271
2272 /*
2273 return a context which will be auto-freed on exit
2274 this is useful for reducing the noise in leak reports
2275 */
talloc_autofree_context(void)2276 _PUBLIC_ void *talloc_autofree_context(void)
2277 {
2278 if (autofree_context == NULL) {
2279 autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
2280 talloc_set_destructor(autofree_context, talloc_autofree_destructor);
2281 atexit(talloc_autofree);
2282 }
2283 return autofree_context;
2284 }
2285
talloc_get_size(const void * context)2286 _PUBLIC_ size_t talloc_get_size(const void *context)
2287 {
2288 struct talloc_chunk *tc;
2289
2290 if (context == NULL) {
2291 context = null_context;
2292 }
2293 if (context == NULL) {
2294 return 0;
2295 }
2296
2297 tc = talloc_chunk_from_ptr(context);
2298
2299 return tc->size;
2300 }
2301
2302 /*
2303 find a parent of this context that has the given name, if any
2304 */
talloc_find_parent_byname(const void * context,const char * name)2305 _PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name)
2306 {
2307 struct talloc_chunk *tc;
2308
2309 if (context == NULL) {
2310 return NULL;
2311 }
2312
2313 tc = talloc_chunk_from_ptr(context);
2314 while (tc) {
2315 if (tc->name && strcmp(tc->name, name) == 0) {
2316 return TC_PTR_FROM_CHUNK(tc);
2317 }
2318 while (tc && tc->prev) tc = tc->prev;
2319 if (tc) {
2320 tc = tc->parent;
2321 }
2322 }
2323 return NULL;
2324 }
2325
2326 /*
2327 show the parentage of a context
2328 */
talloc_show_parents(const void * context,FILE * file)2329 _PUBLIC_ void talloc_show_parents(const void *context, FILE *file)
2330 {
2331 struct talloc_chunk *tc;
2332
2333 if (context == NULL) {
2334 fprintf(file, "talloc no parents for NULL\n");
2335 return;
2336 }
2337
2338 tc = talloc_chunk_from_ptr(context);
2339 fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
2340 while (tc) {
2341 fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
2342 while (tc && tc->prev) tc = tc->prev;
2343 if (tc) {
2344 tc = tc->parent;
2345 }
2346 }
2347 fflush(file);
2348 }
2349
2350 /*
2351 return 1 if ptr is a parent of context
2352 */
_talloc_is_parent(const void * context,const void * ptr,int depth)2353 static int _talloc_is_parent(const void *context, const void *ptr, int depth)
2354 {
2355 struct talloc_chunk *tc;
2356
2357 if (context == NULL) {
2358 return 0;
2359 }
2360
2361 tc = talloc_chunk_from_ptr(context);
2362 while (tc && depth > 0) {
2363 if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
2364 while (tc && tc->prev) tc = tc->prev;
2365 if (tc) {
2366 tc = tc->parent;
2367 depth--;
2368 }
2369 }
2370 return 0;
2371 }
2372
2373 /*
2374 return 1 if ptr is a parent of context
2375 */
talloc_is_parent(const void * context,const void * ptr)2376 _PUBLIC_ int talloc_is_parent(const void *context, const void *ptr)
2377 {
2378 return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH);
2379 }
2380