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