2 Unix SMB/CIFS implementation.
4 local testing of talloc routines.
6 Copyright (C) Andrew Tridgell 2004
8 ** NOTE! The following LGPL license applies to the talloc
9 ** library. This does NOT imply that all of Samba is released
12 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Lesser General Public
14 License as published by the Free Software Foundation; either
15 version 3 of the License, or (at your option) any later version.
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Lesser General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public
23 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 #include "system/time.h"
43 #include "talloc_testsuite.h"
45 #ifndef disable_optimization
46 #if __has_attribute(optimize)
47 #define disable_optimization __attribute__((optimize("O0")))
48 #else /* disable_optimization */
49 #define disable_optimization
51 #endif /* disable_optimization */
53 static struct timeval
private_timeval_current(void)
56 gettimeofday(&tv
, NULL
);
60 static double private_timeval_elapsed(struct timeval
*tv
)
62 struct timeval tv2
= private_timeval_current();
63 return (tv2
.tv_sec
- tv
->tv_sec
) +
64 (tv2
.tv_usec
- tv
->tv_usec
)*1.0e-6;
67 #define torture_assert(test, expr, str) if (!(expr)) { \
68 printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
69 test, __location__, #expr, str); \
73 #define torture_assert_str_equal(test, arg1, arg2, desc) \
74 if (arg1 == NULL && arg2 == NULL) { /* OK, both NULL == equal */ \
75 } else if (arg1 == NULL || arg2 == NULL) { \
77 } else if (strcmp(arg1, arg2)) { \
78 printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
79 test, __location__, arg1, arg2, desc); \
83 #define CHECK_SIZE(test, ptr, tsize) do { \
84 if (talloc_total_size(ptr) != (tsize)) { \
85 printf("failed: %s [\n%s: wrong '%s' tree size: got %u expected %u\n]\n", \
86 test, __location__, #ptr, \
87 (unsigned)talloc_total_size(ptr), \
89 talloc_report_full(ptr, stdout); \
94 #define CHECK_BLOCKS(test, ptr, tblocks) do { \
95 if (talloc_total_blocks(ptr) != (tblocks)) { \
96 printf("failed: %s [\n%s: wrong '%s' tree blocks: got %u expected %u\n]\n", \
97 test, __location__, #ptr, \
98 (unsigned)talloc_total_blocks(ptr), \
100 talloc_report_full(ptr, stdout); \
105 #define CHECK_PARENT(test, ptr, parent) do { \
106 if (talloc_parent(ptr) != (parent)) { \
107 printf("failed: %s [\n%s: '%s' has wrong parent: got %p expected %p\n]\n", \
108 test, __location__, #ptr, \
109 talloc_parent(ptr), \
111 talloc_report_full(ptr, stdout); \
112 talloc_report_full(parent, stdout); \
113 talloc_report_full(NULL, stdout); \
118 static unsigned int test_abort_count
;
121 static void test_abort_fn(const char *reason
)
123 printf("# test_abort_fn(%s)\n", reason
);
127 static void test_abort_start(void)
129 test_abort_count
= 0;
130 talloc_set_abort_fn(test_abort_fn
);
134 static void test_abort_stop(void)
136 test_abort_count
= 0;
137 talloc_set_abort_fn(NULL
);
140 static void test_log_stdout(const char *message
)
142 fprintf(stdout
, "%s", message
);
148 static bool test_ref1(void)
150 void *root
, *p1
, *p2
, *ref
, *r1
;
152 printf("test: ref1\n# SINGLE REFERENCE FREE\n");
154 root
= talloc_named_const(NULL
, 0, "root");
155 p1
= talloc_named_const(root
, 1, "p1");
156 p2
= talloc_named_const(p1
, 1, "p2");
157 talloc_named_const(p1
, 1, "x1");
158 talloc_named_const(p1
, 2, "x2");
159 talloc_named_const(p1
, 3, "x3");
161 r1
= talloc_named_const(root
, 1, "r1");
162 ref
= talloc_reference(r1
, p2
);
163 talloc_report_full(root
, stderr
);
165 CHECK_BLOCKS("ref1", p1
, 5);
166 CHECK_BLOCKS("ref1", p2
, 1);
167 CHECK_BLOCKS("ref1", ref
, 1);
168 CHECK_BLOCKS("ref1", r1
, 2);
170 fprintf(stderr
, "Freeing p2\n");
171 talloc_unlink(r1
, p2
);
172 talloc_report_full(root
, stderr
);
174 CHECK_BLOCKS("ref1", p1
, 5);
175 CHECK_BLOCKS("ref1", p2
, 1);
176 CHECK_BLOCKS("ref1", r1
, 1);
178 fprintf(stderr
, "Freeing p1\n");
180 talloc_report_full(root
, stderr
);
182 CHECK_BLOCKS("ref1", r1
, 1);
184 fprintf(stderr
, "Freeing r1\n");
186 talloc_report_full(NULL
, stderr
);
188 fprintf(stderr
, "Testing NULL\n");
189 if (talloc_reference(root
, NULL
)) {
193 CHECK_BLOCKS("ref1", root
, 1);
195 CHECK_SIZE("ref1", root
, 0);
198 printf("success: ref1\n");
205 static bool test_ref2(void)
207 void *root
, *p1
, *p2
, *ref
, *r1
;
209 printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
210 root
= talloc_named_const(NULL
, 0, "root");
211 p1
= talloc_named_const(root
, 1, "p1");
212 talloc_named_const(p1
, 1, "x1");
213 talloc_named_const(p1
, 1, "x2");
214 talloc_named_const(p1
, 1, "x3");
215 p2
= talloc_named_const(p1
, 1, "p2");
217 r1
= talloc_named_const(root
, 1, "r1");
218 ref
= talloc_reference(r1
, p2
);
219 talloc_report_full(root
, stderr
);
221 CHECK_BLOCKS("ref2", p1
, 5);
222 CHECK_BLOCKS("ref2", p2
, 1);
223 CHECK_BLOCKS("ref2", r1
, 2);
225 fprintf(stderr
, "Freeing ref\n");
226 talloc_unlink(r1
, ref
);
227 talloc_report_full(root
, stderr
);
229 CHECK_BLOCKS("ref2", p1
, 5);
230 CHECK_BLOCKS("ref2", p2
, 1);
231 CHECK_BLOCKS("ref2", r1
, 1);
233 fprintf(stderr
, "Freeing p2\n");
235 talloc_report_full(root
, stderr
);
237 CHECK_BLOCKS("ref2", p1
, 4);
238 CHECK_BLOCKS("ref2", r1
, 1);
240 fprintf(stderr
, "Freeing p1\n");
242 talloc_report_full(root
, stderr
);
244 CHECK_BLOCKS("ref2", r1
, 1);
246 fprintf(stderr
, "Freeing r1\n");
248 talloc_report_full(root
, stderr
);
250 CHECK_SIZE("ref2", root
, 0);
253 printf("success: ref2\n");
260 static bool test_ref3(void)
262 void *root
, *p1
, *p2
, *ref
, *r1
;
264 printf("test: ref3\n# PARENT REFERENCE FREE\n");
266 root
= talloc_named_const(NULL
, 0, "root");
267 p1
= talloc_named_const(root
, 1, "p1");
268 p2
= talloc_named_const(root
, 1, "p2");
269 r1
= talloc_named_const(p1
, 1, "r1");
270 ref
= talloc_reference(p2
, r1
);
271 talloc_report_full(root
, stderr
);
273 CHECK_BLOCKS("ref3", p1
, 2);
274 CHECK_BLOCKS("ref3", p2
, 2);
275 CHECK_BLOCKS("ref3", r1
, 1);
276 CHECK_BLOCKS("ref3", ref
, 1);
278 fprintf(stderr
, "Freeing p1\n");
280 talloc_report_full(root
, stderr
);
282 CHECK_BLOCKS("ref3", p2
, 2);
283 CHECK_BLOCKS("ref3", r1
, 1);
285 fprintf(stderr
, "Freeing p2\n");
287 talloc_report_full(root
, stderr
);
289 CHECK_SIZE("ref3", root
, 0);
293 printf("success: ref3\n");
300 static bool test_ref4(void)
302 void *root
, *p1
, *p2
, *ref
, *r1
;
304 printf("test: ref4\n# REFERRER REFERENCE FREE\n");
306 root
= talloc_named_const(NULL
, 0, "root");
307 p1
= talloc_named_const(root
, 1, "p1");
308 talloc_named_const(p1
, 1, "x1");
309 talloc_named_const(p1
, 1, "x2");
310 talloc_named_const(p1
, 1, "x3");
311 p2
= talloc_named_const(p1
, 1, "p2");
313 r1
= talloc_named_const(root
, 1, "r1");
314 ref
= talloc_reference(r1
, p2
);
315 talloc_report_full(root
, stderr
);
317 CHECK_BLOCKS("ref4", p1
, 5);
318 CHECK_BLOCKS("ref4", p2
, 1);
319 CHECK_BLOCKS("ref4", ref
, 1);
320 CHECK_BLOCKS("ref4", r1
, 2);
322 fprintf(stderr
, "Freeing r1\n");
324 talloc_report_full(root
, stderr
);
326 CHECK_BLOCKS("ref4", p1
, 5);
327 CHECK_BLOCKS("ref4", p2
, 1);
329 fprintf(stderr
, "Freeing p2\n");
331 talloc_report_full(root
, stderr
);
333 CHECK_BLOCKS("ref4", p1
, 4);
335 fprintf(stderr
, "Freeing p1\n");
337 talloc_report_full(root
, stderr
);
339 CHECK_SIZE("ref4", root
, 0);
343 printf("success: ref4\n");
351 static bool test_unlink1(void)
353 void *root
, *p1
, *p2
, *ref
, *r1
;
355 printf("test: unlink\n# UNLINK\n");
357 root
= talloc_named_const(NULL
, 0, "root");
358 p1
= talloc_named_const(root
, 1, "p1");
359 talloc_named_const(p1
, 1, "x1");
360 talloc_named_const(p1
, 1, "x2");
361 talloc_named_const(p1
, 1, "x3");
362 p2
= talloc_named_const(p1
, 1, "p2");
364 r1
= talloc_named_const(p1
, 1, "r1");
365 ref
= talloc_reference(r1
, p2
);
366 talloc_report_full(root
, stderr
);
368 CHECK_BLOCKS("unlink", p1
, 7);
369 CHECK_BLOCKS("unlink", p2
, 1);
370 CHECK_BLOCKS("unlink", ref
, 1);
371 CHECK_BLOCKS("unlink", r1
, 2);
373 fprintf(stderr
, "Unreferencing r1\n");
374 talloc_unlink(r1
, p2
);
375 talloc_report_full(root
, stderr
);
377 CHECK_BLOCKS("unlink", p1
, 6);
378 CHECK_BLOCKS("unlink", p2
, 1);
379 CHECK_BLOCKS("unlink", r1
, 1);
381 fprintf(stderr
, "Freeing p1\n");
383 talloc_report_full(root
, stderr
);
385 CHECK_SIZE("unlink", root
, 0);
389 printf("success: unlink\n");
393 static int fail_destructor(void *ptr
)
399 miscellaneous tests to try to get a higher test coverage percentage
401 static bool test_misc(void)
408 printf("test: misc\n# MISCELLANEOUS\n");
410 root
= talloc_new(NULL
);
412 p1
= talloc_size(root
, 0x7fffffff);
413 torture_assert("misc", !p1
, "failed: large talloc allowed\n");
415 p1
= talloc_strdup(root
, "foo");
416 talloc_increase_ref_count(p1
);
417 talloc_increase_ref_count(p1
);
418 talloc_increase_ref_count(p1
);
419 CHECK_BLOCKS("misc", p1
, 1);
420 CHECK_BLOCKS("misc", root
, 2);
421 talloc_unlink(NULL
, p1
);
422 CHECK_BLOCKS("misc", p1
, 1);
423 CHECK_BLOCKS("misc", root
, 2);
424 talloc_unlink(NULL
, p1
);
425 CHECK_BLOCKS("misc", p1
, 1);
426 CHECK_BLOCKS("misc", root
, 2);
427 p2
= talloc_strdup(p1
, "foo");
428 torture_assert("misc", talloc_unlink(root
, p2
) == -1,
429 "failed: talloc_unlink() of non-reference context should return -1\n");
430 torture_assert("misc", talloc_unlink(p1
, p2
) == 0,
431 "failed: talloc_unlink() of parent should succeed\n");
432 talloc_unlink(NULL
, p1
);
433 CHECK_BLOCKS("misc", p1
, 1);
434 CHECK_BLOCKS("misc", root
, 2);
436 name
= talloc_set_name(p1
, "my name is %s", "foo");
437 torture_assert_str_equal("misc", talloc_get_name(p1
), "my name is foo",
438 "failed: wrong name after talloc_set_name(my name is foo)");
439 torture_assert_str_equal("misc", talloc_get_name(p1
), name
,
440 "failed: wrong name after talloc_set_name(my name is foo)");
441 CHECK_BLOCKS("misc", p1
, 2);
442 CHECK_BLOCKS("misc", root
, 3);
444 talloc_set_name_const(p1
, NULL
);
445 torture_assert_str_equal ("misc", talloc_get_name(p1
), "UNNAMED",
446 "failed: wrong name after talloc_set_name(NULL)");
447 CHECK_BLOCKS("misc", p1
, 2);
448 CHECK_BLOCKS("misc", root
, 3);
450 torture_assert("misc", talloc_free(NULL
) == -1,
451 "talloc_free(NULL) should give -1\n");
453 talloc_set_destructor(p1
, fail_destructor
);
454 torture_assert("misc", talloc_free(p1
) == -1,
455 "Failed destructor should cause talloc_free to fail\n");
456 talloc_set_destructor(p1
, NULL
);
458 talloc_report(root
, stderr
);
461 p2
= (char *)talloc_zero_size(p1
, 20);
462 torture_assert("misc", p2
[19] == 0, "Failed to give zero memory\n");
465 torture_assert("misc", talloc_strdup(root
, NULL
) == NULL
,
466 "failed: strdup on NULL should give NULL\n");
468 p2
= talloc_strndup(p1
, "foo", 2);
469 torture_assert("misc", strcmp("fo", p2
) == 0,
470 "strndup doesn't work\n");
471 p2
= talloc_asprintf_append_buffer(p2
, "o%c", 'd');
472 torture_assert("misc", strcmp("food", p2
) == 0,
473 "talloc_asprintf_append_buffer doesn't work\n");
474 CHECK_BLOCKS("misc", p2
, 1);
475 CHECK_BLOCKS("misc", p1
, 3);
477 p2
= talloc_asprintf_append_buffer(NULL
, "hello %s", "world");
478 torture_assert("misc", strcmp("hello world", p2
) == 0,
479 "talloc_asprintf_append_buffer doesn't work\n");
480 CHECK_BLOCKS("misc", p2
, 1);
481 CHECK_BLOCKS("misc", p1
, 3);
484 d
= talloc_array(p1
, double, 0x20000000);
485 torture_assert("misc", !d
, "failed: integer overflow not detected\n");
487 d
= talloc_realloc(p1
, d
, double, 0x20000000);
488 torture_assert("misc", !d
, "failed: integer overflow not detected\n");
491 CHECK_BLOCKS("misc", root
, 1);
493 p1
= talloc_named(root
, 100, "%d bytes", 100);
494 CHECK_BLOCKS("misc", p1
, 2);
495 CHECK_BLOCKS("misc", root
, 3);
496 talloc_unlink(root
, p1
);
498 p1
= talloc_init("%d bytes", 200);
499 p2
= talloc_asprintf(p1
, "my test '%s'", "string");
500 torture_assert_str_equal("misc", p2
, "my test 'string'",
501 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
502 CHECK_BLOCKS("misc", p1
, 3);
503 CHECK_SIZE("misc", p2
, 17);
504 CHECK_BLOCKS("misc", root
, 1);
505 talloc_unlink(NULL
, p1
);
507 p1
= talloc_named_const(root
, 10, "p1");
508 p2
= (char *)talloc_named_const(root
, 20, "p2");
509 (void)talloc_reference(p1
, p2
);
510 talloc_report_full(root
, stderr
);
511 talloc_unlink(root
, p2
);
512 talloc_report_full(root
, stderr
);
513 CHECK_BLOCKS("misc", p2
, 1);
514 CHECK_BLOCKS("misc", p1
, 2);
515 CHECK_BLOCKS("misc", root
, 3);
516 talloc_unlink(p1
, p2
);
517 talloc_unlink(root
, p1
);
519 p1
= talloc_named_const(root
, 10, "p1");
520 p2
= (char *)talloc_named_const(root
, 20, "p2");
521 (void)talloc_reference(NULL
, p2
);
522 talloc_report_full(root
, stderr
);
523 talloc_unlink(root
, p2
);
524 talloc_report_full(root
, stderr
);
525 CHECK_BLOCKS("misc", p2
, 1);
526 CHECK_BLOCKS("misc", p1
, 1);
527 CHECK_BLOCKS("misc", root
, 2);
528 talloc_unlink(NULL
, p2
);
529 talloc_unlink(root
, p1
);
531 /* Test that talloc_unlink is a no-op */
533 torture_assert("misc", talloc_unlink(root
, NULL
) == -1,
534 "failed: talloc_unlink(root, NULL) == -1\n");
536 talloc_report(root
, stderr
);
537 talloc_report(NULL
, stderr
);
539 CHECK_SIZE("misc", root
, 0);
543 CHECK_SIZE("misc", NULL
, 0);
545 talloc_enable_null_tracking_no_autofree();
546 talloc_enable_leak_report();
547 talloc_enable_leak_report_full();
549 printf("success: misc\n");
558 static bool test_realloc(void)
560 void *root
, *p1
, *p2
;
562 printf("test: realloc\n# REALLOC\n");
564 root
= talloc_new(NULL
);
566 p1
= talloc_size(root
, 10);
567 CHECK_SIZE("realloc", p1
, 10);
569 p1
= talloc_realloc_size(NULL
, p1
, 20);
570 CHECK_SIZE("realloc", p1
, 20);
574 p2
= talloc_realloc_size(p1
, NULL
, 30);
578 p2
= talloc_realloc_size(p1
, p2
, 40);
580 CHECK_SIZE("realloc", p2
, 40);
581 CHECK_SIZE("realloc", root
, 60);
582 CHECK_BLOCKS("realloc", p1
, 4);
584 p1
= talloc_realloc_size(NULL
, p1
, 20);
585 CHECK_SIZE("realloc", p1
, 60);
587 talloc_increase_ref_count(p2
);
588 torture_assert("realloc", talloc_realloc_size(NULL
, p2
, 5) == NULL
,
589 "failed: talloc_realloc() on a referenced pointer should fail\n");
590 CHECK_BLOCKS("realloc", p1
, 4);
592 talloc_realloc_size(NULL
, p2
, 0);
593 talloc_realloc_size(NULL
, p2
, 0);
594 CHECK_BLOCKS("realloc", p1
, 4);
595 talloc_realloc_size(p1
, p2
, 0);
596 CHECK_BLOCKS("realloc", p1
, 3);
598 torture_assert("realloc", talloc_realloc_size(NULL
, p1
, 0x7fffffff) == NULL
,
599 "failed: oversize talloc should fail\n");
601 talloc_realloc_size(NULL
, p1
, 0);
602 CHECK_BLOCKS("realloc", root
, 4);
603 talloc_realloc_size(root
, p1
, 0);
604 CHECK_BLOCKS("realloc", root
, 1);
606 CHECK_SIZE("realloc", root
, 0);
610 printf("success: realloc\n");
616 test realloc with a child
618 static bool test_realloc_child(void)
623 } *el2
, *el2_2
, *el2_3
, **el_list_save
;
626 struct el2
**list
, **list2
, **list3
;
629 printf("test: REALLOC WITH CHILD\n");
631 root
= talloc_new(NULL
);
633 el1
= talloc(root
, struct el1
);
634 el1
->list
= talloc(el1
, struct el2
*);
635 el1
->list
[0] = talloc(el1
->list
, struct el2
);
636 el1
->list
[0]->name
= talloc_strdup(el1
->list
[0], "testing");
638 el1
->list2
= talloc(el1
, struct el2
*);
639 el1
->list2
[0] = talloc(el1
->list2
, struct el2
);
640 el1
->list2
[0]->name
= talloc_strdup(el1
->list2
[0], "testing2");
642 el1
->list3
= talloc(el1
, struct el2
*);
643 el1
->list3
[0] = talloc(el1
->list3
, struct el2
);
644 el1
->list3
[0]->name
= talloc_strdup(el1
->list3
[0], "testing2");
646 el2
= talloc(el1
->list
, struct el2
);
647 CHECK_PARENT("el2", el2
, el1
->list
);
648 el2_2
= talloc(el1
->list2
, struct el2
);
649 CHECK_PARENT("el2", el2_2
, el1
->list2
);
650 el2_3
= talloc(el1
->list3
, struct el2
);
651 CHECK_PARENT("el2", el2_3
, el1
->list3
);
653 el_list_save
= el1
->list
;
654 el1
->list
= talloc_realloc(el1
, el1
->list
, struct el2
*, 100);
655 if (el1
->list
== el_list_save
) {
656 printf("failure: talloc_realloc didn't move pointer");
660 CHECK_PARENT("el1_after_realloc", el1
->list
, el1
);
661 el1
->list2
= talloc_realloc(el1
, el1
->list2
, struct el2
*, 200);
662 CHECK_PARENT("el1_after_realloc", el1
->list2
, el1
);
663 el1
->list3
= talloc_realloc(el1
, el1
->list3
, struct el2
*, 300);
664 CHECK_PARENT("el1_after_realloc", el1
->list3
, el1
);
666 CHECK_PARENT("el2", el2
, el1
->list
);
667 CHECK_PARENT("el2", el2_2
, el1
->list2
);
668 CHECK_PARENT("el2", el2_3
, el1
->list3
);
670 /* Finally check realloc with multiple children */
671 el1
= talloc_realloc(root
, el1
, struct el1
, 100);
672 CHECK_PARENT("el1->list", el1
->list
, el1
);
673 CHECK_PARENT("el1->list2", el1
->list2
, el1
);
674 CHECK_PARENT("el1->list3", el1
->list3
, el1
);
678 printf("success: REALLOC WITH CHILD\n");
685 static bool test_type(void)
696 printf("test: type\n# talloc type checking\n");
698 root
= talloc_new(NULL
);
700 el1
= talloc(root
, struct el1
);
704 torture_assert("type", talloc_get_type(el1
, struct el1
) == el1
,
705 "type check failed on el1\n");
706 torture_assert("type", talloc_get_type(el1
, struct el2
) == NULL
,
707 "type check failed on el1 with el2\n");
708 talloc_set_type(el1
, struct el2
);
709 torture_assert("type", talloc_get_type(el1
, struct el2
) == (struct el2
*)el1
,
710 "type set failed on el1 with el2\n");
714 printf("success: type\n");
721 static bool test_steal(void)
723 void *root
, *p1
, *p2
;
725 printf("test: steal\n# STEAL\n");
727 root
= talloc_new(NULL
);
729 p1
= talloc_array(root
, char, 10);
730 CHECK_SIZE("steal", p1
, 10);
732 p2
= talloc_realloc(root
, NULL
, char, 20);
733 CHECK_SIZE("steal", p1
, 10);
734 CHECK_SIZE("steal", root
, 30);
736 torture_assert("steal", talloc_steal(p1
, NULL
) == NULL
,
737 "failed: stealing NULL should give NULL\n");
739 torture_assert("steal", talloc_steal(p1
, p1
) == p1
,
740 "failed: stealing to ourselves is a nop\n");
741 CHECK_BLOCKS("steal", root
, 3);
742 CHECK_SIZE("steal", root
, 30);
744 talloc_steal(NULL
, p1
);
745 talloc_steal(NULL
, p2
);
746 CHECK_BLOCKS("steal", root
, 1);
747 CHECK_SIZE("steal", root
, 0);
750 talloc_steal(root
, p2
);
751 CHECK_BLOCKS("steal", root
, 2);
752 CHECK_SIZE("steal", root
, 20);
756 CHECK_BLOCKS("steal", root
, 1);
757 CHECK_SIZE("steal", root
, 0);
761 p1
= talloc_size(NULL
, 3);
762 talloc_report_full(NULL
, stderr
);
763 CHECK_SIZE("steal", NULL
, 3);
766 printf("success: steal\n");
773 static bool test_move(void)
781 printf("test: move\n# MOVE\n");
783 root
= talloc_new(NULL
);
785 t1
= talloc(root
, struct t_move
);
786 t2
= talloc(root
, struct t_move
);
787 t1
->p
= talloc_strdup(t1
, "foo");
788 t1
->x
= talloc(t1
, int);
791 t2
->p
= talloc_move(t2
, &t1
->p
);
792 t2
->x
= talloc_move(t2
, &t1
->x
);
793 torture_assert("move", t1
->p
== NULL
&& t1
->x
== NULL
&&
794 strcmp(t2
->p
, "foo") == 0 && *t2
->x
== 42,
795 "talloc move failed");
799 printf("success: move\n");
805 test talloc_realloc_fn
807 static bool test_realloc_fn(void)
811 printf("test: realloc_fn\n# talloc_realloc_fn\n");
813 root
= talloc_new(NULL
);
815 p1
= talloc_realloc_fn(root
, NULL
, 10);
816 CHECK_BLOCKS("realloc_fn", root
, 2);
817 CHECK_SIZE("realloc_fn", root
, 10);
818 p1
= talloc_realloc_fn(root
, p1
, 20);
819 CHECK_BLOCKS("realloc_fn", root
, 2);
820 CHECK_SIZE("realloc_fn", root
, 20);
821 p1
= talloc_realloc_fn(root
, p1
, 0);
822 CHECK_BLOCKS("realloc_fn", root
, 1);
823 CHECK_SIZE("realloc_fn", root
, 0);
827 printf("success: realloc_fn\n");
832 static bool test_unref_reparent(void)
834 void *root
, *p1
, *p2
, *c1
;
836 printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
838 root
= talloc_named_const(NULL
, 0, "root");
839 p1
= talloc_named_const(root
, 1, "orig parent");
840 p2
= talloc_named_const(root
, 1, "parent by reference");
842 c1
= talloc_named_const(p1
, 1, "child");
843 talloc_reference(p2
, c1
);
845 CHECK_PARENT("unref_reparent", c1
, p1
);
849 CHECK_PARENT("unref_reparent", c1
, p2
);
851 talloc_unlink(p2
, c1
);
853 CHECK_SIZE("unref_reparent", root
, 1);
858 printf("success: unref_reparent\n");
862 /* Make the size big enough to not fit into the stack */
863 #define ALLOC_SIZE (128 * 1024)
864 #define ALLOC_DUP_STRING "talloc talloc talloc talloc talloc talloc talloc"
867 measure the speed of talloc versus malloc
869 static bool test_speed(void) disable_optimization
;
870 static bool test_speed(void)
872 void *ctx
= talloc_new(NULL
);
874 const int loop
= 1000;
878 printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
880 tv
= private_timeval_current();
884 for (i
=0;i
<loop
;i
++) {
885 p1
= talloc_size(ctx
, loop
% ALLOC_SIZE
);
886 p2
= talloc_strdup(p1
, ALLOC_DUP_STRING
);
887 p3
= talloc_size(p1
, ALLOC_SIZE
);
893 } while (private_timeval_elapsed(&tv
) < 5.0);
895 fprintf(stderr
, "talloc:\t\t%.0f ops/sec\n", count
/private_timeval_elapsed(&tv
));
899 ctx
= talloc_pool(NULL
, ALLOC_SIZE
* 2);
901 tv
= private_timeval_current();
905 for (i
=0;i
<loop
;i
++) {
906 p1
= talloc_size(ctx
, loop
% ALLOC_SIZE
);
907 p2
= talloc_strdup(p1
, ALLOC_DUP_STRING
);
908 p3
= talloc_size(p1
, ALLOC_SIZE
);
914 } while (private_timeval_elapsed(&tv
) < 5.0);
918 fprintf(stderr
, "talloc_pool:\t%.0f ops/sec\n", count
/private_timeval_elapsed(&tv
));
920 tv
= private_timeval_current();
924 for (i
=0;i
<loop
;i
++) {
925 p1
= malloc(loop
% ALLOC_SIZE
);
926 p2
= strdup(ALLOC_DUP_STRING
);
927 p3
= malloc(ALLOC_SIZE
);
933 } while (private_timeval_elapsed(&tv
) < 5.0);
934 fprintf(stderr
, "malloc:\t\t%.0f ops/sec\n", count
/private_timeval_elapsed(&tv
));
936 printf("\n# TALLOC_ZERO VS CALLOC SPEED\n");
938 ctx
= talloc_new(NULL
);
940 tv
= private_timeval_current();
944 for (i
=0;i
<loop
;i
++) {
945 p1
= talloc_zero_size(ctx
, loop
% ALLOC_SIZE
);
946 p2
= talloc_strdup(p1
, ALLOC_DUP_STRING
);
947 p3
= talloc_zero_size(p1
, ALLOC_SIZE
);
953 } while (private_timeval_elapsed(&tv
) < 5.0);
955 fprintf(stderr
, "talloc_zero:\t%.0f ops/sec\n", count
/private_timeval_elapsed(&tv
));
959 tv
= private_timeval_current();
963 for (i
=0;i
<loop
;i
++) {
964 p1
= calloc(1, loop
% ALLOC_SIZE
);
965 p2
= strdup(ALLOC_DUP_STRING
);
966 p3
= calloc(1, ALLOC_SIZE
);
972 } while (private_timeval_elapsed(&tv
) < 5.0);
973 fprintf(stderr
, "calloc:\t\t%.0f ops/sec\n", count
/private_timeval_elapsed(&tv
));
975 printf("success: speed\n");
980 static bool test_lifeless(void)
982 void *top
= talloc_new(NULL
);
983 char *parent
, *child
;
984 void *child_owner
= talloc_new(NULL
);
986 printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
988 parent
= talloc_strdup(top
, "parent");
989 child
= talloc_strdup(parent
, "child");
990 (void)talloc_reference(child
, parent
);
991 (void)talloc_reference(child_owner
, child
);
992 talloc_report_full(top
, stderr
);
993 talloc_unlink(top
, parent
);
994 talloc_unlink(top
, child
);
995 talloc_report_full(top
, stderr
);
997 talloc_free(child_owner
);
1000 printf("success: lifeless\n");
1004 static int loop_destructor_count
;
1006 static int test_loop_destructor(char *ptr
)
1008 loop_destructor_count
++;
1012 static bool test_loop(void)
1014 void *top
= talloc_new(NULL
);
1020 printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
1022 parent
= talloc_strdup(top
, "parent");
1023 req1
= talloc(parent
, struct req1
);
1024 req1
->req2
= talloc_strdup(req1
, "req2");
1025 talloc_set_destructor(req1
->req2
, test_loop_destructor
);
1026 req1
->req3
= talloc_strdup(req1
, "req3");
1027 (void)talloc_reference(req1
->req3
, req1
);
1028 talloc_report_full(top
, stderr
);
1029 talloc_free(parent
);
1030 talloc_report_full(top
, stderr
);
1031 talloc_report_full(NULL
, stderr
);
1034 torture_assert("loop", loop_destructor_count
== 1,
1035 "FAILED TO FIRE LOOP DESTRUCTOR\n");
1036 loop_destructor_count
= 0;
1038 printf("success: loop\n");
1042 static int realloc_parent_destructor_count
;
1044 static int test_realloc_parent_destructor(char *ptr
)
1046 realloc_parent_destructor_count
++;
1050 static bool test_realloc_on_destructor_parent(void)
1052 void *top
= talloc_new(NULL
);
1054 char *a
, *b
, *C
, *D
;
1055 realloc_parent_destructor_count
= 0;
1057 printf("test: free_for_exit\n# TALLOC FREE FOR EXIT\n");
1059 parent
= talloc_strdup(top
, "parent");
1060 a
= talloc_strdup(parent
, "a");
1061 b
= talloc_strdup(a
, "b");
1062 C
= talloc_strdup(a
, "C");
1063 D
= talloc_strdup(b
, "D");
1064 talloc_set_destructor(D
, test_realloc_parent_destructor
);
1065 /* Capitalised ones have destructors.
1067 * parent --> a -> b -> D
1071 a
= talloc_realloc(parent
, a
, char, 2048);
1073 torture_assert("check talloc_realloc", a
!= NULL
, "talloc_realloc failed");
1075 talloc_set_destructor(C
, test_realloc_parent_destructor
);
1077 * parent --> a[2048] -> b -> D
1082 talloc_free(parent
);
1084 torture_assert("check destructor realloc_parent_destructor",
1085 realloc_parent_destructor_count
== 2,
1086 "FAILED TO FIRE free_for_exit_destructor\n");
1089 printf("success: free_for_exit\n");
1090 talloc_free(top
); /* make ASAN happy */
1095 static int fail_destructor_str(char *ptr
)
1100 static bool test_free_parent_deny_child(void)
1102 void *top
= talloc_new(NULL
);
1107 printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
1109 level1
= talloc_strdup(top
, "level1");
1110 level2
= talloc_strdup(level1
, "level2");
1111 level3
= talloc_strdup(level2
, "level3");
1113 talloc_set_destructor(level3
, fail_destructor_str
);
1114 talloc_free(level1
);
1115 talloc_set_destructor(level3
, NULL
);
1117 CHECK_PARENT("free_parent_deny_child", level3
, top
);
1121 printf("success: free_parent_deny_child\n");
1130 static int reparenting_destructor(struct new_parent
*np
)
1132 talloc_set_destructor(np
, NULL
);
1133 (void)talloc_move(np
->new_parent
, &np
);
1137 static bool test_free_parent_reparent_child(void)
1139 void *top
= talloc_new(NULL
);
1141 char *alternate_level1
;
1143 struct new_parent
*level3
;
1145 printf("test: free_parent_reparent_child\n# "
1146 "TALLOC FREE PARENT REPARENT CHILD\n");
1148 level1
= talloc_strdup(top
, "level1");
1149 alternate_level1
= talloc_strdup(top
, "alternate_level1");
1150 level2
= talloc_strdup(level1
, "level2");
1151 level3
= talloc(level2
, struct new_parent
);
1152 level3
->new_parent
= alternate_level1
;
1153 memset(level3
->val
, 'x', sizeof(level3
->val
));
1155 talloc_set_destructor(level3
, reparenting_destructor
);
1156 talloc_free(level1
);
1158 CHECK_PARENT("free_parent_reparent_child",
1159 level3
, alternate_level1
);
1163 printf("success: free_parent_reparent_child\n");
1167 static bool test_free_parent_reparent_child_in_pool(void)
1169 void *top
= talloc_new(NULL
);
1171 char *alternate_level1
;
1174 struct new_parent
*level3
;
1176 printf("test: free_parent_reparent_child_in_pool\n# "
1177 "TALLOC FREE PARENT REPARENT CHILD IN POOL\n");
1179 pool
= talloc_pool(top
, 1024);
1180 level1
= talloc_strdup(pool
, "level1");
1181 alternate_level1
= talloc_strdup(top
, "alternate_level1");
1182 level2
= talloc_strdup(level1
, "level2");
1183 level3
= talloc(level2
, struct new_parent
);
1184 level3
->new_parent
= alternate_level1
;
1185 memset(level3
->val
, 'x', sizeof(level3
->val
));
1187 talloc_set_destructor(level3
, reparenting_destructor
);
1188 talloc_free(level1
);
1189 talloc_set_destructor(level3
, NULL
);
1191 CHECK_PARENT("free_parent_reparent_child_in_pool",
1192 level3
, alternate_level1
);
1194 /* Even freeing alternate_level1 should leave pool alone. */
1195 talloc_free(alternate_level1
);
1198 printf("success: free_parent_reparent_child_in_pool\n");
1203 static bool test_talloc_ptrtype(void)
1205 void *top
= talloc_new(NULL
);
1209 } *s1
, *s2
, **s3
, ***s4
;
1210 const char *location1
;
1211 const char *location2
;
1212 const char *location3
;
1213 const char *location4
;
1215 printf("test: ptrtype\n# TALLOC PTRTYPE\n");
1217 s1
= talloc_ptrtype(top
, s1
);location1
= __location__
;
1219 if (talloc_get_size(s1
) != sizeof(struct struct1
)) {
1220 printf("failure: ptrtype [\n"
1221 "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1222 "]\n", (unsigned long)talloc_get_size(s1
),
1223 (unsigned long)sizeof(struct struct1
));
1227 if (strcmp(location1
, talloc_get_name(s1
)) != 0) {
1228 printf("failure: ptrtype [\n"
1229 "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1230 talloc_get_name(s1
), location1
);
1234 s2
= talloc_array_ptrtype(top
, s2
, 10);location2
= __location__
;
1236 if (talloc_get_size(s2
) != (sizeof(struct struct1
) * 10)) {
1237 printf("failure: ptrtype [\n"
1238 "talloc_array_ptrtype() allocated the wrong size "
1239 "%lu (should be %lu)\n]\n",
1240 (unsigned long)talloc_get_size(s2
),
1241 (unsigned long)(sizeof(struct struct1
)*10));
1245 if (strcmp(location2
, talloc_get_name(s2
)) != 0) {
1246 printf("failure: ptrtype [\n"
1247 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1248 talloc_get_name(s2
), location2
);
1252 s3
= talloc_array_ptrtype(top
, s3
, 10);location3
= __location__
;
1254 if (talloc_get_size(s3
) != (sizeof(struct struct1
*) * 10)) {
1255 printf("failure: ptrtype [\n"
1256 "talloc_array_ptrtype() allocated the wrong size "
1257 "%lu (should be %lu)\n]\n",
1258 (unsigned long)talloc_get_size(s3
),
1259 (unsigned long)(sizeof(struct struct1
*)*10));
1263 torture_assert_str_equal("ptrtype", location3
, talloc_get_name(s3
),
1264 "talloc_array_ptrtype() sets the wrong name");
1266 s4
= talloc_array_ptrtype(top
, s4
, 10);location4
= __location__
;
1268 if (talloc_get_size(s4
) != (sizeof(struct struct1
**) * 10)) {
1269 printf("failure: ptrtype [\n"
1270 "talloc_array_ptrtype() allocated the wrong size "
1271 "%lu (should be %lu)\n]\n",
1272 (unsigned long)talloc_get_size(s4
),
1273 (unsigned long)(sizeof(struct struct1
**)*10));
1277 torture_assert_str_equal("ptrtype", location4
, talloc_get_name(s4
),
1278 "talloc_array_ptrtype() sets the wrong name");
1282 printf("success: ptrtype\n");
1286 static int _test_talloc_free_in_destructor(void **ptr
)
1292 static bool test_talloc_free_in_destructor(void)
1301 printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1303 level0
= talloc_new(NULL
);
1304 level1
= talloc_new(level0
);
1305 level2
= talloc_new(level1
);
1306 level3
= talloc_new(level2
);
1307 level4
= talloc_new(level3
);
1308 level5
= talloc(level4
, void *);
1311 (void)talloc_reference(level0
, level3
);
1312 (void)talloc_reference(level3
, level3
);
1313 (void)talloc_reference(level5
, level3
);
1315 talloc_set_destructor(level5
, _test_talloc_free_in_destructor
);
1317 talloc_free(level1
);
1319 talloc_free(level0
);
1321 talloc_free(level3
); /* make ASAN happy */
1323 printf("success: free_in_destructor\n");
1327 static bool test_autofree(void)
1329 #if _SAMBA_BUILD_ < 4
1330 /* autofree test would kill smbtorture */
1332 printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1334 p
= talloc_autofree_context();
1337 p
= talloc_autofree_context();
1340 printf("success: autofree\n");
1345 static bool test_pool(void)
1348 void *p1
, *p2
, *p3
, *p4
;
1351 pool
= talloc_pool(NULL
, 1024);
1353 p1
= talloc_size(pool
, 80);
1354 memset(p1
, 0x11, talloc_get_size(p1
));
1355 p2
= talloc_size(pool
, 20);
1356 memset(p2
, 0x11, talloc_get_size(p2
));
1357 p3
= talloc_size(p1
, 50);
1358 memset(p3
, 0x11, talloc_get_size(p3
));
1359 p4
= talloc_size(p3
, 1000);
1360 memset(p4
, 0x11, talloc_get_size(p4
));
1362 p2_2
= talloc_realloc_size(pool
, p2
, 20+1);
1363 torture_assert("pool realloc 20+1", p2_2
== p2
, "failed: pointer changed");
1364 memset(p2
, 0x11, talloc_get_size(p2
));
1365 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1366 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1367 memset(p2
, 0x11, talloc_get_size(p2
));
1368 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1369 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1370 memset(p2
, 0x11, talloc_get_size(p2
));
1374 /* this should reclaim the memory of p4 and p3 */
1375 p2_2
= talloc_realloc_size(pool
, p2
, 400);
1376 torture_assert("pool realloc 400", p2_2
== p2
, "failed: pointer changed");
1377 memset(p2
, 0x11, talloc_get_size(p2
));
1381 /* this should reclaim the memory of p1 */
1382 p2_2
= talloc_realloc_size(pool
, p2
, 800);
1383 torture_assert("pool realloc 800", p2_2
== p1
, "failed: pointer not changed");
1385 memset(p2
, 0x11, talloc_get_size(p2
));
1387 /* this should do a malloc */
1388 p2_2
= talloc_realloc_size(pool
, p2
, 1800);
1389 torture_assert("pool realloc 1800", p2_2
!= p2
, "failed: pointer not changed");
1391 memset(p2
, 0x11, talloc_get_size(p2
));
1393 /* this should reclaim the memory from the pool */
1394 p3
= talloc_size(pool
, 80);
1395 torture_assert("pool alloc 80", p3
== p1
, "failed: pointer changed");
1396 memset(p3
, 0x11, talloc_get_size(p3
));
1401 p1
= talloc_size(pool
, 80);
1402 memset(p1
, 0x11, talloc_get_size(p1
));
1403 p2
= talloc_size(pool
, 20);
1404 memset(p2
, 0x11, talloc_get_size(p2
));
1408 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1409 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1410 memset(p2
, 0x11, talloc_get_size(p2
));
1411 p2_2
= talloc_realloc_size(pool
, p2
, 20-1);
1412 torture_assert("pool realloc 20-1", p2_2
== p2
, "failed: pointer changed");
1413 memset(p2
, 0x11, talloc_get_size(p2
));
1415 /* this should do a malloc */
1416 p2_2
= talloc_realloc_size(pool
, p2
, 1800);
1417 torture_assert("pool realloc 1800", p2_2
!= p2
, "failed: pointer not changed");
1419 memset(p2
, 0x11, talloc_get_size(p2
));
1421 /* this should reclaim the memory from the pool */
1422 p3
= talloc_size(pool
, 800);
1423 torture_assert("pool alloc 800", p3
== p1
, "failed: pointer changed");
1424 memset(p3
, 0x11, talloc_get_size(p3
));
1431 static bool test_pool_steal(void)
1440 root
= talloc_new(NULL
);
1441 pool
= talloc_pool(root
, 1024);
1443 p1
= talloc_size(pool
, 4 * 16);
1444 torture_assert("pool allocate 4 * 16", p1
!= NULL
, "failed ");
1445 memset(p1
, 0x11, talloc_get_size(p1
));
1446 p2
= talloc_size(pool
, 4 * 16);
1447 torture_assert("pool allocate 4 * 16", p2
> p1
, "failed: !(p2 > p1) ");
1448 memset(p2
, 0x11, talloc_get_size(p2
));
1450 ofs1
= PTR_DIFF(p2
, p1
);
1451 hdr
= ofs1
- talloc_get_size(p1
);
1453 talloc_steal(root
, p1
);
1454 talloc_steal(root
, p2
);
1460 p1_2
= talloc_realloc_size(root
, p1
, 5 * 16);
1461 torture_assert("pool realloc 5 * 16", p1_2
> p2
, "failed: pointer not changed");
1462 memset(p1_2
, 0x11, talloc_get_size(p1_2
));
1463 ofs1
= PTR_DIFF(p1_2
, p2
);
1464 ofs2
= talloc_get_size(p2
) + hdr
;
1466 torture_assert("pool realloc ", ofs1
== ofs2
, "failed: pointer offset unexpected");
1468 p2_2
= talloc_realloc_size(root
, p2
, 3 * 16);
1469 torture_assert("pool realloc 5 * 16", p2_2
== p2
, "failed: pointer changed");
1470 memset(p2_2
, 0x11, talloc_get_size(p2_2
));
1476 /* now we should reclaim the full pool */
1477 p2_2
= talloc_realloc_size(root
, p2
, 8 * 16);
1478 torture_assert("pool realloc 8 * 16", p2_2
== p1
, "failed: pointer not expected");
1480 memset(p2_2
, 0x11, talloc_get_size(p2_2
));
1482 /* now we malloc and free the full pool space */
1483 p2_2
= talloc_realloc_size(root
, p2
, 2 * 1024);
1484 torture_assert("pool realloc 2 * 1024", p2_2
!= p1
, "failed: pointer not expected");
1485 memset(p2_2
, 0x11, talloc_get_size(p2_2
));
1494 static bool test_pool_nest(void)
1497 void *e
= talloc_new(NULL
);
1499 p1
= talloc_pool(NULL
, 1024);
1500 torture_assert("talloc_pool", p1
!= NULL
, "failed");
1502 p2
= talloc_pool(p1
, 500);
1503 torture_assert("talloc_pool", p2
!= NULL
, "failed");
1505 p3
= talloc_size(p2
, 10);
1507 talloc_steal(e
, p3
);
1515 talloc_free(e
); /* make ASAN happy */
1526 static bool test_pooled_object(void)
1529 const char *s1
= "hello";
1530 const char *s2
= "world";
1531 const char *s3
= "";
1533 p
= talloc_pooled_object(NULL
, struct pooled
, 3,
1534 strlen(s1
)+strlen(s2
)+strlen(s3
)+3);
1536 if (talloc_get_size(p
) != sizeof(struct pooled
)) {
1540 p
->s1
= talloc_strdup(p
, s1
);
1543 p
->s1
= talloc_strdup(p
, s2
);
1546 p
->s1
= talloc_strdup(p
, s1
);
1547 p
->s2
= talloc_strdup(p
, s2
);
1548 p
->s3
= talloc_strdup(p
, s3
);
1554 static bool test_free_ref_null_context(void)
1559 talloc_disable_null_tracking();
1560 p1
= talloc_new(NULL
);
1561 p2
= talloc_new(NULL
);
1563 p3
= talloc_reference(p2
, p1
);
1564 torture_assert("reference", p3
== p1
, "failed: reference on null");
1566 ret
= talloc_free(p1
);
1567 torture_assert("ref free with null parent", ret
== 0, "failed: free with null parent");
1570 talloc_enable_null_tracking_no_autofree();
1571 p1
= talloc_new(NULL
);
1572 p2
= talloc_new(NULL
);
1574 p3
= talloc_reference(p2
, p1
);
1575 torture_assert("reference", p3
== p1
, "failed: reference on null");
1577 ret
= talloc_free(p1
);
1578 torture_assert("ref free with null tracked parent", ret
== 0, "failed: free with null parent");
1584 static bool test_rusty(void)
1589 talloc_enable_null_tracking();
1590 root
= talloc_new(NULL
);
1591 p1
= talloc_strdup(root
, "foo");
1592 talloc_increase_ref_count(p1
);
1593 talloc_report_full(root
, stdout
);
1595 CHECK_BLOCKS("null_context", NULL
, 2);
1596 talloc_free(p1
); /* make ASAN happy */
1601 static bool test_free_children(void)
1605 const char *name
, *name2
;
1607 talloc_enable_null_tracking();
1608 root
= talloc_new(NULL
);
1609 p1
= talloc_strdup(root
, "foo1");
1610 p2
= talloc_strdup(p1
, "foo2");
1613 talloc_set_name(p1
, "%s", "testname");
1614 talloc_free_children(p1
);
1615 /* check its still a valid talloc ptr */
1616 talloc_get_size(talloc_get_name(p1
));
1617 if (strcmp(talloc_get_name(p1
), "testname") != 0) {
1621 talloc_set_name(p1
, "%s", "testname");
1622 name
= talloc_get_name(p1
);
1623 talloc_free_children(p1
);
1624 /* check its still a valid talloc ptr */
1625 talloc_get_size(talloc_get_name(p1
));
1626 torture_assert("name", name
== talloc_get_name(p1
), "name ptr changed");
1627 torture_assert("namecheck", strcmp(talloc_get_name(p1
), "testname") == 0,
1629 CHECK_BLOCKS("name1", p1
, 2);
1631 /* note that this does not free the old child name */
1632 talloc_set_name_const(p1
, "testname2");
1633 name2
= talloc_get_name(p1
);
1635 talloc_free_children(p1
);
1637 torture_assert("namecheck", strcmp(talloc_get_name(p1
), "testname2") == 0,
1639 CHECK_BLOCKS("name1", p1
, 1);
1641 talloc_report_full(root
, stdout
);
1646 static bool test_memlimit(void)
1649 char *l1
, *l2
, *l3
, *l4
, *l5
, *t
;
1653 printf("test: memlimit\n# MEMORY LIMITS\n");
1655 printf("==== talloc_new(NULL)\n");
1656 root
= talloc_new(NULL
);
1658 talloc_report_full(root
, stdout
);
1660 printf("==== talloc_size(root, 2048)\n");
1661 l1
= talloc_size(root
, 2048);
1662 torture_assert("memlimit", l1
!= NULL
,
1663 "failed: alloc should not fail due to memory limit\n");
1665 talloc_report_full(root
, stdout
);
1667 printf("==== talloc_free(l1)\n");
1670 talloc_report_full(root
, stdout
);
1672 printf("==== talloc_strdup(root, level 1)\n");
1673 l1
= talloc_strdup(root
, "level 1");
1674 torture_assert("memlimit", l1
!= NULL
,
1675 "failed: alloc should not fail due to memory limit\n");
1677 talloc_report_full(root
, stdout
);
1679 printf("==== talloc_set_memlimit(l1, 2048)\n");
1680 torture_assert("memlimit", talloc_set_memlimit(l1
, 2048) == 0,
1681 "failed: setting memlimit should never fail\n");
1683 talloc_report_full(root
, stdout
);
1685 printf("==== talloc_size(root, 2048)\n");
1686 l2
= talloc_size(l1
, 2048);
1687 torture_assert("memlimit", l2
== NULL
,
1688 "failed: alloc should fail due to memory limit\n");
1690 talloc_report_full(root
, stdout
);
1692 printf("==== talloc_strdup(l1, level 2)\n");
1693 l2
= talloc_strdup(l1
, "level 2");
1694 torture_assert("memlimit", l2
!= NULL
,
1695 "failed: alloc should not fail due to memory limit\n");
1697 talloc_report_full(root
, stdout
);
1699 printf("==== talloc_free(l2)\n");
1702 talloc_report_full(root
, stdout
);
1704 printf("==== talloc_size(NULL, 2048)\n");
1705 l2
= talloc_size(NULL
, 2048);
1707 talloc_report_full(root
, stdout
);
1709 printf("==== talloc_steal(l1, l2)\n");
1710 talloc_steal(l1
, l2
);
1712 talloc_report_full(root
, stdout
);
1714 printf("==== talloc_strdup(l2, level 3)\n");
1715 l3
= talloc_strdup(l2
, "level 3");
1716 torture_assert("memlimit", l3
== NULL
,
1717 "failed: alloc should fail due to memory limit\n");
1719 talloc_report_full(root
, stdout
);
1721 printf("==== talloc_free(l2)\n");
1724 talloc_report_full(root
, stdout
);
1726 printf("==== talloc_strdup(NULL, level 2)\n");
1727 l2
= talloc_strdup(NULL
, "level 2");
1728 talloc_steal(l1
, l2
);
1730 talloc_report_full(root
, stdout
);
1732 printf("==== talloc_strdup(l2, level 3)\n");
1733 l3
= talloc_strdup(l2
, "level 3");
1734 torture_assert("memlimit", l3
!= NULL
,
1735 "failed: alloc should not fail due to memory limit\n");
1737 talloc_report_full(root
, stdout
);
1739 printf("==== talloc_set_memlimit(l3, 1024)\n");
1740 torture_assert("memlimit", talloc_set_memlimit(l3
, 1024) == 0,
1741 "failed: setting memlimit should never fail\n");
1743 talloc_report_full(root
, stdout
);
1745 printf("==== talloc_strdup(l3, level 4)\n");
1746 l4
= talloc_strdup(l3
, "level 4");
1747 torture_assert("memlimit", l4
!= NULL
,
1748 "failed: alloc should not fail due to memory limit\n");
1750 talloc_report_full(root
, stdout
);
1752 printf("==== talloc_set_memlimit(l4, 512)\n");
1753 torture_assert("memlimit", talloc_set_memlimit(l4
, 512) == 0,
1754 "failed: setting memlimit should never fail\n");
1756 talloc_report_full(root
, stdout
);
1758 printf("==== talloc_strdup(l4, level 5)\n");
1759 l5
= talloc_strdup(l4
, "level 5");
1760 torture_assert("memlimit", l5
!= NULL
,
1761 "failed: alloc should not fail due to memory limit\n");
1763 talloc_report_full(root
, stdout
);
1765 printf("==== talloc_realloc(NULL, l5, char, 600)\n");
1766 t
= talloc_realloc(NULL
, l5
, char, 600);
1767 torture_assert("memlimit", t
== NULL
,
1768 "failed: alloc should fail due to memory limit\n");
1770 talloc_report_full(root
, stdout
);
1772 printf("==== talloc_realloc(NULL, l5, char, 5)\n");
1773 l5
= talloc_realloc(NULL
, l5
, char, 5);
1774 torture_assert("memlimit", l5
!= NULL
,
1775 "failed: alloc should not fail due to memory limit\n");
1777 talloc_report_full(root
, stdout
);
1779 printf("==== talloc_strdup(l3, level 4)\n");
1780 l4
= talloc_strdup(l3
, "level 4");
1781 torture_assert("memlimit", l4
!= NULL
,
1782 "failed: alloc should not fail due to memory limit\n");
1784 talloc_report_full(root
, stdout
);
1786 printf("==== talloc_set_memlimit(l4, 512)\n");
1787 torture_assert("memlimit", talloc_set_memlimit(l4
, 512) == 0,
1788 "failed: setting memlimit should never fail\n");
1790 talloc_report_full(root
, stdout
);
1792 printf("==== talloc_strdup(l4, level 5)\n");
1793 l5
= talloc_strdup(l4
, "level 5");
1794 torture_assert("memlimit", l5
!= NULL
,
1795 "failed: alloc should not fail due to memory limit\n");
1797 talloc_report_full(root
, stdout
);
1799 printf("==== Make new temp context and steal l5\n");
1800 t
= talloc_new(root
);
1801 talloc_steal(t
, l5
);
1803 talloc_report_full(root
, stdout
);
1805 printf("==== talloc_size(t, 2048)\n");
1806 l1
= talloc_size(t
, 2048);
1807 torture_assert("memlimit", l1
!= NULL
,
1808 "failed: alloc should not fail due to memory limit\n");
1810 talloc_report_full(root
, stdout
);
1813 /* Test memlimits with pools. */
1814 printf("==== talloc_pool(NULL, 10*1024)\n");
1815 pool
= talloc_pool(NULL
, 10*1024);
1816 torture_assert("memlimit", pool
!= NULL
,
1817 "failed: alloc should not fail due to memory limit\n");
1819 printf("==== talloc_set_memlimit(pool, 10*1024)\n");
1820 talloc_set_memlimit(pool
, 10*1024);
1821 for (i
= 0; i
< 9; i
++) {
1822 printf("==== talloc_size(pool, 1024) %i/10\n", i
+ 1);
1823 l1
= talloc_size(pool
, 1024);
1824 torture_assert("memlimit", l1
!= NULL
,
1825 "failed: alloc should not fail due to memory limit\n");
1826 talloc_report_full(pool
, stdout
);
1828 /* The next alloc should fail. */
1829 printf("==== talloc_size(pool, 1024) 10/10\n");
1830 l2
= talloc_size(pool
, 1024);
1831 torture_assert("memlimit", l2
== NULL
,
1832 "failed: alloc should fail due to memory limit\n");
1834 talloc_report_full(pool
, stdout
);
1836 /* Moving one of the children shouldn't change the limit,
1837 as it's still inside the pool. */
1839 printf("==== talloc_new(NULL)\n");
1840 root
= talloc_new(NULL
);
1842 printf("==== talloc_steal(root, l1)\n");
1843 talloc_steal(root
, l1
);
1845 printf("==== talloc_size(pool, 1024)\n");
1846 l2
= talloc_size(pool
, 1024);
1847 torture_assert("memlimit", l2
== NULL
,
1848 "failed: alloc should fail due to memory limit\n");
1850 printf("==== talloc_free_children(pool)\n");
1852 talloc_free_children(pool
);
1854 printf("==== talloc_size(pool, 1024)\n");
1855 l1
= talloc_size(pool
, 1024);
1857 /* try reallocs of increasing size */
1858 for (i
= 1; i
< 9; i
++) {
1859 printf("==== talloc_realloc_size(NULL, l1, %i*1024) %i/10\n", i
, i
+ 1);
1860 l1
= talloc_realloc_size(NULL
, l1
, i
*1024);
1861 torture_assert("memlimit", l1
!= NULL
,
1862 "failed: realloc should not fail due to memory limit\n");
1863 talloc_report_full(pool
, stdout
);
1865 /* The next alloc should fail. */
1866 printf("==== talloc_realloc_size(NULL, l1, 10*1024) 10/10\n");
1867 l2
= talloc_realloc_size(NULL
, l1
, 10*1024);
1868 torture_assert("memlimit", l2
== NULL
,
1869 "failed: realloc should fail due to memory limit\n");
1871 /* Increase the memlimit */
1872 printf("==== talloc_set_memlimit(pool, 11*1024)\n");
1873 talloc_set_memlimit(pool
, 11*1024);
1875 /* The final realloc should still fail
1876 as the entire realloced chunk needs to be moved out of the pool */
1877 printf("==== talloc_realloc_size(NULL, l1, 10*1024) 10/10\n");
1878 l2
= talloc_realloc_size(NULL
, l1
, 10*1024);
1879 torture_assert("memlimit", l2
== NULL
,
1880 "failed: realloc should fail due to memory limit\n");
1882 talloc_report_full(pool
, stdout
);
1884 printf("==== talloc_set_memlimit(pool, 21*1024)\n");
1885 talloc_set_memlimit(pool
, 21*1024);
1887 /* There's now sufficient space to move the chunk out of the pool */
1888 printf("==== talloc_realloc_size(NULL, l1, 10*1024) 10/10\n");
1889 l2
= talloc_realloc_size(NULL
, l1
, 10*1024);
1890 torture_assert("memlimit", l2
!= NULL
,
1891 "failed: realloc should not fail due to memory limit\n");
1893 talloc_report_full(pool
, stdout
);
1895 /* ...which should mean smaller allocations can now occur within the pool */
1896 printf("==== talloc_size(pool, 9*1024)\n");
1897 l1
= talloc_size(pool
, 9*1024);
1898 torture_assert("memlimit", l1
!= NULL
,
1899 "failed: new allocations should be allowed in the pool\n");
1901 talloc_report_full(pool
, stdout
);
1903 /* But reallocs bigger than the pool will still fail */
1904 printf("==== talloc_realloc_size(NULL, l1, 10*1024)\n");
1905 l2
= talloc_realloc_size(NULL
, l1
, 10*1024);
1906 torture_assert("memlimit", l2
== NULL
,
1907 "failed: realloc should fail due to memory limit\n");
1909 talloc_report_full(pool
, stdout
);
1911 /* ..as well as allocs */
1912 printf("==== talloc_size(pool, 1024)\n");
1913 l1
= talloc_size(pool
, 1024);
1914 torture_assert("memlimit", l1
== NULL
,
1915 "failed: alloc should fail due to memory limit\n");
1917 talloc_report_full(pool
, stdout
);
1919 printf("==== talloc_free_children(pool)\n");
1920 talloc_free_children(pool
);
1922 printf("==== talloc_set_memlimit(pool, 1024)\n");
1923 talloc_set_memlimit(pool
, 1024);
1925 /* We should still be able to allocate up to the pool limit
1926 because the memlimit only applies to new heap allocations */
1927 printf("==== talloc_size(pool, 9*1024)\n");
1928 l1
= talloc_size(pool
, 9*1024);
1929 torture_assert("memlimit", l1
!= NULL
,
1930 "failed: alloc should not fail due to memory limit\n");
1932 talloc_report_full(pool
, stdout
);
1934 l1
= talloc_size(pool
, 1024);
1935 torture_assert("memlimit", l1
== NULL
,
1936 "failed: alloc should fail due to memory limit\n");
1938 talloc_report_full(pool
, stdout
);
1940 printf("==== talloc_free_children(pool)\n");
1941 talloc_free_children(pool
);
1943 printf("==== talloc_set_memlimit(pool, 10*1024)\n");
1944 talloc_set_memlimit(pool
, 10*1024);
1946 printf("==== talloc_size(pool, 1024)\n");
1947 l1
= talloc_size(pool
, 1024);
1948 torture_assert("memlimit", l1
!= NULL
,
1949 "failed: alloc should not fail due to memory limit\n");
1951 talloc_report_full(pool
, stdout
);
1955 printf("success: memlimit\n");
1962 #define NUM_THREADS 100
1964 /* Sync variables. */
1965 static pthread_mutex_t mtx
= PTHREAD_MUTEX_INITIALIZER
;
1966 static pthread_cond_t condvar
= PTHREAD_COND_INITIALIZER
;
1967 static void *intermediate_ptr
;
1970 static void *thread_fn(void *arg
)
1973 const char *ctx_name
= (const char *)arg
;
1974 void *sub_ctx
= NULL
;
1976 * Do stuff that creates a new talloc hierarchy in
1979 void *top_ctx
= talloc_named_const(NULL
, 0, "top");
1980 if (top_ctx
== NULL
) {
1983 sub_ctx
= talloc_named_const(top_ctx
, 100, ctx_name
);
1984 if (sub_ctx
== NULL
) {
1989 * Now transfer a pointer from our hierarchy
1990 * onto the intermediate ptr.
1992 ret
= pthread_mutex_lock(&mtx
);
1994 talloc_free(top_ctx
);
1997 /* Wait for intermediate_ptr to be free. */
1998 while (intermediate_ptr
!= NULL
) {
1999 ret
= pthread_cond_wait(&condvar
, &mtx
);
2001 talloc_free(top_ctx
);
2002 ret
= pthread_mutex_unlock(&mtx
);
2008 /* and move our memory onto it from our toplevel hierarchy. */
2009 intermediate_ptr
= talloc_move(NULL
, &sub_ctx
);
2011 /* Tell the main thread it's ready for pickup. */
2012 pthread_cond_broadcast(&condvar
);
2013 ret
= pthread_mutex_unlock(&mtx
);
2016 talloc_free(top_ctx
);
2021 static bool test_pthread_talloc_passing(void)
2025 char str_array
[NUM_THREADS
][20];
2026 pthread_t thread_id
;
2030 * Important ! Null tracking breaks threaded talloc.
2031 * It *must* be turned off.
2033 talloc_disable_null_tracking();
2035 printf("test: pthread_talloc_passing\n# PTHREAD TALLOC PASSING\n");
2037 /* Main thread toplevel context. */
2038 mem_ctx
= talloc_named_const(NULL
, 0, "toplevel");
2039 if (mem_ctx
== NULL
) {
2040 printf("failed to create toplevel context\n");
2045 * Spin off NUM_THREADS threads.
2046 * They will use their own toplevel contexts.
2048 for (i
= 0; i
< NUM_THREADS
; i
++) {
2049 ret
= snprintf(str_array
[i
],
2054 printf("snprintf %d failed\n", i
);
2057 ret
= pthread_create(&thread_id
,
2062 printf("failed to create thread %d (%d)\n", i
, ret
);
2067 printf("Created %d threads\n", NUM_THREADS
);
2069 /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */
2070 for (i
= 0; i
< NUM_THREADS
; i
++) {
2071 ret
= pthread_mutex_lock(&mtx
);
2073 printf("pthread_mutex_lock %d failed (%d)\n", i
, ret
);
2074 talloc_free(mem_ctx
);
2078 /* Wait for intermediate_ptr to have our data. */
2079 while (intermediate_ptr
== NULL
) {
2080 ret
= pthread_cond_wait(&condvar
, &mtx
);
2082 printf("pthread_cond_wait %d failed (%d)\n", i
,
2084 talloc_free(mem_ctx
);
2085 ret
= pthread_mutex_unlock(&mtx
);
2090 /* and move it onto our toplevel hierarchy. */
2091 (void)talloc_move(mem_ctx
, &intermediate_ptr
);
2093 /* Tell the sub-threads we're ready for another. */
2094 pthread_cond_broadcast(&condvar
);
2095 ret
= pthread_mutex_unlock(&mtx
);
2099 CHECK_SIZE("pthread_talloc_passing", mem_ctx
, NUM_THREADS
* 100);
2101 /* Dump the hierarchy. */
2102 talloc_report(mem_ctx
, stdout
);
2104 talloc_free(mem_ctx
);
2105 printf("success: pthread_talloc_passing\n");
2110 static void test_magic_protection_abort(const char *reason
)
2112 /* exit with errcode 42 to communicate successful test to the parent process */
2113 if (strcmp(reason
, "Bad talloc magic value - unknown value") == 0) {
2116 printf("talloc aborted for an unexpected reason\n");
2120 static int test_magic_protection_destructor(int *ptr
)
2122 _exit(404); /* Not 42 */
2125 static bool test_magic_protection(void)
2127 void *pool
= talloc_pool(NULL
, 1024);
2132 printf("test: magic_protection\n");
2133 p1
= talloc(pool
, int);
2134 p2
= talloc(pool
, int);
2136 /* To avoid complaints from the compiler assign values to the p1 & p2. */
2142 talloc_set_abort_fn(test_magic_protection_abort
);
2143 talloc_set_destructor(p2
, test_magic_protection_destructor
);
2146 * Simulate a security attack
2147 * by triggering a buffer overflow in memset to overwrite the
2148 * constructor in the next pool chunk.
2150 * Real attacks would attempt to set a real destructor.
2152 memset_s(p1
, 32, '\0', 32);
2154 /* Then the attack takes effect when the memory's freed. */
2157 /* Never reached. Make compilers happy */
2161 while (wait(&exit_status
) != pid
);
2163 talloc_free(pool
); /* make ASAN happy */
2165 if (!WIFEXITED(exit_status
)) {
2166 printf("Child exited through unexpected abnormal means\n");
2169 if (WEXITSTATUS(exit_status
) != 42) {
2170 printf("Child exited with wrong exit status\n");
2173 if (WIFSIGNALED(exit_status
)) {
2174 printf("Child received unexpected signal\n");
2178 printf("success: magic_protection\n");
2182 static void test_magic_free_protection_abort(const char *reason
)
2184 /* exit with errcode 42 to communicate successful test to the parent process */
2185 if (strcmp(reason
, "Bad talloc magic value - access after free") == 0) {
2192 static bool test_magic_free_protection(void)
2194 void *pool
= talloc_pool(NULL
, 1024);
2199 printf("test: magic_free_protection\n");
2200 p1
= talloc(pool
, int);
2201 p2
= talloc(pool
, int);
2203 /* To avoid complaints from the compiler assign values to the p1 & p2. */
2207 p3
= talloc_realloc(pool
, p2
, int, 2048);
2208 torture_assert("pool realloc 2048",
2210 "failed: pointer not changed");
2213 * Now access the memory in the pool after the realloc(). It
2214 * should be marked as free, so use of the old pointer should
2215 * trigger the abort function
2219 talloc_set_abort_fn(test_magic_free_protection_abort
);
2221 talloc_get_name(p2
);
2223 /* Never reached. Make compilers happy */
2227 while (wait(&exit_status
) != pid
);
2229 if (!WIFEXITED(exit_status
)) {
2230 printf("Child exited through unexpected abnormal means\n");
2233 if (WEXITSTATUS(exit_status
) != 42) {
2234 printf("Child exited with wrong exit status\n");
2237 if (WIFSIGNALED(exit_status
)) {
2238 printf("Child received unexpected signal\n");
2244 printf("success: magic_free_protection\n");
2248 static void test_reset(void)
2250 talloc_set_log_fn(test_log_stdout
);
2252 talloc_disable_null_tracking();
2253 talloc_enable_null_tracking_no_autofree();
2256 bool torture_local_talloc(struct torture_context
*tctx
)
2263 ret
&= test_pooled_object();
2265 ret
&= test_pool_nest();
2275 ret
&= test_unlink1();
2279 ret
&= test_realloc();
2281 ret
&= test_realloc_child();
2283 ret
&= test_steal();
2287 ret
&= test_unref_reparent();
2289 ret
&= test_realloc_fn();
2293 ret
&= test_lifeless();
2297 ret
&= test_free_parent_deny_child();
2299 ret
&= test_realloc_on_destructor_parent();
2301 ret
&= test_free_parent_reparent_child();
2303 ret
&= test_free_parent_reparent_child_in_pool();
2305 ret
&= test_talloc_ptrtype();
2307 ret
&= test_talloc_free_in_destructor();
2311 ret
&= test_pool_steal();
2313 ret
&= test_free_ref_null_context();
2315 ret
&= test_rusty();
2317 ret
&= test_free_children();
2319 ret
&= test_memlimit();
2322 ret
&= test_pthread_talloc_passing();
2328 ret
&= test_speed();
2331 ret
&= test_autofree();
2333 ret
&= test_magic_protection();
2335 ret
&= test_magic_free_protection();
2338 talloc_disable_null_tracking();