6f23ad4e18a3de62647119b095646a29930f83cb
[samba.git] / lib / talloc / testsuite.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    local testing of talloc routines.
5
6    Copyright (C) Andrew Tridgell 2004
7    
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
11    
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.
16
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.
21
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/>.
24 */
25
26 #include "replace.h"
27 #include "system/time.h"
28 #include <talloc.h>
29
30 #ifdef HAVE_PTHREAD
31 #include <pthread.h>
32 #endif
33
34 #include <unistd.h>
35 #include <sys/wait.h>
36
37 #ifdef NDEBUG
38 #undef NDEBUG
39 #endif
40
41 #include <assert.h>
42
43 #include "talloc_testsuite.h"
44
45 static struct timeval private_timeval_current(void)
46 {
47         struct timeval tv;
48         gettimeofday(&tv, NULL);
49         return tv;
50 }
51
52 static double private_timeval_elapsed(struct timeval *tv)
53 {
54         struct timeval tv2 = private_timeval_current();
55         return (tv2.tv_sec - tv->tv_sec) + 
56                (tv2.tv_usec - tv->tv_usec)*1.0e-6;
57 }
58
59 #define torture_assert(test, expr, str) if (!(expr)) { \
60         printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
61                 test, __location__, #expr, str); \
62         return false; \
63 }
64
65 #define torture_assert_str_equal(test, arg1, arg2, desc) \
66         if (arg1 == NULL && arg2 == NULL) { /* OK, both NULL == equal */ \
67         } else if (arg1 == NULL || arg2 == NULL) {                      \
68                 return false;                                           \
69         } else if (strcmp(arg1, arg2)) {                        \
70                 printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
71                    test, __location__, arg1, arg2, desc); \
72                 return false; \
73         }
74
75 #define CHECK_SIZE(test, ptr, tsize) do { \
76         if (talloc_total_size(ptr) != (tsize)) { \
77                 printf("failed: %s [\n%s: wrong '%s' tree size: got %u  expected %u\n]\n", \
78                        test, __location__, #ptr, \
79                        (unsigned)talloc_total_size(ptr), \
80                        (unsigned)tsize); \
81                 talloc_report_full(ptr, stdout); \
82                 return false; \
83         } \
84 } while (0)
85
86 #define CHECK_BLOCKS(test, ptr, tblocks) do { \
87         if (talloc_total_blocks(ptr) != (tblocks)) { \
88                 printf("failed: %s [\n%s: wrong '%s' tree blocks: got %u  expected %u\n]\n", \
89                        test, __location__, #ptr, \
90                        (unsigned)talloc_total_blocks(ptr), \
91                        (unsigned)tblocks); \
92                 talloc_report_full(ptr, stdout); \
93                 return false; \
94         } \
95 } while (0)
96
97 #define CHECK_PARENT(test, ptr, parent) do { \
98         if (talloc_parent(ptr) != (parent)) { \
99                 printf("failed: %s [\n%s: '%s' has wrong parent: got %p  expected %p\n]\n", \
100                        test, __location__, #ptr, \
101                        talloc_parent(ptr), \
102                        (parent)); \
103                 talloc_report_full(ptr, stdout); \
104                 talloc_report_full(parent, stdout); \
105                 talloc_report_full(NULL, stdout); \
106                 return false; \
107         } \
108 } while (0)
109
110 static unsigned int test_abort_count;
111
112 #if 0
113 static void test_abort_fn(const char *reason)
114 {
115         printf("# test_abort_fn(%s)\n", reason);
116         test_abort_count++;
117 }
118
119 static void test_abort_start(void)
120 {
121         test_abort_count = 0;
122         talloc_set_abort_fn(test_abort_fn);
123 }
124 #endif
125
126 static void test_abort_stop(void)
127 {
128         test_abort_count = 0;
129         talloc_set_abort_fn(NULL);
130 }
131
132 static void test_log_stdout(const char *message)
133 {
134         fprintf(stdout, "%s", message);
135 }
136
137 /*
138   test references 
139 */
140 static bool test_ref1(void)
141 {
142         void *root, *p1, *p2, *ref, *r1;
143
144         printf("test: ref1\n# SINGLE REFERENCE FREE\n");
145
146         root = talloc_named_const(NULL, 0, "root");
147         p1 = talloc_named_const(root, 1, "p1");
148         p2 = talloc_named_const(p1, 1, "p2");
149         talloc_named_const(p1, 1, "x1");
150         talloc_named_const(p1, 2, "x2");
151         talloc_named_const(p1, 3, "x3");
152
153         r1 = talloc_named_const(root, 1, "r1"); 
154         ref = talloc_reference(r1, p2);
155         talloc_report_full(root, stderr);
156
157         CHECK_BLOCKS("ref1", p1, 5);
158         CHECK_BLOCKS("ref1", p2, 1);
159         CHECK_BLOCKS("ref1", ref, 1);
160         CHECK_BLOCKS("ref1", r1, 2);
161
162         fprintf(stderr, "Freeing p2\n");
163         talloc_unlink(r1, p2);
164         talloc_report_full(root, stderr);
165
166         CHECK_BLOCKS("ref1", p1, 5);
167         CHECK_BLOCKS("ref1", p2, 1);
168         CHECK_BLOCKS("ref1", r1, 1);
169
170         fprintf(stderr, "Freeing p1\n");
171         talloc_free(p1);
172         talloc_report_full(root, stderr);
173
174         CHECK_BLOCKS("ref1", r1, 1);
175
176         fprintf(stderr, "Freeing r1\n");
177         talloc_free(r1);
178         talloc_report_full(NULL, stderr);
179
180         fprintf(stderr, "Testing NULL\n");
181         if (talloc_reference(root, NULL)) {
182                 return false;
183         }
184
185         CHECK_BLOCKS("ref1", root, 1);
186
187         CHECK_SIZE("ref1", root, 0);
188
189         talloc_free(root);
190         printf("success: ref1\n");
191         return true;
192 }
193
194 /*
195   test references 
196 */
197 static bool test_ref2(void)
198 {
199         void *root, *p1, *p2, *ref, *r1;
200
201         printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
202         root = talloc_named_const(NULL, 0, "root");
203         p1 = talloc_named_const(root, 1, "p1");
204         talloc_named_const(p1, 1, "x1");
205         talloc_named_const(p1, 1, "x2");
206         talloc_named_const(p1, 1, "x3");
207         p2 = talloc_named_const(p1, 1, "p2");
208
209         r1 = talloc_named_const(root, 1, "r1"); 
210         ref = talloc_reference(r1, p2);
211         talloc_report_full(root, stderr);
212
213         CHECK_BLOCKS("ref2", p1, 5);
214         CHECK_BLOCKS("ref2", p2, 1);
215         CHECK_BLOCKS("ref2", r1, 2);
216
217         fprintf(stderr, "Freeing ref\n");
218         talloc_unlink(r1, ref);
219         talloc_report_full(root, stderr);
220
221         CHECK_BLOCKS("ref2", p1, 5);
222         CHECK_BLOCKS("ref2", p2, 1);
223         CHECK_BLOCKS("ref2", r1, 1);
224
225         fprintf(stderr, "Freeing p2\n");
226         talloc_free(p2);
227         talloc_report_full(root, stderr);
228
229         CHECK_BLOCKS("ref2", p1, 4);
230         CHECK_BLOCKS("ref2", r1, 1);
231
232         fprintf(stderr, "Freeing p1\n");
233         talloc_free(p1);
234         talloc_report_full(root, stderr);
235
236         CHECK_BLOCKS("ref2", r1, 1);
237
238         fprintf(stderr, "Freeing r1\n");
239         talloc_free(r1);
240         talloc_report_full(root, stderr);
241
242         CHECK_SIZE("ref2", root, 0);
243
244         talloc_free(root);
245         printf("success: ref2\n");
246         return true;
247 }
248
249 /*
250   test references 
251 */
252 static bool test_ref3(void)
253 {
254         void *root, *p1, *p2, *ref, *r1;
255
256         printf("test: ref3\n# PARENT REFERENCE FREE\n");
257
258         root = talloc_named_const(NULL, 0, "root");
259         p1 = talloc_named_const(root, 1, "p1");
260         p2 = talloc_named_const(root, 1, "p2");
261         r1 = talloc_named_const(p1, 1, "r1");
262         ref = talloc_reference(p2, r1);
263         talloc_report_full(root, stderr);
264
265         CHECK_BLOCKS("ref3", p1, 2);
266         CHECK_BLOCKS("ref3", p2, 2);
267         CHECK_BLOCKS("ref3", r1, 1);
268         CHECK_BLOCKS("ref3", ref, 1);
269
270         fprintf(stderr, "Freeing p1\n");
271         talloc_free(p1);
272         talloc_report_full(root, stderr);
273
274         CHECK_BLOCKS("ref3", p2, 2);
275         CHECK_BLOCKS("ref3", r1, 1);
276
277         fprintf(stderr, "Freeing p2\n");
278         talloc_free(p2);
279         talloc_report_full(root, stderr);
280
281         CHECK_SIZE("ref3", root, 0);
282
283         talloc_free(root);
284
285         printf("success: ref3\n");
286         return true;
287 }
288
289 /*
290   test references 
291 */
292 static bool test_ref4(void)
293 {
294         void *root, *p1, *p2, *ref, *r1;
295
296         printf("test: ref4\n# REFERRER REFERENCE FREE\n");
297
298         root = talloc_named_const(NULL, 0, "root");
299         p1 = talloc_named_const(root, 1, "p1");
300         talloc_named_const(p1, 1, "x1");
301         talloc_named_const(p1, 1, "x2");
302         talloc_named_const(p1, 1, "x3");
303         p2 = talloc_named_const(p1, 1, "p2");
304
305         r1 = talloc_named_const(root, 1, "r1"); 
306         ref = talloc_reference(r1, p2);
307         talloc_report_full(root, stderr);
308
309         CHECK_BLOCKS("ref4", p1, 5);
310         CHECK_BLOCKS("ref4", p2, 1);
311         CHECK_BLOCKS("ref4", ref, 1);
312         CHECK_BLOCKS("ref4", r1, 2);
313
314         fprintf(stderr, "Freeing r1\n");
315         talloc_free(r1);
316         talloc_report_full(root, stderr);
317
318         CHECK_BLOCKS("ref4", p1, 5);
319         CHECK_BLOCKS("ref4", p2, 1);
320
321         fprintf(stderr, "Freeing p2\n");
322         talloc_free(p2);
323         talloc_report_full(root, stderr);
324
325         CHECK_BLOCKS("ref4", p1, 4);
326
327         fprintf(stderr, "Freeing p1\n");
328         talloc_free(p1);
329         talloc_report_full(root, stderr);
330
331         CHECK_SIZE("ref4", root, 0);
332
333         talloc_free(root);
334
335         printf("success: ref4\n");
336         return true;
337 }
338
339
340 /*
341   test references 
342 */
343 static bool test_unlink1(void)
344 {
345         void *root, *p1, *p2, *ref, *r1;
346
347         printf("test: unlink\n# UNLINK\n");
348
349         root = talloc_named_const(NULL, 0, "root");
350         p1 = talloc_named_const(root, 1, "p1");
351         talloc_named_const(p1, 1, "x1");
352         talloc_named_const(p1, 1, "x2");
353         talloc_named_const(p1, 1, "x3");
354         p2 = talloc_named_const(p1, 1, "p2");
355
356         r1 = talloc_named_const(p1, 1, "r1");   
357         ref = talloc_reference(r1, p2);
358         talloc_report_full(root, stderr);
359
360         CHECK_BLOCKS("unlink", p1, 7);
361         CHECK_BLOCKS("unlink", p2, 1);
362         CHECK_BLOCKS("unlink", ref, 1);
363         CHECK_BLOCKS("unlink", r1, 2);
364
365         fprintf(stderr, "Unreferencing r1\n");
366         talloc_unlink(r1, p2);
367         talloc_report_full(root, stderr);
368
369         CHECK_BLOCKS("unlink", p1, 6);
370         CHECK_BLOCKS("unlink", p2, 1);
371         CHECK_BLOCKS("unlink", r1, 1);
372
373         fprintf(stderr, "Freeing p1\n");
374         talloc_free(p1);
375         talloc_report_full(root, stderr);
376
377         CHECK_SIZE("unlink", root, 0);
378
379         talloc_free(root);
380
381         printf("success: unlink\n");
382         return true;
383 }
384
385 static int fail_destructor(void *ptr)
386 {
387         return -1;
388 }
389
390 /*
391   miscellaneous tests to try to get a higher test coverage percentage
392 */
393 static bool test_misc(void)
394 {
395         void *root, *p1;
396         char *p2;
397         double *d;
398         const char *name;
399
400         printf("test: misc\n# MISCELLANEOUS\n");
401
402         root = talloc_new(NULL);
403
404         p1 = talloc_size(root, 0x7fffffff);
405         torture_assert("misc", !p1, "failed: large talloc allowed\n");
406
407         p1 = talloc_strdup(root, "foo");
408         talloc_increase_ref_count(p1);
409         talloc_increase_ref_count(p1);
410         talloc_increase_ref_count(p1);
411         CHECK_BLOCKS("misc", p1, 1);
412         CHECK_BLOCKS("misc", root, 2);
413         talloc_unlink(NULL, p1);
414         CHECK_BLOCKS("misc", p1, 1);
415         CHECK_BLOCKS("misc", root, 2);
416         talloc_unlink(NULL, p1);
417         CHECK_BLOCKS("misc", p1, 1);
418         CHECK_BLOCKS("misc", root, 2);
419         p2 = talloc_strdup(p1, "foo");
420         torture_assert("misc", talloc_unlink(root, p2) == -1,
421                                    "failed: talloc_unlink() of non-reference context should return -1\n");
422         torture_assert("misc", talloc_unlink(p1, p2) == 0,
423                 "failed: talloc_unlink() of parent should succeed\n");
424         talloc_unlink(NULL, p1);
425         CHECK_BLOCKS("misc", p1, 1);
426         CHECK_BLOCKS("misc", root, 2);
427
428         name = talloc_set_name(p1, "my name is %s", "foo");
429         torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
430                 "failed: wrong name after talloc_set_name(my name is foo)");
431         torture_assert_str_equal("misc", talloc_get_name(p1), name,
432                 "failed: wrong name after talloc_set_name(my name is foo)");
433         CHECK_BLOCKS("misc", p1, 2);
434         CHECK_BLOCKS("misc", root, 3);
435
436         talloc_set_name_const(p1, NULL);
437         torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
438                 "failed: wrong name after talloc_set_name(NULL)");
439         CHECK_BLOCKS("misc", p1, 2);
440         CHECK_BLOCKS("misc", root, 3);
441
442         torture_assert("misc", talloc_free(NULL) == -1, 
443                                    "talloc_free(NULL) should give -1\n");
444
445         talloc_set_destructor(p1, fail_destructor);
446         torture_assert("misc", talloc_free(p1) == -1, 
447                 "Failed destructor should cause talloc_free to fail\n");
448         talloc_set_destructor(p1, NULL);
449
450         talloc_report(root, stderr);
451
452
453         p2 = (char *)talloc_zero_size(p1, 20);
454         torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n");
455         talloc_free(p2);
456
457         torture_assert("misc", talloc_strdup(root, NULL) == NULL,
458                 "failed: strdup on NULL should give NULL\n");
459
460         p2 = talloc_strndup(p1, "foo", 2);
461         torture_assert("misc", strcmp("fo", p2) == 0, 
462                                    "strndup doesn't work\n");
463         p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd');
464         torture_assert("misc", strcmp("food", p2) == 0, 
465                                    "talloc_asprintf_append_buffer doesn't work\n");
466         CHECK_BLOCKS("misc", p2, 1);
467         CHECK_BLOCKS("misc", p1, 3);
468
469         p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world");
470         torture_assert("misc", strcmp("hello world", p2) == 0,
471                 "talloc_asprintf_append_buffer doesn't work\n");
472         CHECK_BLOCKS("misc", p2, 1);
473         CHECK_BLOCKS("misc", p1, 3);
474         talloc_free(p2);
475
476         d = talloc_array(p1, double, 0x20000000);
477         torture_assert("misc", !d, "failed: integer overflow not detected\n");
478
479         d = talloc_realloc(p1, d, double, 0x20000000);
480         torture_assert("misc", !d, "failed: integer overflow not detected\n");
481
482         talloc_free(p1);
483         CHECK_BLOCKS("misc", root, 1);
484
485         p1 = talloc_named(root, 100, "%d bytes", 100);
486         CHECK_BLOCKS("misc", p1, 2);
487         CHECK_BLOCKS("misc", root, 3);
488         talloc_unlink(root, p1);
489
490         p1 = talloc_init("%d bytes", 200);
491         p2 = talloc_asprintf(p1, "my test '%s'", "string");
492         torture_assert_str_equal("misc", p2, "my test 'string'",
493                 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
494         CHECK_BLOCKS("misc", p1, 3);
495         CHECK_SIZE("misc", p2, 17);
496         CHECK_BLOCKS("misc", root, 1);
497         talloc_unlink(NULL, p1);
498
499         p1 = talloc_named_const(root, 10, "p1");
500         p2 = (char *)talloc_named_const(root, 20, "p2");
501         (void)talloc_reference(p1, p2);
502         talloc_report_full(root, stderr);
503         talloc_unlink(root, p2);
504         talloc_report_full(root, stderr);
505         CHECK_BLOCKS("misc", p2, 1);
506         CHECK_BLOCKS("misc", p1, 2);
507         CHECK_BLOCKS("misc", root, 3);
508         talloc_unlink(p1, p2);
509         talloc_unlink(root, p1);
510
511         p1 = talloc_named_const(root, 10, "p1");
512         p2 = (char *)talloc_named_const(root, 20, "p2");
513         (void)talloc_reference(NULL, p2);
514         talloc_report_full(root, stderr);
515         talloc_unlink(root, p2);
516         talloc_report_full(root, stderr);
517         CHECK_BLOCKS("misc", p2, 1);
518         CHECK_BLOCKS("misc", p1, 1);
519         CHECK_BLOCKS("misc", root, 2);
520         talloc_unlink(NULL, p2);
521         talloc_unlink(root, p1);
522
523         /* Test that talloc_unlink is a no-op */
524
525         torture_assert("misc", talloc_unlink(root, NULL) == -1,
526                 "failed: talloc_unlink(root, NULL) == -1\n");
527
528         talloc_report(root, stderr);
529         talloc_report(NULL, stderr);
530
531         CHECK_SIZE("misc", root, 0);
532
533         talloc_free(root);
534
535         CHECK_SIZE("misc", NULL, 0);
536
537         talloc_enable_null_tracking_no_autofree();
538         talloc_enable_leak_report();
539         talloc_enable_leak_report_full();
540
541         printf("success: misc\n");
542
543         return true;
544 }
545
546
547 /*
548   test realloc
549 */
550 static bool test_realloc(void)
551 {
552         void *root, *p1, *p2;
553
554         printf("test: realloc\n# REALLOC\n");
555
556         root = talloc_new(NULL);
557
558         p1 = talloc_size(root, 10);
559         CHECK_SIZE("realloc", p1, 10);
560
561         p1 = talloc_realloc_size(NULL, p1, 20);
562         CHECK_SIZE("realloc", p1, 20);
563
564         talloc_new(p1);
565
566         p2 = talloc_realloc_size(p1, NULL, 30);
567
568         talloc_new(p1);
569
570         p2 = talloc_realloc_size(p1, p2, 40);
571
572         CHECK_SIZE("realloc", p2, 40);
573         CHECK_SIZE("realloc", root, 60);
574         CHECK_BLOCKS("realloc", p1, 4);
575
576         p1 = talloc_realloc_size(NULL, p1, 20);
577         CHECK_SIZE("realloc", p1, 60);
578
579         talloc_increase_ref_count(p2);
580         torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
581                 "failed: talloc_realloc() on a referenced pointer should fail\n");
582         CHECK_BLOCKS("realloc", p1, 4);
583
584         talloc_realloc_size(NULL, p2, 0);
585         talloc_realloc_size(NULL, p2, 0);
586         CHECK_BLOCKS("realloc", p1, 4);
587         talloc_realloc_size(p1, p2, 0);
588         CHECK_BLOCKS("realloc", p1, 3);
589
590         torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
591                 "failed: oversize talloc should fail\n");
592
593         talloc_realloc_size(NULL, p1, 0);
594         CHECK_BLOCKS("realloc", root, 4);
595         talloc_realloc_size(root, p1, 0);
596         CHECK_BLOCKS("realloc", root, 1);
597
598         CHECK_SIZE("realloc", root, 0);
599
600         talloc_free(root);
601
602         printf("success: realloc\n");
603
604         return true;
605 }
606
607 /*
608   test realloc with a child
609 */
610 static bool test_realloc_child(void)
611 {
612         void *root;
613         struct el2 {
614                 const char *name;
615         } *el2, *el2_2, *el2_3, **el_list_save;
616         struct el1 {
617                 int count;
618                 struct el2 **list, **list2, **list3;
619         } *el1;
620
621         printf("test: REALLOC WITH CHILD\n");
622
623         root = talloc_new(NULL);
624
625         el1 = talloc(root, struct el1);
626         el1->list = talloc(el1, struct el2 *);
627         el1->list[0] = talloc(el1->list, struct el2);
628         el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
629
630         el1->list2 = talloc(el1, struct el2 *);
631         el1->list2[0] = talloc(el1->list2, struct el2);
632         el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
633
634         el1->list3 = talloc(el1, struct el2 *);
635         el1->list3[0] = talloc(el1->list3, struct el2);
636         el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
637         
638         el2 = talloc(el1->list, struct el2);
639         CHECK_PARENT("el2", el2, el1->list);
640         el2_2 = talloc(el1->list2, struct el2);
641         CHECK_PARENT("el2", el2_2, el1->list2);
642         el2_3 = talloc(el1->list3, struct el2);
643         CHECK_PARENT("el2", el2_3, el1->list3);
644
645         el_list_save = el1->list;
646         el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
647         if (el1->list == el_list_save) {
648                 printf("failure: talloc_realloc didn't move pointer");
649                 return false;
650         }
651
652         CHECK_PARENT("el1_after_realloc", el1->list, el1);
653         el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
654         CHECK_PARENT("el1_after_realloc", el1->list2, el1);
655         el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
656         CHECK_PARENT("el1_after_realloc", el1->list3, el1);
657
658         CHECK_PARENT("el2", el2, el1->list);
659         CHECK_PARENT("el2", el2_2, el1->list2);
660         CHECK_PARENT("el2", el2_3, el1->list3);
661
662         /* Finally check realloc with multiple children */
663         el1 = talloc_realloc(root, el1, struct el1, 100);
664         CHECK_PARENT("el1->list", el1->list, el1);
665         CHECK_PARENT("el1->list2", el1->list2, el1);
666         CHECK_PARENT("el1->list3", el1->list3, el1);
667
668         talloc_free(root);
669
670         printf("success: REALLOC WITH CHILD\n");
671         return true;
672 }
673
674 /*
675   test type checking
676 */
677 static bool test_type(void)
678 {
679         void *root;
680         struct el1 {
681                 int count;
682         };
683         struct el2 {
684                 int count;
685         };
686         struct el1 *el1;
687
688         printf("test: type\n# talloc type checking\n");
689
690         root = talloc_new(NULL);
691
692         el1 = talloc(root, struct el1);
693
694         el1->count = 1;
695
696         torture_assert("type", talloc_get_type(el1, struct el1) == el1,
697                 "type check failed on el1\n");
698         torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
699                 "type check failed on el1 with el2\n");
700         talloc_set_type(el1, struct el2);
701         torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
702                 "type set failed on el1 with el2\n");
703
704         talloc_free(root);
705
706         printf("success: type\n");
707         return true;
708 }
709
710 /*
711   test steal
712 */
713 static bool test_steal(void)
714 {
715         void *root, *p1, *p2;
716
717         printf("test: steal\n# STEAL\n");
718
719         root = talloc_new(NULL);
720
721         p1 = talloc_array(root, char, 10);
722         CHECK_SIZE("steal", p1, 10);
723
724         p2 = talloc_realloc(root, NULL, char, 20);
725         CHECK_SIZE("steal", p1, 10);
726         CHECK_SIZE("steal", root, 30);
727
728         torture_assert("steal", talloc_steal(p1, NULL) == NULL,
729                 "failed: stealing NULL should give NULL\n");
730
731         torture_assert("steal", talloc_steal(p1, p1) == p1,
732                 "failed: stealing to ourselves is a nop\n");
733         CHECK_BLOCKS("steal", root, 3);
734         CHECK_SIZE("steal", root, 30);
735
736         talloc_steal(NULL, p1);
737         talloc_steal(NULL, p2);
738         CHECK_BLOCKS("steal", root, 1);
739         CHECK_SIZE("steal", root, 0);
740
741         talloc_free(p1);
742         talloc_steal(root, p2);
743         CHECK_BLOCKS("steal", root, 2);
744         CHECK_SIZE("steal", root, 20);
745         
746         talloc_free(p2);
747
748         CHECK_BLOCKS("steal", root, 1);
749         CHECK_SIZE("steal", root, 0);
750
751         talloc_free(root);
752
753         p1 = talloc_size(NULL, 3);
754         talloc_report_full(NULL, stderr);
755         CHECK_SIZE("steal", NULL, 3);
756         talloc_free(p1);
757
758         printf("success: steal\n");
759         return true;
760 }
761
762 /*
763   test move
764 */
765 static bool test_move(void)
766 {
767         void *root;
768         struct t_move {
769                 char *p;
770                 int *x;
771         } *t1, *t2;
772
773         printf("test: move\n# MOVE\n");
774
775         root = talloc_new(NULL);
776
777         t1 = talloc(root, struct t_move);
778         t2 = talloc(root, struct t_move);
779         t1->p = talloc_strdup(t1, "foo");
780         t1->x = talloc(t1, int);
781         *t1->x = 42;
782
783         t2->p = talloc_move(t2, &t1->p);
784         t2->x = talloc_move(t2, &t1->x);
785         torture_assert("move", t1->p == NULL && t1->x == NULL &&
786             strcmp(t2->p, "foo") == 0 && *t2->x == 42,
787                 "talloc move failed");
788
789         talloc_free(root);
790
791         printf("success: move\n");
792
793         return true;
794 }
795
796 /*
797   test talloc_realloc_fn
798 */
799 static bool test_realloc_fn(void)
800 {
801         void *root, *p1;
802
803         printf("test: realloc_fn\n# talloc_realloc_fn\n");
804
805         root = talloc_new(NULL);
806
807         p1 = talloc_realloc_fn(root, NULL, 10);
808         CHECK_BLOCKS("realloc_fn", root, 2);
809         CHECK_SIZE("realloc_fn", root, 10);
810         p1 = talloc_realloc_fn(root, p1, 20);
811         CHECK_BLOCKS("realloc_fn", root, 2);
812         CHECK_SIZE("realloc_fn", root, 20);
813         p1 = talloc_realloc_fn(root, p1, 0);
814         CHECK_BLOCKS("realloc_fn", root, 1);
815         CHECK_SIZE("realloc_fn", root, 0);
816
817         talloc_free(root);
818
819         printf("success: realloc_fn\n");
820         return true;
821 }
822
823
824 static bool test_unref_reparent(void)
825 {
826         void *root, *p1, *p2, *c1;
827
828         printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
829
830         root = talloc_named_const(NULL, 0, "root");
831         p1 = talloc_named_const(root, 1, "orig parent");
832         p2 = talloc_named_const(root, 1, "parent by reference");
833
834         c1 = talloc_named_const(p1, 1, "child");
835         talloc_reference(p2, c1);
836
837         CHECK_PARENT("unref_reparent", c1, p1);
838
839         talloc_free(p1);
840
841         CHECK_PARENT("unref_reparent", c1, p2);
842
843         talloc_unlink(p2, c1);
844
845         CHECK_SIZE("unref_reparent", root, 1);
846
847         talloc_free(p2);
848         talloc_free(root);
849
850         printf("success: unref_reparent\n");
851         return true;
852 }
853
854 /*
855   measure the speed of talloc versus malloc
856 */
857 static bool test_speed(void)
858 {
859         void *ctx = talloc_new(NULL);
860         unsigned count;
861         const int loop = 1000;
862         int i;
863         struct timeval tv;
864
865         printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
866
867         tv = private_timeval_current();
868         count = 0;
869         do {
870                 void *p1, *p2, *p3;
871                 for (i=0;i<loop;i++) {
872                         p1 = talloc_size(ctx, loop % 100);
873                         p2 = talloc_strdup(p1, "foo bar");
874                         p3 = talloc_size(p1, 300);
875                         (void)p2;
876                         (void)p3;
877                         talloc_free(p1);
878                 }
879                 count += 3 * loop;
880         } while (private_timeval_elapsed(&tv) < 5.0);
881
882         fprintf(stderr, "talloc: %.0f ops/sec\n", count/private_timeval_elapsed(&tv));
883
884         talloc_free(ctx);
885
886         ctx = talloc_pool(NULL, 1024);
887
888         tv = private_timeval_current();
889         count = 0;
890         do {
891                 void *p1, *p2, *p3;
892                 for (i=0;i<loop;i++) {
893                         p1 = talloc_size(ctx, loop % 100);
894                         p2 = talloc_strdup(p1, "foo bar");
895                         p3 = talloc_size(p1, 300);
896                         (void)p2;
897                         (void)p3;
898                         talloc_free(p1);
899                 }
900                 count += 3 * loop;
901         } while (private_timeval_elapsed(&tv) < 5.0);
902
903         talloc_free(ctx);
904
905         fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/private_timeval_elapsed(&tv));
906
907         tv = private_timeval_current();
908         count = 0;
909         do {
910                 void *p1, *p2, *p3;
911                 for (i=0;i<loop;i++) {
912                         p1 = malloc(loop % 100);
913                         p2 = strdup("foo bar");
914                         p3 = malloc(300);
915                         free(p1);
916                         free(p2);
917                         free(p3);
918                 }
919                 count += 3 * loop;
920         } while (private_timeval_elapsed(&tv) < 5.0);
921         fprintf(stderr, "malloc: %.0f ops/sec\n", count/private_timeval_elapsed(&tv));
922
923         printf("success: speed\n");
924
925         return true;
926 }
927
928 static bool test_lifeless(void)
929 {
930         void *top = talloc_new(NULL);
931         char *parent, *child; 
932         void *child_owner = talloc_new(NULL);
933
934         printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
935
936         parent = talloc_strdup(top, "parent");
937         child = talloc_strdup(parent, "child");  
938         (void)talloc_reference(child, parent);
939         (void)talloc_reference(child_owner, child); 
940         talloc_report_full(top, stderr);
941         talloc_unlink(top, parent);
942         talloc_unlink(top, child);
943         talloc_report_full(top, stderr);
944         talloc_free(top);
945         talloc_free(child_owner);
946         talloc_free(child);
947
948         printf("success: lifeless\n");
949         return true;
950 }
951
952 static int loop_destructor_count;
953
954 static int test_loop_destructor(char *ptr)
955 {
956         loop_destructor_count++;
957         return 0;
958 }
959
960 static bool test_loop(void)
961 {
962         void *top = talloc_new(NULL);
963         char *parent;
964         struct req1 {
965                 char *req2, *req3;
966         } *req1;
967
968         printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
969
970         parent = talloc_strdup(top, "parent");
971         req1 = talloc(parent, struct req1);
972         req1->req2 = talloc_strdup(req1, "req2");  
973         talloc_set_destructor(req1->req2, test_loop_destructor);
974         req1->req3 = talloc_strdup(req1, "req3");
975         (void)talloc_reference(req1->req3, req1);
976         talloc_report_full(top, stderr);
977         talloc_free(parent);
978         talloc_report_full(top, stderr);
979         talloc_report_full(NULL, stderr);
980         talloc_free(top);
981
982         torture_assert("loop", loop_destructor_count == 1, 
983                                    "FAILED TO FIRE LOOP DESTRUCTOR\n");
984         loop_destructor_count = 0;
985
986         printf("success: loop\n");
987         return true;
988 }
989
990 static int realloc_parent_destructor_count;
991
992 static int test_realloc_parent_destructor(char *ptr)
993 {
994         realloc_parent_destructor_count++;
995         return 0;
996 }
997
998 static bool test_realloc_on_destructor_parent(void)
999 {
1000         void *top = talloc_new(NULL);
1001         char *parent;
1002         char *a, *b, *C, *D;
1003         realloc_parent_destructor_count = 0;
1004
1005         printf("test: free_for_exit\n# TALLOC FREE FOR EXIT\n");
1006
1007         parent = talloc_strdup(top, "parent");
1008         a = talloc_strdup(parent, "a");
1009         b = talloc_strdup(a, "b");
1010         C = talloc_strdup(a, "C");
1011         D = talloc_strdup(b, "D");
1012         talloc_set_destructor(D, test_realloc_parent_destructor);
1013         /* Capitalised ones have destructors.
1014          *
1015          * parent --> a -> b -> D
1016          *              -> c
1017          */
1018
1019         a = talloc_realloc(parent, a, char, 2048);
1020
1021         torture_assert("check talloc_realloc", a != NULL, "talloc_realloc failed");
1022
1023         talloc_set_destructor(C, test_realloc_parent_destructor);
1024         /*
1025          * parent --> a[2048] -> b -> D
1026          *                    -> C
1027          *
1028          */
1029
1030         talloc_free(parent);
1031
1032         torture_assert("check destructor realloc_parent_destructor",
1033                        realloc_parent_destructor_count == 2,
1034                        "FAILED TO FIRE free_for_exit_destructor\n");
1035
1036
1037         printf("success: free_for_exit\n");
1038         talloc_free(top); /* make ASAN happy */
1039
1040         return true;
1041 }
1042
1043 static int fail_destructor_str(char *ptr)
1044 {
1045         return -1;
1046 }
1047
1048 static bool test_free_parent_deny_child(void)
1049 {
1050         void *top = talloc_new(NULL);
1051         char *level1;
1052         char *level2;
1053         char *level3;
1054
1055         printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
1056
1057         level1 = talloc_strdup(top, "level1");
1058         level2 = talloc_strdup(level1, "level2");
1059         level3 = talloc_strdup(level2, "level3");
1060
1061         talloc_set_destructor(level3, fail_destructor_str);
1062         talloc_free(level1);
1063         talloc_set_destructor(level3, NULL);
1064
1065         CHECK_PARENT("free_parent_deny_child", level3, top);
1066
1067         talloc_free(top);
1068
1069         printf("success: free_parent_deny_child\n");
1070         return true;
1071 }
1072
1073 struct new_parent {
1074         void *new_parent;
1075         char val[20];
1076 };
1077
1078 static int reparenting_destructor(struct new_parent *np)
1079 {
1080         talloc_set_destructor(np, NULL);
1081         (void)talloc_move(np->new_parent, &np);
1082         return -1;
1083 }
1084
1085 static bool test_free_parent_reparent_child(void)
1086 {
1087         void *top = talloc_new(NULL);
1088         char *level1;
1089         char *alternate_level1;
1090         char *level2;
1091         struct new_parent *level3;
1092
1093         printf("test: free_parent_reparent_child\n# "
1094                 "TALLOC FREE PARENT REPARENT CHILD\n");
1095
1096         level1 = talloc_strdup(top, "level1");
1097         alternate_level1 = talloc_strdup(top, "alternate_level1");
1098         level2 = talloc_strdup(level1, "level2");
1099         level3 = talloc(level2, struct new_parent);
1100         level3->new_parent = alternate_level1;
1101         memset(level3->val, 'x', sizeof(level3->val));
1102
1103         talloc_set_destructor(level3, reparenting_destructor);
1104         talloc_free(level1);
1105
1106         CHECK_PARENT("free_parent_reparent_child",
1107                 level3, alternate_level1);
1108
1109         talloc_free(top);
1110
1111         printf("success: free_parent_reparent_child\n");
1112         return true;
1113 }
1114
1115 static bool test_free_parent_reparent_child_in_pool(void)
1116 {
1117         void *top = talloc_new(NULL);
1118         char *level1;
1119         char *alternate_level1;
1120         char *level2;
1121         void *pool;
1122         struct new_parent *level3;
1123
1124         printf("test: free_parent_reparent_child_in_pool\n# "
1125                 "TALLOC FREE PARENT REPARENT CHILD IN POOL\n");
1126
1127         pool = talloc_pool(top, 1024);
1128         level1 = talloc_strdup(pool, "level1");
1129         alternate_level1 = talloc_strdup(top, "alternate_level1");
1130         level2 = talloc_strdup(level1, "level2");
1131         level3 = talloc(level2, struct new_parent);
1132         level3->new_parent = alternate_level1;
1133         memset(level3->val, 'x', sizeof(level3->val));
1134
1135         talloc_set_destructor(level3, reparenting_destructor);
1136         talloc_free(level1);
1137         talloc_set_destructor(level3, NULL);
1138
1139         CHECK_PARENT("free_parent_reparent_child_in_pool",
1140                 level3, alternate_level1);
1141
1142         /* Even freeing alternate_level1 should leave pool alone. */
1143         talloc_free(alternate_level1);
1144         talloc_free(top);
1145
1146         printf("success: free_parent_reparent_child_in_pool\n");
1147         return true;
1148 }
1149
1150
1151 static bool test_talloc_ptrtype(void)
1152 {
1153         void *top = talloc_new(NULL);
1154         struct struct1 {
1155                 int foo;
1156                 int bar;
1157         } *s1, *s2, **s3, ***s4;
1158         const char *location1;
1159         const char *location2;
1160         const char *location3;
1161         const char *location4;
1162
1163         printf("test: ptrtype\n# TALLOC PTRTYPE\n");
1164
1165         s1 = talloc_ptrtype(top, s1);location1 = __location__;
1166
1167         if (talloc_get_size(s1) != sizeof(struct struct1)) {
1168                 printf("failure: ptrtype [\n"
1169                   "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1170                   "]\n", (unsigned long)talloc_get_size(s1),
1171                            (unsigned long)sizeof(struct struct1));
1172                 return false;
1173         }
1174
1175         if (strcmp(location1, talloc_get_name(s1)) != 0) {
1176                 printf("failure: ptrtype [\n"
1177                   "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1178                         talloc_get_name(s1), location1);
1179                 return false;
1180         }
1181
1182         s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
1183
1184         if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
1185                 printf("failure: ptrtype [\n"
1186                            "talloc_array_ptrtype() allocated the wrong size "
1187                        "%lu (should be %lu)\n]\n",
1188                         (unsigned long)talloc_get_size(s2),
1189                     (unsigned long)(sizeof(struct struct1)*10));
1190                 return false;
1191         }
1192
1193         if (strcmp(location2, talloc_get_name(s2)) != 0) {
1194                 printf("failure: ptrtype [\n"
1195                 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1196                         talloc_get_name(s2), location2);
1197                 return false;
1198         }
1199
1200         s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
1201
1202         if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
1203                 printf("failure: ptrtype [\n"
1204                            "talloc_array_ptrtype() allocated the wrong size "
1205                        "%lu (should be %lu)\n]\n",
1206                            (unsigned long)talloc_get_size(s3),
1207                        (unsigned long)(sizeof(struct struct1 *)*10));
1208                 return false;
1209         }
1210
1211         torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
1212                 "talloc_array_ptrtype() sets the wrong name");
1213
1214         s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
1215
1216         if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
1217                 printf("failure: ptrtype [\n"
1218                       "talloc_array_ptrtype() allocated the wrong size "
1219                        "%lu (should be %lu)\n]\n",
1220                            (unsigned long)talloc_get_size(s4),
1221                        (unsigned long)(sizeof(struct struct1 **)*10));
1222                 return false;
1223         }
1224
1225         torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
1226                 "talloc_array_ptrtype() sets the wrong name");
1227
1228         talloc_free(top);
1229
1230         printf("success: ptrtype\n");
1231         return true;
1232 }
1233
1234 static int _test_talloc_free_in_destructor(void **ptr)
1235 {
1236         talloc_free(*ptr);
1237         return 0;
1238 }
1239
1240 static bool test_talloc_free_in_destructor(void)
1241 {
1242         void *level0;
1243         void *level1;
1244         void *level2;
1245         void *level3;
1246         void *level4;
1247         void **level5;
1248
1249         printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1250
1251         level0 = talloc_new(NULL);
1252         level1 = talloc_new(level0);
1253         level2 = talloc_new(level1);
1254         level3 = talloc_new(level2);
1255         level4 = talloc_new(level3);
1256         level5 = talloc(level4, void *);
1257
1258         *level5 = level3;
1259         (void)talloc_reference(level0, level3);
1260         (void)talloc_reference(level3, level3);
1261         (void)talloc_reference(level5, level3);
1262
1263         talloc_set_destructor(level5, _test_talloc_free_in_destructor);
1264
1265         talloc_free(level1);
1266
1267         talloc_free(level0);
1268
1269         talloc_free(level3); /* make ASAN happy */
1270
1271         printf("success: free_in_destructor\n");
1272         return true;
1273 }
1274
1275 static bool test_autofree(void)
1276 {
1277 #if _SAMBA_BUILD_ < 4
1278         /* autofree test would kill smbtorture */
1279         void *p;
1280         printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1281
1282         p = talloc_autofree_context();
1283         talloc_free(p);
1284
1285         p = talloc_autofree_context();
1286         talloc_free(p);
1287
1288         printf("success: autofree\n");
1289 #endif
1290         return true;
1291 }
1292
1293 static bool test_pool(void)
1294 {
1295         void *pool;
1296         void *p1, *p2, *p3, *p4;
1297         void *p2_2;
1298
1299         pool = talloc_pool(NULL, 1024);
1300
1301         p1 = talloc_size(pool, 80);
1302         memset(p1, 0x11, talloc_get_size(p1));
1303         p2 = talloc_size(pool, 20);
1304         memset(p2, 0x11, talloc_get_size(p2));
1305         p3 = talloc_size(p1, 50);
1306         memset(p3, 0x11, talloc_get_size(p3));
1307         p4 = talloc_size(p3, 1000);
1308         memset(p4, 0x11, talloc_get_size(p4));
1309
1310 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1311         p2_2 = talloc_realloc_size(pool, p2, 20+1);
1312         torture_assert("pool realloc 20+1", p2_2 == p2, "failed: pointer changed");
1313         memset(p2, 0x11, talloc_get_size(p2));
1314         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1315         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1316         memset(p2, 0x11, talloc_get_size(p2));
1317         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1318         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1319         memset(p2, 0x11, talloc_get_size(p2));
1320
1321         talloc_free(p3);
1322
1323         /* this should reclaim the memory of p4 and p3 */
1324         p2_2 = talloc_realloc_size(pool, p2, 400);
1325         torture_assert("pool realloc 400", p2_2 == p2, "failed: pointer changed");
1326         memset(p2, 0x11, talloc_get_size(p2));
1327
1328         talloc_free(p1);
1329
1330         /* this should reclaim the memory of p1 */
1331         p2_2 = talloc_realloc_size(pool, p2, 800);
1332         torture_assert("pool realloc 800", p2_2 == p1, "failed: pointer not changed");
1333         p2 = p2_2;
1334         memset(p2, 0x11, talloc_get_size(p2));
1335
1336         /* this should do a malloc */
1337         p2_2 = talloc_realloc_size(pool, p2, 1800);
1338         torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
1339         p2 = p2_2;
1340         memset(p2, 0x11, talloc_get_size(p2));
1341
1342         /* this should reclaim the memory from the pool */
1343         p3 = talloc_size(pool, 80);
1344         torture_assert("pool alloc 80", p3 == p1, "failed: pointer changed");
1345         memset(p3, 0x11, talloc_get_size(p3));
1346
1347         talloc_free(p2);
1348         talloc_free(p3);
1349
1350         p1 = talloc_size(pool, 80);
1351         memset(p1, 0x11, talloc_get_size(p1));
1352         p2 = talloc_size(pool, 20);
1353         memset(p2, 0x11, talloc_get_size(p2));
1354
1355         talloc_free(p1);
1356
1357         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1358         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1359         memset(p2, 0x11, talloc_get_size(p2));
1360         p2_2 = talloc_realloc_size(pool, p2, 20-1);
1361         torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1362         memset(p2, 0x11, talloc_get_size(p2));
1363
1364         /* this should do a malloc */
1365         p2_2 = talloc_realloc_size(pool, p2, 1800);
1366         torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
1367         p2 = p2_2;
1368         memset(p2, 0x11, talloc_get_size(p2));
1369
1370         /* this should reclaim the memory from the pool */
1371         p3 = talloc_size(pool, 800);
1372         torture_assert("pool alloc 800", p3 == p1, "failed: pointer changed");
1373         memset(p3, 0x11, talloc_get_size(p3));
1374
1375 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1376
1377         talloc_free(pool);
1378
1379         return true;
1380 }
1381
1382 static bool test_pool_steal(void)
1383 {
1384         void *root;
1385         void *pool;
1386         void *p1, *p2;
1387         void *p1_2, *p2_2;
1388         size_t hdr;
1389         size_t ofs1, ofs2;
1390
1391         root = talloc_new(NULL);
1392         pool = talloc_pool(root, 1024);
1393
1394         p1 = talloc_size(pool, 4 * 16);
1395         torture_assert("pool allocate 4 * 16", p1 != NULL, "failed ");
1396         memset(p1, 0x11, talloc_get_size(p1));
1397         p2 = talloc_size(pool, 4 * 16);
1398         torture_assert("pool allocate 4 * 16", p2 > p1, "failed: !(p2 > p1) ");
1399         memset(p2, 0x11, talloc_get_size(p2));
1400
1401         ofs1 = PTR_DIFF(p2, p1);
1402         hdr = ofs1 - talloc_get_size(p1);
1403
1404         talloc_steal(root, p1);
1405         talloc_steal(root, p2);
1406
1407         talloc_free(pool);
1408
1409         p1_2 = p1;
1410
1411 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1412         p1_2 = talloc_realloc_size(root, p1, 5 * 16);
1413         torture_assert("pool realloc 5 * 16", p1_2 > p2, "failed: pointer not changed");
1414         memset(p1_2, 0x11, talloc_get_size(p1_2));
1415         ofs1 = PTR_DIFF(p1_2, p2);
1416         ofs2 = talloc_get_size(p2) + hdr;
1417
1418         torture_assert("pool realloc ", ofs1 == ofs2, "failed: pointer offset unexpected");
1419
1420         p2_2 = talloc_realloc_size(root, p2, 3 * 16);
1421         torture_assert("pool realloc 5 * 16", p2_2 == p2, "failed: pointer changed");
1422         memset(p2_2, 0x11, talloc_get_size(p2_2));
1423 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1424
1425         talloc_free(p1_2);
1426
1427         p2_2 = p2;
1428
1429 #if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1430         /* now we should reclaim the full pool */
1431         p2_2 = talloc_realloc_size(root, p2, 8 * 16);
1432         torture_assert("pool realloc 8 * 16", p2_2 == p1, "failed: pointer not expected");
1433         p2 = p2_2;
1434         memset(p2_2, 0x11, talloc_get_size(p2_2));
1435
1436         /* now we malloc and free the full pool space */
1437         p2_2 = talloc_realloc_size(root, p2, 2 * 1024);
1438         torture_assert("pool realloc 2 * 1024", p2_2 != p1, "failed: pointer not expected");
1439         memset(p2_2, 0x11, talloc_get_size(p2_2));
1440
1441 #endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1442
1443         talloc_free(p2_2);
1444
1445         talloc_free(root);
1446
1447         return true;
1448 }
1449
1450 static bool test_pool_nest(void)
1451 {
1452         void *p1, *p2, *p3;
1453         void *e = talloc_new(NULL);
1454
1455         p1 = talloc_pool(NULL, 1024);
1456         torture_assert("talloc_pool", p1 != NULL, "failed");
1457
1458         p2 = talloc_pool(p1, 500);
1459         torture_assert("talloc_pool", p2 != NULL, "failed");
1460
1461         p3 = talloc_size(p2, 10);
1462
1463         talloc_steal(e, p3);
1464
1465         talloc_free(p2);
1466
1467         talloc_free(p3);
1468
1469         talloc_free(p1);
1470
1471         talloc_free(e); /* make ASAN happy */
1472
1473         return true;
1474 }
1475
1476 struct pooled {
1477         char *s1;
1478         char *s2;
1479         char *s3;
1480 };
1481
1482 static bool test_pooled_object(void)
1483 {
1484         struct pooled *p;
1485         const char *s1 = "hello";
1486         const char *s2 = "world";
1487         const char *s3 = "";
1488
1489         p = talloc_pooled_object(NULL, struct pooled, 3,
1490                         strlen(s1)+strlen(s2)+strlen(s3)+3);
1491
1492         if (talloc_get_size(p) != sizeof(struct pooled)) {
1493                 return false;
1494         }
1495
1496         p->s1 = talloc_strdup(p, s1);
1497
1498         TALLOC_FREE(p->s1);
1499         p->s1 = talloc_strdup(p, s2);
1500         TALLOC_FREE(p->s1);
1501
1502         p->s1 = talloc_strdup(p, s1);
1503         p->s2 = talloc_strdup(p, s2);
1504         p->s3 = talloc_strdup(p, s3);
1505
1506         TALLOC_FREE(p);
1507         return true;
1508 }
1509
1510 static bool test_free_ref_null_context(void)
1511 {
1512         void *p1, *p2, *p3;
1513         int ret;
1514
1515         talloc_disable_null_tracking();
1516         p1 = talloc_new(NULL);
1517         p2 = talloc_new(NULL);
1518
1519         p3 = talloc_reference(p2, p1);
1520         torture_assert("reference", p3 == p1, "failed: reference on null");
1521
1522         ret = talloc_free(p1);
1523         torture_assert("ref free with null parent", ret == 0, "failed: free with null parent");
1524         talloc_free(p2);
1525
1526         talloc_enable_null_tracking_no_autofree();
1527         p1 = talloc_new(NULL);
1528         p2 = talloc_new(NULL);
1529
1530         p3 = talloc_reference(p2, p1);
1531         torture_assert("reference", p3 == p1, "failed: reference on null");
1532
1533         ret = talloc_free(p1);
1534         torture_assert("ref free with null tracked parent", ret == 0, "failed: free with null parent");
1535         talloc_free(p2);
1536
1537         return true;
1538 }
1539
1540 static bool test_rusty(void)
1541 {
1542         void *root;
1543         char *p1;
1544
1545         talloc_enable_null_tracking();
1546         root = talloc_new(NULL);
1547         p1 = talloc_strdup(root, "foo");
1548         talloc_increase_ref_count(p1);
1549         talloc_report_full(root, stdout);
1550         talloc_free(root);
1551         CHECK_BLOCKS("null_context", NULL, 2);
1552         talloc_free(p1); /* make ASAN happy */
1553
1554         return true;
1555 }
1556
1557 static bool test_free_children(void)
1558 {
1559         void *root;
1560         char *p1, *p2;
1561         const char *name, *name2;
1562
1563         talloc_enable_null_tracking();
1564         root = talloc_new(NULL);
1565         p1 = talloc_strdup(root, "foo1");
1566         p2 = talloc_strdup(p1, "foo2");
1567         (void)p2;
1568
1569         talloc_set_name(p1, "%s", "testname");
1570         talloc_free_children(p1);
1571         /* check its still a valid talloc ptr */
1572         talloc_get_size(talloc_get_name(p1));
1573         if (strcmp(talloc_get_name(p1), "testname") != 0) {
1574                 return false;
1575         }
1576
1577         talloc_set_name(p1, "%s", "testname");
1578         name = talloc_get_name(p1);
1579         talloc_free_children(p1);
1580         /* check its still a valid talloc ptr */
1581         talloc_get_size(talloc_get_name(p1));
1582         torture_assert("name", name == talloc_get_name(p1), "name ptr changed");
1583         torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname") == 0,
1584                        "wrong name");
1585         CHECK_BLOCKS("name1", p1, 2);
1586
1587         /* note that this does not free the old child name */
1588         talloc_set_name_const(p1, "testname2");
1589         name2 = talloc_get_name(p1);
1590         /* but this does */
1591         talloc_free_children(p1);
1592         (void)name2;
1593         torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname2") == 0,
1594                        "wrong name");
1595         CHECK_BLOCKS("name1", p1, 1);
1596
1597         talloc_report_full(root, stdout);
1598         talloc_free(root);
1599         return true;
1600 }
1601
1602 static bool test_memlimit(void)
1603 {
1604         void *root;
1605         char *l1, *l2, *l3, *l4, *l5, *t;
1606         char *pool;
1607         int i;
1608
1609         printf("test: memlimit\n# MEMORY LIMITS\n");
1610
1611         printf("==== talloc_new(NULL)\n");
1612         root = talloc_new(NULL);
1613
1614         talloc_report_full(root, stdout);
1615
1616         printf("==== talloc_size(root, 2048)\n");
1617         l1 = talloc_size(root, 2048);
1618         torture_assert("memlimit", l1 != NULL,
1619                 "failed: alloc should not fail due to memory limit\n");
1620
1621         talloc_report_full(root, stdout);
1622
1623         printf("==== talloc_free(l1)\n");
1624         talloc_free(l1);
1625
1626         talloc_report_full(root, stdout);
1627
1628         printf("==== talloc_strdup(root, level 1)\n");
1629         l1 = talloc_strdup(root, "level 1");
1630         torture_assert("memlimit", l1 != NULL,
1631                 "failed: alloc should not fail due to memory limit\n");
1632
1633         talloc_report_full(root, stdout);
1634
1635         printf("==== talloc_set_memlimit(l1, 2048)\n");
1636         torture_assert("memlimit", talloc_set_memlimit(l1, 2048) == 0,
1637                 "failed: setting memlimit should never fail\n");
1638
1639         talloc_report_full(root, stdout);
1640
1641         printf("==== talloc_size(root, 2048)\n");
1642         l2 = talloc_size(l1, 2048);
1643         torture_assert("memlimit", l2 == NULL,
1644                 "failed: alloc should fail due to memory limit\n");
1645
1646         talloc_report_full(root, stdout);
1647
1648         printf("==== talloc_strdup(l1, level 2)\n");
1649         l2 = talloc_strdup(l1, "level 2");
1650         torture_assert("memlimit", l2 != NULL,
1651                 "failed: alloc should not fail due to memory limit\n");
1652
1653         talloc_report_full(root, stdout);
1654
1655         printf("==== talloc_free(l2)\n");
1656         talloc_free(l2);
1657
1658         talloc_report_full(root, stdout);
1659
1660         printf("==== talloc_size(NULL, 2048)\n");
1661         l2 = talloc_size(NULL, 2048);
1662
1663         talloc_report_full(root, stdout);
1664
1665         printf("==== talloc_steal(l1, l2)\n");
1666         talloc_steal(l1, l2);
1667
1668         talloc_report_full(root, stdout);
1669
1670         printf("==== talloc_strdup(l2, level 3)\n");
1671         l3 = talloc_strdup(l2, "level 3");
1672         torture_assert("memlimit", l3 == NULL,
1673                 "failed: alloc should fail due to memory limit\n");
1674
1675         talloc_report_full(root, stdout);
1676
1677         printf("==== talloc_free(l2)\n");
1678         talloc_free(l2);
1679
1680         talloc_report_full(root, stdout);
1681
1682         printf("==== talloc_strdup(NULL, level 2)\n");
1683         l2 = talloc_strdup(NULL, "level 2");
1684         talloc_steal(l1, l2);
1685
1686         talloc_report_full(root, stdout);
1687
1688         printf("==== talloc_strdup(l2, level 3)\n");
1689         l3 = talloc_strdup(l2, "level 3");
1690         torture_assert("memlimit", l3 != NULL,
1691                 "failed: alloc should not fail due to memory limit\n");
1692
1693         talloc_report_full(root, stdout);
1694
1695         printf("==== talloc_set_memlimit(l3, 1024)\n");
1696         torture_assert("memlimit", talloc_set_memlimit(l3, 1024) == 0,
1697                 "failed: setting memlimit should never fail\n");
1698
1699         talloc_report_full(root, stdout);
1700
1701         printf("==== talloc_strdup(l3, level 4)\n");
1702         l4 = talloc_strdup(l3, "level 4");
1703         torture_assert("memlimit", l4 != NULL,
1704                 "failed: alloc should not fail due to memory limit\n");
1705
1706         talloc_report_full(root, stdout);
1707
1708         printf("==== talloc_set_memlimit(l4, 512)\n");
1709         torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0,
1710                 "failed: setting memlimit should never fail\n");
1711
1712         talloc_report_full(root, stdout);
1713
1714         printf("==== talloc_strdup(l4, level 5)\n");
1715         l5 = talloc_strdup(l4, "level 5");
1716         torture_assert("memlimit", l5 != NULL,
1717                 "failed: alloc should not fail due to memory limit\n");
1718
1719         talloc_report_full(root, stdout);
1720
1721         printf("==== talloc_realloc(NULL, l5, char, 600)\n");
1722         t = talloc_realloc(NULL, l5, char, 600);
1723         torture_assert("memlimit", t == NULL,
1724                 "failed: alloc should fail due to memory limit\n");
1725
1726         talloc_report_full(root, stdout);
1727
1728         printf("==== talloc_realloc(NULL, l5, char, 5)\n");
1729         l5 = talloc_realloc(NULL, l5, char, 5);
1730         torture_assert("memlimit", l5 != NULL,
1731                 "failed: alloc should not fail due to memory limit\n");
1732
1733         talloc_report_full(root, stdout);
1734
1735         printf("==== talloc_strdup(l3, level 4)\n");
1736         l4 = talloc_strdup(l3, "level 4");
1737         torture_assert("memlimit", l4 != NULL,
1738                 "failed: alloc should not fail due to memory limit\n");
1739
1740         talloc_report_full(root, stdout);
1741
1742         printf("==== talloc_set_memlimit(l4, 512)\n");
1743         torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0,
1744                 "failed: setting memlimit should never fail\n");
1745
1746         talloc_report_full(root, stdout);
1747
1748         printf("==== talloc_strdup(l4, level 5)\n");
1749         l5 = talloc_strdup(l4, "level 5");
1750         torture_assert("memlimit", l5 != NULL,
1751                 "failed: alloc should not fail due to memory limit\n");
1752
1753         talloc_report_full(root, stdout);
1754
1755         printf("==== Make new temp context and steal l5\n");
1756         t = talloc_new(root);
1757         talloc_steal(t, l5);
1758
1759         talloc_report_full(root, stdout);
1760
1761         printf("==== talloc_size(t, 2048)\n");
1762         l1 = talloc_size(t, 2048);
1763         torture_assert("memlimit", l1 != NULL,
1764                 "failed: alloc should not fail due to memory limit\n");
1765
1766         talloc_report_full(root, stdout);
1767         talloc_free(root);
1768
1769         /* Test memlimits with pools. */
1770         printf("==== talloc_pool(NULL, 10*1024)\n");
1771         pool = talloc_pool(NULL, 10*1024);
1772         torture_assert("memlimit", pool != NULL,
1773                 "failed: alloc should not fail due to memory limit\n");
1774
1775         printf("==== talloc_set_memlimit(pool, 10*1024)\n");
1776         talloc_set_memlimit(pool, 10*1024);
1777         for (i = 0; i < 9; i++) {
1778                 printf("==== talloc_size(pool, 1024) %i/10\n", i + 1);
1779                 l1 = talloc_size(pool, 1024);
1780                 torture_assert("memlimit", l1 != NULL,
1781                         "failed: alloc should not fail due to memory limit\n");
1782                 talloc_report_full(pool, stdout);
1783         }
1784         /* The next alloc should fail. */
1785         printf("==== talloc_size(pool, 1024) 10/10\n");
1786         l2 = talloc_size(pool, 1024);
1787         torture_assert("memlimit", l2 == NULL,
1788                         "failed: alloc should fail due to memory limit\n");
1789
1790         talloc_report_full(pool, stdout);
1791
1792         /* Moving one of the children shouldn't change the limit,
1793            as it's still inside the pool. */
1794
1795         printf("==== talloc_new(NULL)\n");
1796         root = talloc_new(NULL);
1797
1798         printf("==== talloc_steal(root, l1)\n");
1799         talloc_steal(root, l1);
1800
1801         printf("==== talloc_size(pool, 1024)\n");
1802         l2 = talloc_size(pool, 1024);
1803         torture_assert("memlimit", l2 == NULL,
1804                         "failed: alloc should fail due to memory limit\n");
1805
1806         printf("==== talloc_free_children(pool)\n");
1807         talloc_free(l1);
1808         talloc_free_children(pool);
1809
1810         printf("==== talloc_size(pool, 1024)\n");
1811         l1 = talloc_size(pool, 1024);
1812
1813         /* try reallocs of increasing size */
1814         for (i = 1; i < 9; i++) {
1815                 printf("==== talloc_realloc_size(NULL, l1, %i*1024) %i/10\n", i, i + 1);
1816                 l1 = talloc_realloc_size(NULL, l1, i*1024);
1817                 torture_assert("memlimit", l1 != NULL,
1818                         "failed: realloc should not fail due to memory limit\n");
1819                 talloc_report_full(pool, stdout);
1820         }
1821         /* The next alloc should fail. */
1822         printf("==== talloc_realloc_size(NULL, l1, 10*1024) 10/10\n");
1823         l2 = talloc_realloc_size(NULL, l1, 10*1024);
1824         torture_assert("memlimit", l2 == NULL,
1825                         "failed: realloc should fail due to memory limit\n");
1826
1827         /* Increase the memlimit */
1828         printf("==== talloc_set_memlimit(pool, 11*1024)\n");
1829         talloc_set_memlimit(pool, 11*1024);
1830
1831         /* The final realloc should still fail
1832            as the entire realloced chunk needs to be moved out of the pool */
1833         printf("==== talloc_realloc_size(NULL, l1, 10*1024) 10/10\n");
1834         l2 = talloc_realloc_size(NULL, l1, 10*1024);
1835         torture_assert("memlimit", l2 == NULL,
1836                         "failed: realloc should fail due to memory limit\n");
1837
1838         talloc_report_full(pool, stdout);
1839
1840         printf("==== talloc_set_memlimit(pool, 21*1024)\n");
1841         talloc_set_memlimit(pool, 21*1024);
1842
1843         /* There's now sufficient space to move the chunk out of the pool */
1844         printf("==== talloc_realloc_size(NULL, l1, 10*1024) 10/10\n");
1845         l2 = talloc_realloc_size(NULL, l1, 10*1024);
1846         torture_assert("memlimit", l2 != NULL,
1847                         "failed: realloc should not fail due to memory limit\n");
1848
1849         talloc_report_full(pool, stdout);
1850
1851         /* ...which should mean smaller allocations can now occur within the pool */
1852         printf("==== talloc_size(pool, 9*1024)\n");
1853         l1 = talloc_size(pool, 9*1024);
1854         torture_assert("memlimit", l1 != NULL,
1855                         "failed: new allocations should be allowed in the pool\n");
1856
1857         talloc_report_full(pool, stdout);
1858
1859         /* But reallocs bigger than the pool will still fail */
1860         printf("==== talloc_realloc_size(NULL, l1, 10*1024)\n");
1861         l2 = talloc_realloc_size(NULL, l1, 10*1024);
1862         torture_assert("memlimit", l2 == NULL,
1863                         "failed: realloc should fail due to memory limit\n");
1864
1865         talloc_report_full(pool, stdout);
1866
1867         /* ..as well as allocs */
1868         printf("==== talloc_size(pool, 1024)\n");
1869         l1 = talloc_size(pool, 1024);
1870         torture_assert("memlimit", l1 == NULL,
1871                         "failed: alloc should fail due to memory limit\n");
1872
1873         talloc_report_full(pool, stdout);
1874
1875         printf("==== talloc_free_children(pool)\n");
1876         talloc_free_children(pool);
1877
1878         printf("==== talloc_set_memlimit(pool, 1024)\n");
1879         talloc_set_memlimit(pool, 1024);
1880
1881         /* We should still be able to allocate up to the pool limit
1882            because the memlimit only applies to new heap allocations */
1883         printf("==== talloc_size(pool, 9*1024)\n");
1884         l1 = talloc_size(pool, 9*1024);
1885         torture_assert("memlimit", l1 != NULL,
1886                         "failed: alloc should not fail due to memory limit\n");
1887
1888         talloc_report_full(pool, stdout);
1889
1890         l1 = talloc_size(pool, 1024);
1891         torture_assert("memlimit", l1 == NULL,
1892                         "failed: alloc should fail due to memory limit\n");
1893
1894         talloc_report_full(pool, stdout);
1895
1896         printf("==== talloc_free_children(pool)\n");
1897         talloc_free_children(pool);
1898
1899         printf("==== talloc_set_memlimit(pool, 10*1024)\n");
1900         talloc_set_memlimit(pool, 10*1024);
1901
1902         printf("==== talloc_size(pool, 1024)\n");
1903         l1 = talloc_size(pool, 1024);
1904         torture_assert("memlimit", l1 != NULL,
1905                         "failed: alloc should not fail due to memory limit\n");
1906
1907         talloc_report_full(pool, stdout);
1908
1909         talloc_free(pool);
1910         talloc_free(root);
1911         printf("success: memlimit\n");
1912
1913         return true;
1914 }
1915
1916 #ifdef HAVE_PTHREAD
1917
1918 #define NUM_THREADS 100
1919
1920 /* Sync variables. */
1921 static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
1922 static pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;
1923 static void *intermediate_ptr;
1924
1925 /* Subthread. */
1926 static void *thread_fn(void *arg)
1927 {
1928         int ret;
1929         const char *ctx_name = (const char *)arg;
1930         void *sub_ctx = NULL;
1931         /*
1932          * Do stuff that creates a new talloc hierarchy in
1933          * this thread.
1934          */
1935         void *top_ctx = talloc_named_const(NULL, 0, "top");
1936         if (top_ctx == NULL) {
1937                 return NULL;
1938         }
1939         sub_ctx = talloc_named_const(top_ctx, 100, ctx_name);
1940         if (sub_ctx == NULL) {
1941                 return NULL;
1942         }
1943
1944         /*
1945          * Now transfer a pointer from our hierarchy
1946          * onto the intermediate ptr.
1947          */
1948         ret = pthread_mutex_lock(&mtx);
1949         if (ret != 0) {
1950                 talloc_free(top_ctx);
1951                 return NULL;
1952         }
1953         /* Wait for intermediate_ptr to be free. */
1954         while (intermediate_ptr != NULL) {
1955                 ret = pthread_cond_wait(&condvar, &mtx);
1956                 if (ret != 0) {
1957                         talloc_free(top_ctx);
1958                         ret = pthread_mutex_unlock(&mtx);
1959                         assert(ret == 0);
1960                         return NULL;
1961                 }
1962         }
1963
1964         /* and move our memory onto it from our toplevel hierarchy. */
1965         intermediate_ptr = talloc_move(NULL, &sub_ctx);
1966
1967         /* Tell the main thread it's ready for pickup. */
1968         pthread_cond_broadcast(&condvar);
1969         ret = pthread_mutex_unlock(&mtx);
1970         assert(ret == 0);
1971
1972         talloc_free(top_ctx);
1973         return NULL;
1974 }
1975
1976 /* Main thread. */
1977 static bool test_pthread_talloc_passing(void)
1978 {
1979         int i;
1980         int ret;
1981         char str_array[NUM_THREADS][20];
1982         pthread_t thread_id;
1983         void *mem_ctx;
1984
1985         /*
1986          * Important ! Null tracking breaks threaded talloc.
1987          * It *must* be turned off.
1988          */
1989         talloc_disable_null_tracking();
1990
1991         printf("test: pthread_talloc_passing\n# PTHREAD TALLOC PASSING\n");
1992
1993         /* Main thread toplevel context. */
1994         mem_ctx = talloc_named_const(NULL, 0, "toplevel");
1995         if (mem_ctx == NULL) {
1996                 printf("failed to create toplevel context\n");
1997                 return false;
1998         }
1999
2000         /*
2001          * Spin off NUM_THREADS threads.
2002          * They will use their own toplevel contexts.
2003          */
2004         for (i = 0; i < NUM_THREADS; i++) {
2005                 ret = snprintf(str_array[i],
2006                                20,
2007                                "thread:%d",
2008                                i);
2009                 if (ret < 0) {
2010                         printf("snprintf %d failed\n", i);
2011                         return false;
2012                 }
2013                 ret = pthread_create(&thread_id,
2014                                 NULL,
2015                                 thread_fn,
2016                                 str_array[i]);
2017                 if (ret != 0) {
2018                         printf("failed to create thread %d (%d)\n", i, ret);
2019                         return false;
2020                 }
2021         }
2022
2023         printf("Created %d threads\n", NUM_THREADS);
2024
2025         /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */
2026         for (i = 0; i < NUM_THREADS; i++) {
2027                 ret = pthread_mutex_lock(&mtx);
2028                 if (ret != 0) {
2029                         printf("pthread_mutex_lock %d failed (%d)\n", i, ret);
2030                         talloc_free(mem_ctx);
2031                         return false;
2032                 }
2033
2034                 /* Wait for intermediate_ptr to have our data. */
2035                 while (intermediate_ptr == NULL) {
2036                         ret = pthread_cond_wait(&condvar, &mtx);
2037                         if (ret != 0) {
2038                                 printf("pthread_cond_wait %d failed (%d)\n", i,
2039                                         ret);
2040                                 talloc_free(mem_ctx);
2041                                 ret = pthread_mutex_unlock(&mtx);
2042                                 assert(ret == 0);
2043                         }
2044                 }
2045
2046                 /* and move it onto our toplevel hierarchy. */
2047                 (void)talloc_move(mem_ctx, &intermediate_ptr);
2048
2049                 /* Tell the sub-threads we're ready for another. */
2050                 pthread_cond_broadcast(&condvar);
2051                 ret = pthread_mutex_unlock(&mtx);
2052                 assert(ret == 0);
2053         }
2054
2055         CHECK_SIZE("pthread_talloc_passing", mem_ctx, NUM_THREADS * 100);
2056 #if 1
2057         /* Dump the hierarchy. */
2058         talloc_report(mem_ctx, stdout);
2059 #endif
2060         talloc_free(mem_ctx);
2061         printf("success: pthread_talloc_passing\n");
2062         return true;
2063 }
2064 #endif
2065
2066 static void test_magic_protection_abort(const char *reason)
2067 {
2068         /* exit with errcode 42 to communicate successful test to the parent process */
2069         if (strcmp(reason, "Bad talloc magic value - unknown value") == 0) {
2070                 _exit(42);
2071         } else {
2072                 printf("talloc aborted for an unexpected reason\n");
2073         }
2074 }
2075
2076 static int test_magic_protection_destructor(int *ptr)
2077 {
2078         _exit(404); /* Not 42 */
2079 }
2080
2081 static bool test_magic_protection(void)
2082 {
2083         void *pool = talloc_pool(NULL, 1024);
2084         int *p1, *p2;
2085         pid_t pid;
2086         int exit_status;
2087
2088         printf("test: magic_protection\n");
2089         p1 = talloc(pool, int);
2090         p2 = talloc(pool, int);
2091
2092         /* To avoid complaints from the compiler assign values to the p1 & p2. */
2093         *p1 = 6;
2094         *p2 = 9;
2095
2096         pid = fork();
2097         if (pid == 0) {
2098                 talloc_set_abort_fn(test_magic_protection_abort);
2099                 talloc_set_destructor(p2, test_magic_protection_destructor);
2100
2101                 /*
2102                  * Simulate a security attack
2103                  * by triggering a buffer overflow in memset to overwrite the
2104                  * constructor in the next pool chunk.
2105                  *
2106                  * Real attacks would attempt to set a real destructor.
2107                  */
2108                 memset(p1, '\0', 32);
2109
2110                 /* Then the attack takes effect when the memory's freed. */
2111                 talloc_free(pool);
2112
2113                 /* Never reached. Make compilers happy */
2114                 return true;
2115         }
2116
2117         while (wait(&exit_status) != pid);
2118
2119         talloc_free(pool); /* make ASAN happy */
2120
2121         if (!WIFEXITED(exit_status)) {
2122                 printf("Child exited through unexpected abnormal means\n");
2123                 return false;
2124         }
2125         if (WEXITSTATUS(exit_status) != 42) {
2126                 printf("Child exited with wrong exit status\n");
2127                 return false;
2128         }
2129         if (WIFSIGNALED(exit_status)) {
2130                 printf("Child received unexpected signal\n");
2131                 return false;
2132         }
2133
2134         printf("success: magic_protection\n");
2135         return true;
2136 }
2137
2138 static void test_magic_free_protection_abort(const char *reason)
2139 {
2140         /* exit with errcode 42 to communicate successful test to the parent process */
2141         if (strcmp(reason, "Bad talloc magic value - access after free") == 0) {
2142                 _exit(42);
2143         }
2144         /* not 42 */
2145         _exit(404);
2146 }
2147
2148 static bool test_magic_free_protection(void)
2149 {
2150         void *pool = talloc_pool(NULL, 1024);
2151         int *p1, *p2, *p3;
2152         pid_t pid;
2153         int exit_status;
2154
2155         printf("test: magic_free_protection\n");
2156         p1 = talloc(pool, int);
2157         p2 = talloc(pool, int);
2158
2159         /* To avoid complaints from the compiler assign values to the p1 & p2. */
2160         *p1 = 6;
2161         *p2 = 9;
2162
2163         p3 = talloc_realloc(pool, p2, int, 2048);
2164         torture_assert("pool realloc 2048",
2165                        p3 != p2,
2166                        "failed: pointer not changed");
2167
2168         /*
2169          * Now access the memory in the pool after the realloc().  It
2170          * should be marked as free, so use of the old pointer should
2171          * trigger the abort function
2172          */
2173         pid = fork();
2174         if (pid == 0) {
2175                 talloc_set_abort_fn(test_magic_free_protection_abort);
2176
2177                 talloc_get_name(p2);
2178
2179                 /* Never reached. Make compilers happy */
2180                 return true;
2181         }
2182
2183         while (wait(&exit_status) != pid);
2184
2185         if (!WIFEXITED(exit_status)) {
2186                 printf("Child exited through unexpected abnormal means\n");
2187                 return false;
2188         }
2189         if (WEXITSTATUS(exit_status) != 42) {
2190                 printf("Child exited with wrong exit status\n");
2191                 return false;
2192         }
2193         if (WIFSIGNALED(exit_status)) {
2194                 printf("Child received unexpected signal\n");
2195                 return false;
2196         }
2197
2198         talloc_free(pool);
2199
2200         printf("success: magic_free_protection\n");
2201         return true;
2202 }
2203
2204 static void test_reset(void)
2205 {
2206         talloc_set_log_fn(test_log_stdout);
2207         test_abort_stop();
2208         talloc_disable_null_tracking();
2209         talloc_enable_null_tracking_no_autofree();
2210 }
2211
2212 bool torture_local_talloc(struct torture_context *tctx)
2213 {
2214         bool ret = true;
2215
2216         setlinebuf(stdout);
2217
2218         test_reset();
2219         ret &= test_pooled_object();
2220         test_reset();
2221         ret &= test_pool_nest();
2222         test_reset();
2223         ret &= test_ref1();
2224         test_reset();
2225         ret &= test_ref2();
2226         test_reset();
2227         ret &= test_ref3();
2228         test_reset();
2229         ret &= test_ref4();
2230         test_reset();
2231         ret &= test_unlink1(); 
2232         test_reset();
2233         ret &= test_misc();
2234         test_reset();
2235         ret &= test_realloc();
2236         test_reset();
2237         ret &= test_realloc_child(); 
2238         test_reset();
2239         ret &= test_steal(); 
2240         test_reset();
2241         ret &= test_move(); 
2242         test_reset();
2243         ret &= test_unref_reparent();
2244         test_reset();
2245         ret &= test_realloc_fn(); 
2246         test_reset();
2247         ret &= test_type();
2248         test_reset();
2249         ret &= test_lifeless(); 
2250         test_reset();
2251         ret &= test_loop();
2252         test_reset();
2253         ret &= test_free_parent_deny_child(); 
2254         test_reset();
2255         ret &= test_realloc_on_destructor_parent();
2256         test_reset();
2257         ret &= test_free_parent_reparent_child();
2258         test_reset();
2259         ret &= test_free_parent_reparent_child_in_pool();
2260         test_reset();
2261         ret &= test_talloc_ptrtype();
2262         test_reset();
2263         ret &= test_talloc_free_in_destructor();
2264         test_reset();
2265         ret &= test_pool();
2266         test_reset();
2267         ret &= test_pool_steal();
2268         test_reset();
2269         ret &= test_free_ref_null_context();
2270         test_reset();
2271         ret &= test_rusty();
2272         test_reset();
2273         ret &= test_free_children();
2274         test_reset();
2275         ret &= test_memlimit();
2276 #ifdef HAVE_PTHREAD
2277         test_reset();
2278         ret &= test_pthread_talloc_passing();
2279 #endif
2280
2281
2282         if (ret) {
2283                 test_reset();
2284                 ret &= test_speed();
2285         }
2286         test_reset();
2287         ret &= test_autofree();
2288         test_reset();
2289         ret &= test_magic_protection();
2290         test_reset();
2291         ret &= test_magic_free_protection();
2292
2293         test_reset();
2294         talloc_disable_null_tracking();
2295         return ret;
2296 }