libcli: Fix a signed/unsigned comparison warning
[samba4-gss.git] / lib / talloc / testsuite.c
blobdc0039940fff913dac88a62856a23eee066f351a
1 /*
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
10 ** under the LGPL
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/>.
26 #include "replace.h"
27 #include "system/time.h"
28 #include <talloc.h>
30 #ifdef HAVE_PTHREAD
31 #include <pthread.h>
32 #endif
34 #include <unistd.h>
35 #include <sys/wait.h>
37 #ifdef NDEBUG
38 #undef NDEBUG
39 #endif
41 #include <assert.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
50 #endif
51 #endif /* disable_optimization */
53 static struct timeval private_timeval_current(void)
55 struct timeval tv;
56 gettimeofday(&tv, NULL);
57 return tv;
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); \
70 return false; \
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) { \
76 return false; \
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); \
80 return false; \
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), \
88 (unsigned)tsize); \
89 talloc_report_full(ptr, stdout); \
90 return false; \
91 } \
92 } while (0)
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), \
99 (unsigned)tblocks); \
100 talloc_report_full(ptr, stdout); \
101 return false; \
103 } while (0)
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), \
110 (parent)); \
111 talloc_report_full(ptr, stdout); \
112 talloc_report_full(parent, stdout); \
113 talloc_report_full(NULL, stdout); \
114 return false; \
116 } while (0)
118 static unsigned int test_abort_count;
120 #if 0
121 static void test_abort_fn(const char *reason)
123 printf("# test_abort_fn(%s)\n", reason);
124 test_abort_count++;
127 static void test_abort_start(void)
129 test_abort_count = 0;
130 talloc_set_abort_fn(test_abort_fn);
132 #endif
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);
146 test references
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");
179 talloc_free(p1);
180 talloc_report_full(root, stderr);
182 CHECK_BLOCKS("ref1", r1, 1);
184 fprintf(stderr, "Freeing r1\n");
185 talloc_free(r1);
186 talloc_report_full(NULL, stderr);
188 fprintf(stderr, "Testing NULL\n");
189 if (talloc_reference(root, NULL)) {
190 return false;
193 CHECK_BLOCKS("ref1", root, 1);
195 CHECK_SIZE("ref1", root, 0);
197 talloc_free(root);
198 printf("success: ref1\n");
199 return true;
203 test references
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");
234 talloc_free(p2);
235 talloc_report_full(root, stderr);
237 CHECK_BLOCKS("ref2", p1, 4);
238 CHECK_BLOCKS("ref2", r1, 1);
240 fprintf(stderr, "Freeing p1\n");
241 talloc_free(p1);
242 talloc_report_full(root, stderr);
244 CHECK_BLOCKS("ref2", r1, 1);
246 fprintf(stderr, "Freeing r1\n");
247 talloc_free(r1);
248 talloc_report_full(root, stderr);
250 CHECK_SIZE("ref2", root, 0);
252 talloc_free(root);
253 printf("success: ref2\n");
254 return true;
258 test references
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");
279 talloc_free(p1);
280 talloc_report_full(root, stderr);
282 CHECK_BLOCKS("ref3", p2, 2);
283 CHECK_BLOCKS("ref3", r1, 1);
285 fprintf(stderr, "Freeing p2\n");
286 talloc_free(p2);
287 talloc_report_full(root, stderr);
289 CHECK_SIZE("ref3", root, 0);
291 talloc_free(root);
293 printf("success: ref3\n");
294 return true;
298 test references
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");
323 talloc_free(r1);
324 talloc_report_full(root, stderr);
326 CHECK_BLOCKS("ref4", p1, 5);
327 CHECK_BLOCKS("ref4", p2, 1);
329 fprintf(stderr, "Freeing p2\n");
330 talloc_free(p2);
331 talloc_report_full(root, stderr);
333 CHECK_BLOCKS("ref4", p1, 4);
335 fprintf(stderr, "Freeing p1\n");
336 talloc_free(p1);
337 talloc_report_full(root, stderr);
339 CHECK_SIZE("ref4", root, 0);
341 talloc_free(root);
343 printf("success: ref4\n");
344 return true;
349 test references
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");
382 talloc_free(p1);
383 talloc_report_full(root, stderr);
385 CHECK_SIZE("unlink", root, 0);
387 talloc_free(root);
389 printf("success: unlink\n");
390 return true;
393 static int fail_destructor(void *ptr)
395 return -1;
399 miscellaneous tests to try to get a higher test coverage percentage
401 static bool test_misc(void)
403 void *root, *p1;
404 char *p2;
405 double *d;
406 const char *name;
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");
463 talloc_free(p2);
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);
482 talloc_free(p2);
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");
490 talloc_free(p1);
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);
541 talloc_free(root);
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");
551 return true;
556 test realloc
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);
572 talloc_new(p1);
574 p2 = talloc_realloc_size(p1, NULL, 30);
576 talloc_new(p1);
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);
608 talloc_free(root);
610 printf("success: realloc\n");
612 return true;
616 test realloc with a child
618 static bool test_realloc_child(void)
620 void *root;
621 struct el2 {
622 const char *name;
623 } *el2, *el2_2, *el2_3, **el_list_save;
624 struct el1 {
625 int count;
626 struct el2 **list, **list2, **list3;
627 } *el1;
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");
657 return false;
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);
676 talloc_free(root);
678 printf("success: REALLOC WITH CHILD\n");
679 return true;
683 test type checking
685 static bool test_type(void)
687 void *root;
688 struct el1 {
689 int count;
691 struct el2 {
692 int count;
694 struct el1 *el1;
696 printf("test: type\n# talloc type checking\n");
698 root = talloc_new(NULL);
700 el1 = talloc(root, struct el1);
702 el1->count = 1;
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");
712 talloc_free(root);
714 printf("success: type\n");
715 return true;
719 test steal
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);
749 talloc_free(p1);
750 talloc_steal(root, p2);
751 CHECK_BLOCKS("steal", root, 2);
752 CHECK_SIZE("steal", root, 20);
754 talloc_free(p2);
756 CHECK_BLOCKS("steal", root, 1);
757 CHECK_SIZE("steal", root, 0);
759 talloc_free(root);
761 p1 = talloc_size(NULL, 3);
762 talloc_report_full(NULL, stderr);
763 CHECK_SIZE("steal", NULL, 3);
764 talloc_free(p1);
766 printf("success: steal\n");
767 return true;
771 test move
773 static bool test_move(void)
775 void *root;
776 struct t_move {
777 char *p;
778 int *x;
779 } *t1, *t2;
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);
789 *t1->x = 42;
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");
797 talloc_free(root);
799 printf("success: move\n");
801 return true;
805 test talloc_realloc_fn
807 static bool test_realloc_fn(void)
809 void *root, *p1;
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);
825 talloc_free(root);
827 printf("success: realloc_fn\n");
828 return true;
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);
847 talloc_free(p1);
849 CHECK_PARENT("unref_reparent", c1, p2);
851 talloc_unlink(p2, c1);
853 CHECK_SIZE("unref_reparent", root, 1);
855 talloc_free(p2);
856 talloc_free(root);
858 printf("success: unref_reparent\n");
859 return true;
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);
873 unsigned count;
874 const int loop = 1000;
875 int i;
876 struct timeval tv;
878 printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
880 tv = private_timeval_current();
881 count = 0;
882 do {
883 void *p1, *p2, *p3;
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);
888 (void)p2;
889 (void)p3;
890 talloc_free(p1);
892 count += 3 * loop;
893 } while (private_timeval_elapsed(&tv) < 5.0);
895 fprintf(stderr, "talloc:\t\t%.0f ops/sec\n", count/private_timeval_elapsed(&tv));
897 talloc_free(ctx);
899 ctx = talloc_pool(NULL, ALLOC_SIZE * 2);
901 tv = private_timeval_current();
902 count = 0;
903 do {
904 void *p1, *p2, *p3;
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);
909 (void)p2;
910 (void)p3;
911 talloc_free(p1);
913 count += 3 * loop;
914 } while (private_timeval_elapsed(&tv) < 5.0);
916 talloc_free(ctx);
918 fprintf(stderr, "talloc_pool:\t%.0f ops/sec\n", count/private_timeval_elapsed(&tv));
920 tv = private_timeval_current();
921 count = 0;
922 do {
923 void *p1, *p2, *p3;
924 for (i=0;i<loop;i++) {
925 p1 = malloc(loop % ALLOC_SIZE);
926 p2 = strdup(ALLOC_DUP_STRING);
927 p3 = malloc(ALLOC_SIZE);
928 free(p1);
929 free(p2);
930 free(p3);
932 count += 3 * loop;
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();
941 count = 0;
942 do {
943 void *p1, *p2, *p3;
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);
948 (void)p2;
949 (void)p3;
950 talloc_free(p1);
952 count += 3 * loop;
953 } while (private_timeval_elapsed(&tv) < 5.0);
955 fprintf(stderr, "talloc_zero:\t%.0f ops/sec\n", count/private_timeval_elapsed(&tv));
957 talloc_free(ctx);
959 tv = private_timeval_current();
960 count = 0;
961 do {
962 void *p1, *p2, *p3;
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);
967 free(p1);
968 free(p2);
969 free(p3);
971 count += 3 * loop;
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");
977 return true;
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);
996 talloc_free(top);
997 talloc_free(child_owner);
998 talloc_free(child);
1000 printf("success: lifeless\n");
1001 return true;
1004 static int loop_destructor_count;
1006 static int test_loop_destructor(char *ptr)
1008 loop_destructor_count++;
1009 return 0;
1012 static bool test_loop(void)
1014 void *top = talloc_new(NULL);
1015 char *parent;
1016 struct req1 {
1017 char *req2, *req3;
1018 } *req1;
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);
1032 talloc_free(top);
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");
1039 return true;
1042 static int realloc_parent_destructor_count;
1044 static int test_realloc_parent_destructor(char *ptr)
1046 realloc_parent_destructor_count++;
1047 return 0;
1050 static bool test_realloc_on_destructor_parent(void)
1052 void *top = talloc_new(NULL);
1053 char *parent;
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
1068 * -> c
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
1078 * -> C
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 */
1092 return true;
1095 static int fail_destructor_str(char *ptr)
1097 return -1;
1100 static bool test_free_parent_deny_child(void)
1102 void *top = talloc_new(NULL);
1103 char *level1;
1104 char *level2;
1105 char *level3;
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);
1119 talloc_free(top);
1121 printf("success: free_parent_deny_child\n");
1122 return true;
1125 struct new_parent {
1126 void *new_parent;
1127 char val[20];
1130 static int reparenting_destructor(struct new_parent *np)
1132 talloc_set_destructor(np, NULL);
1133 (void)talloc_move(np->new_parent, &np);
1134 return -1;
1137 static bool test_free_parent_reparent_child(void)
1139 void *top = talloc_new(NULL);
1140 char *level1;
1141 char *alternate_level1;
1142 char *level2;
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);
1161 talloc_free(top);
1163 printf("success: free_parent_reparent_child\n");
1164 return true;
1167 static bool test_free_parent_reparent_child_in_pool(void)
1169 void *top = talloc_new(NULL);
1170 char *level1;
1171 char *alternate_level1;
1172 char *level2;
1173 void *pool;
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);
1196 talloc_free(top);
1198 printf("success: free_parent_reparent_child_in_pool\n");
1199 return true;
1203 static bool test_talloc_ptrtype(void)
1205 void *top = talloc_new(NULL);
1206 struct struct1 {
1207 int foo;
1208 int bar;
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));
1224 return false;
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);
1231 return false;
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));
1242 return false;
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);
1249 return false;
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));
1260 return false;
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));
1274 return false;
1277 torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
1278 "talloc_array_ptrtype() sets the wrong name");
1280 talloc_free(top);
1282 printf("success: ptrtype\n");
1283 return true;
1286 static int _test_talloc_free_in_destructor(void **ptr)
1288 talloc_free(*ptr);
1289 return 0;
1292 static bool test_talloc_free_in_destructor(void)
1294 void *level0;
1295 void *level1;
1296 void *level2;
1297 void *level3;
1298 void *level4;
1299 void **level5;
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 *);
1310 *level5 = level3;
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");
1324 return true;
1327 static bool test_autofree(void)
1329 #if _SAMBA_BUILD_ < 4
1330 /* autofree test would kill smbtorture */
1331 void *p;
1332 printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1334 p = talloc_autofree_context();
1335 talloc_free(p);
1337 p = talloc_autofree_context();
1338 talloc_free(p);
1340 printf("success: autofree\n");
1341 #endif
1342 return true;
1345 static bool test_pool(void)
1347 void *pool;
1348 void *p1, *p2, *p3, *p4;
1349 void *p2_2;
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));
1372 talloc_free(p3);
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));
1379 talloc_free(p1);
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");
1384 p2 = p2_2;
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");
1390 p2 = p2_2;
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));
1398 talloc_free(p2);
1399 talloc_free(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));
1406 talloc_free(p1);
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");
1418 p2 = p2_2;
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));
1426 talloc_free(pool);
1428 return true;
1431 static bool test_pool_steal(void)
1433 void *root;
1434 void *pool;
1435 void *p1, *p2;
1436 void *p1_2, *p2_2;
1437 size_t hdr;
1438 size_t ofs1, ofs2;
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);
1456 talloc_free(pool);
1458 p1_2 = p1;
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));
1472 talloc_free(p1_2);
1474 p2_2 = p2;
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");
1479 p2 = p2_2;
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));
1487 talloc_free(p2_2);
1489 talloc_free(root);
1491 return true;
1494 static bool test_pool_nest(void)
1496 void *p1, *p2, *p3;
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);
1509 talloc_free(p2);
1511 talloc_free(p3);
1513 talloc_free(p1);
1515 talloc_free(e); /* make ASAN happy */
1517 return true;
1520 struct pooled {
1521 char *s1;
1522 char *s2;
1523 char *s3;
1526 static bool test_pooled_object(void)
1528 struct pooled *p;
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)) {
1537 return false;
1540 p->s1 = talloc_strdup(p, s1);
1542 TALLOC_FREE(p->s1);
1543 p->s1 = talloc_strdup(p, s2);
1544 TALLOC_FREE(p->s1);
1546 p->s1 = talloc_strdup(p, s1);
1547 p->s2 = talloc_strdup(p, s2);
1548 p->s3 = talloc_strdup(p, s3);
1550 TALLOC_FREE(p);
1551 return true;
1554 static bool test_free_ref_null_context(void)
1556 void *p1, *p2, *p3;
1557 int ret;
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");
1568 talloc_free(p2);
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");
1579 talloc_free(p2);
1581 return true;
1584 static bool test_rusty(void)
1586 void *root;
1587 char *p1;
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);
1594 talloc_free(root);
1595 CHECK_BLOCKS("null_context", NULL, 2);
1596 talloc_free(p1); /* make ASAN happy */
1598 return true;
1601 static bool test_free_children(void)
1603 void *root;
1604 char *p1, *p2;
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");
1611 (void)p2;
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) {
1618 return false;
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,
1628 "wrong name");
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);
1634 /* but this does */
1635 talloc_free_children(p1);
1636 (void)name2;
1637 torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname2") == 0,
1638 "wrong name");
1639 CHECK_BLOCKS("name1", p1, 1);
1641 talloc_report_full(root, stdout);
1642 talloc_free(root);
1643 return true;
1646 static bool test_memlimit(void)
1648 void *root;
1649 char *l1, *l2, *l3, *l4, *l5, *t;
1650 char *pool;
1651 int i;
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");
1668 talloc_free(l1);
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");
1700 talloc_free(l2);
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");
1722 talloc_free(l2);
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);
1811 talloc_free(root);
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");
1851 talloc_free(l1);
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);
1953 talloc_free(pool);
1954 talloc_free(root);
1955 printf("success: memlimit\n");
1957 return true;
1960 #ifdef HAVE_PTHREAD
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;
1969 /* Subthread. */
1970 static void *thread_fn(void *arg)
1972 int ret;
1973 const char *ctx_name = (const char *)arg;
1974 void *sub_ctx = NULL;
1976 * Do stuff that creates a new talloc hierarchy in
1977 * this thread.
1979 void *top_ctx = talloc_named_const(NULL, 0, "top");
1980 if (top_ctx == NULL) {
1981 return NULL;
1983 sub_ctx = talloc_named_const(top_ctx, 100, ctx_name);
1984 if (sub_ctx == NULL) {
1985 return NULL;
1989 * Now transfer a pointer from our hierarchy
1990 * onto the intermediate ptr.
1992 ret = pthread_mutex_lock(&mtx);
1993 if (ret != 0) {
1994 talloc_free(top_ctx);
1995 return NULL;
1997 /* Wait for intermediate_ptr to be free. */
1998 while (intermediate_ptr != NULL) {
1999 ret = pthread_cond_wait(&condvar, &mtx);
2000 if (ret != 0) {
2001 talloc_free(top_ctx);
2002 ret = pthread_mutex_unlock(&mtx);
2003 assert(ret == 0);
2004 return NULL;
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);
2014 assert(ret == 0);
2016 talloc_free(top_ctx);
2017 return NULL;
2020 /* Main thread. */
2021 static bool test_pthread_talloc_passing(void)
2023 int i;
2024 int ret;
2025 char str_array[NUM_THREADS][20];
2026 pthread_t thread_id;
2027 void *mem_ctx;
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");
2041 return false;
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],
2051 "thread:%d",
2053 if (ret < 0) {
2054 printf("snprintf %d failed\n", i);
2055 return false;
2057 ret = pthread_create(&thread_id,
2058 NULL,
2059 thread_fn,
2060 str_array[i]);
2061 if (ret != 0) {
2062 printf("failed to create thread %d (%d)\n", i, ret);
2063 return false;
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);
2072 if (ret != 0) {
2073 printf("pthread_mutex_lock %d failed (%d)\n", i, ret);
2074 talloc_free(mem_ctx);
2075 return false;
2078 /* Wait for intermediate_ptr to have our data. */
2079 while (intermediate_ptr == NULL) {
2080 ret = pthread_cond_wait(&condvar, &mtx);
2081 if (ret != 0) {
2082 printf("pthread_cond_wait %d failed (%d)\n", i,
2083 ret);
2084 talloc_free(mem_ctx);
2085 ret = pthread_mutex_unlock(&mtx);
2086 assert(ret == 0);
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);
2096 assert(ret == 0);
2099 CHECK_SIZE("pthread_talloc_passing", mem_ctx, NUM_THREADS * 100);
2100 #if 1
2101 /* Dump the hierarchy. */
2102 talloc_report(mem_ctx, stdout);
2103 #endif
2104 talloc_free(mem_ctx);
2105 printf("success: pthread_talloc_passing\n");
2106 return true;
2108 #endif
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) {
2114 _exit(42);
2115 } else {
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);
2128 int *p1, *p2;
2129 pid_t pid;
2130 int exit_status;
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. */
2137 *p1 = 6;
2138 *p2 = 9;
2140 pid = fork();
2141 if (pid == 0) {
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. */
2155 talloc_free(pool);
2157 /* Never reached. Make compilers happy */
2158 return true;
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");
2167 return false;
2169 if (WEXITSTATUS(exit_status) != 42) {
2170 printf("Child exited with wrong exit status\n");
2171 return false;
2173 if (WIFSIGNALED(exit_status)) {
2174 printf("Child received unexpected signal\n");
2175 return false;
2178 printf("success: magic_protection\n");
2179 return true;
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) {
2186 _exit(42);
2188 /* not 42 */
2189 _exit(404);
2192 static bool test_magic_free_protection(void)
2194 void *pool = talloc_pool(NULL, 1024);
2195 int *p1, *p2, *p3;
2196 pid_t pid;
2197 int exit_status;
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. */
2204 *p1 = 6;
2205 *p2 = 9;
2207 p3 = talloc_realloc(pool, p2, int, 2048);
2208 torture_assert("pool realloc 2048",
2209 p3 != p2,
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
2217 pid = fork();
2218 if (pid == 0) {
2219 talloc_set_abort_fn(test_magic_free_protection_abort);
2221 talloc_get_name(p2);
2223 /* Never reached. Make compilers happy */
2224 return true;
2227 while (wait(&exit_status) != pid);
2229 if (!WIFEXITED(exit_status)) {
2230 printf("Child exited through unexpected abnormal means\n");
2231 return false;
2233 if (WEXITSTATUS(exit_status) != 42) {
2234 printf("Child exited with wrong exit status\n");
2235 return false;
2237 if (WIFSIGNALED(exit_status)) {
2238 printf("Child received unexpected signal\n");
2239 return false;
2242 talloc_free(pool);
2244 printf("success: magic_free_protection\n");
2245 return true;
2248 static void test_reset(void)
2250 talloc_set_log_fn(test_log_stdout);
2251 test_abort_stop();
2252 talloc_disable_null_tracking();
2253 talloc_enable_null_tracking_no_autofree();
2256 bool torture_local_talloc(struct torture_context *tctx)
2258 bool ret = true;
2260 setlinebuf(stdout);
2262 test_reset();
2263 ret &= test_pooled_object();
2264 test_reset();
2265 ret &= test_pool_nest();
2266 test_reset();
2267 ret &= test_ref1();
2268 test_reset();
2269 ret &= test_ref2();
2270 test_reset();
2271 ret &= test_ref3();
2272 test_reset();
2273 ret &= test_ref4();
2274 test_reset();
2275 ret &= test_unlink1();
2276 test_reset();
2277 ret &= test_misc();
2278 test_reset();
2279 ret &= test_realloc();
2280 test_reset();
2281 ret &= test_realloc_child();
2282 test_reset();
2283 ret &= test_steal();
2284 test_reset();
2285 ret &= test_move();
2286 test_reset();
2287 ret &= test_unref_reparent();
2288 test_reset();
2289 ret &= test_realloc_fn();
2290 test_reset();
2291 ret &= test_type();
2292 test_reset();
2293 ret &= test_lifeless();
2294 test_reset();
2295 ret &= test_loop();
2296 test_reset();
2297 ret &= test_free_parent_deny_child();
2298 test_reset();
2299 ret &= test_realloc_on_destructor_parent();
2300 test_reset();
2301 ret &= test_free_parent_reparent_child();
2302 test_reset();
2303 ret &= test_free_parent_reparent_child_in_pool();
2304 test_reset();
2305 ret &= test_talloc_ptrtype();
2306 test_reset();
2307 ret &= test_talloc_free_in_destructor();
2308 test_reset();
2309 ret &= test_pool();
2310 test_reset();
2311 ret &= test_pool_steal();
2312 test_reset();
2313 ret &= test_free_ref_null_context();
2314 test_reset();
2315 ret &= test_rusty();
2316 test_reset();
2317 ret &= test_free_children();
2318 test_reset();
2319 ret &= test_memlimit();
2320 #ifdef HAVE_PTHREAD
2321 test_reset();
2322 ret &= test_pthread_talloc_passing();
2323 #endif
2326 if (ret) {
2327 test_reset();
2328 ret &= test_speed();
2330 test_reset();
2331 ret &= test_autofree();
2332 test_reset();
2333 ret &= test_magic_protection();
2334 test_reset();
2335 ret &= test_magic_free_protection();
2337 test_reset();
2338 talloc_disable_null_tracking();
2339 return ret;