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
private_timeval_current(void)45 static struct timeval private_timeval_current(void)
46 {
47 struct timeval tv;
48 gettimeofday(&tv, NULL);
49 return tv;
50 }
51
private_timeval_elapsed(struct timeval * tv)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
test_abort_stop(void)126 static void test_abort_stop(void)
127 {
128 test_abort_count = 0;
129 talloc_set_abort_fn(NULL);
130 }
131
test_log_stdout(const char * message)132 static void test_log_stdout(const char *message)
133 {
134 fprintf(stdout, "%s", message);
135 }
136
137 /*
138 test references
139 */
test_ref1(void)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 */
test_ref2(void)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 */
test_ref3(void)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 */
test_ref4(void)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 */
test_unlink1(void)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
fail_destructor(void * ptr)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 */
test_misc(void)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 */
test_realloc(void)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 */
test_realloc_child(void)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 */
test_type(void)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 */
test_steal(void)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 */
test_move(void)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 */
test_realloc_fn(void)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
test_unref_reparent(void)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 */
test_speed(void)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
test_lifeless(void)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
test_loop_destructor(char * ptr)954 static int test_loop_destructor(char *ptr)
955 {
956 loop_destructor_count++;
957 return 0;
958 }
959
test_loop(void)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
test_realloc_parent_destructor(char * ptr)992 static int test_realloc_parent_destructor(char *ptr)
993 {
994 realloc_parent_destructor_count++;
995 return 0;
996 }
997
test_realloc_on_destructor_parent(void)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
fail_destructor_str(char * ptr)1043 static int fail_destructor_str(char *ptr)
1044 {
1045 return -1;
1046 }
1047
test_free_parent_deny_child(void)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
reparenting_destructor(struct new_parent * np)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
test_free_parent_reparent_child(void)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
test_free_parent_reparent_child_in_pool(void)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
test_talloc_ptrtype(void)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
_test_talloc_free_in_destructor(void ** ptr)1234 static int _test_talloc_free_in_destructor(void **ptr)
1235 {
1236 talloc_free(*ptr);
1237 return 0;
1238 }
1239
test_talloc_free_in_destructor(void)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
test_autofree(void)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
test_pool(void)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
test_pool_steal(void)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
test_pool_nest(void)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
test_pooled_object(void)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
test_free_ref_null_context(void)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
test_rusty(void)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
test_free_children(void)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
test_memlimit(void)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 pool = talloc_pool(NULL, 10*1024);
1771 torture_assert("memlimit", pool != NULL,
1772 "failed: alloc should not fail due to memory limit\n");
1773 talloc_set_memlimit(pool, 10*1024);
1774 for (i = 0; i < 9; i++) {
1775 l1 = talloc_size(pool, 1024);
1776 torture_assert("memlimit", l1 != NULL,
1777 "failed: alloc should not fail due to memory limit\n");
1778 }
1779 /* The next alloc should fail. */
1780 l2 = talloc_size(pool, 1024);
1781 torture_assert("memlimit", l2 == NULL,
1782 "failed: alloc should fail due to memory limit\n");
1783
1784 /* Moving one of the children shouldn't change the limit,
1785 as it's still inside the pool. */
1786 root = talloc_new(NULL);
1787 talloc_steal(root, l1);
1788 l2 = talloc_size(pool, 1024);
1789 torture_assert("memlimit", l2 == NULL,
1790 "failed: alloc should fail due to memory limit\n");
1791
1792 talloc_free(pool);
1793 talloc_free(root);
1794 printf("success: memlimit\n");
1795
1796 return true;
1797 }
1798
1799 #ifdef HAVE_PTHREAD
1800
1801 #define NUM_THREADS 100
1802
1803 /* Sync variables. */
1804 static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
1805 static pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;
1806 static void *intermediate_ptr;
1807
1808 /* Subthread. */
thread_fn(void * arg)1809 static void *thread_fn(void *arg)
1810 {
1811 int ret;
1812 const char *ctx_name = (const char *)arg;
1813 void *sub_ctx = NULL;
1814 /*
1815 * Do stuff that creates a new talloc hierarchy in
1816 * this thread.
1817 */
1818 void *top_ctx = talloc_named_const(NULL, 0, "top");
1819 if (top_ctx == NULL) {
1820 return NULL;
1821 }
1822 sub_ctx = talloc_named_const(top_ctx, 100, ctx_name);
1823 if (sub_ctx == NULL) {
1824 return NULL;
1825 }
1826
1827 /*
1828 * Now transfer a pointer from our hierarchy
1829 * onto the intermediate ptr.
1830 */
1831 ret = pthread_mutex_lock(&mtx);
1832 if (ret != 0) {
1833 talloc_free(top_ctx);
1834 return NULL;
1835 }
1836 /* Wait for intermediate_ptr to be free. */
1837 while (intermediate_ptr != NULL) {
1838 ret = pthread_cond_wait(&condvar, &mtx);
1839 if (ret != 0) {
1840 talloc_free(top_ctx);
1841 ret = pthread_mutex_unlock(&mtx);
1842 assert(ret == 0);
1843 return NULL;
1844 }
1845 }
1846
1847 /* and move our memory onto it from our toplevel hierarchy. */
1848 intermediate_ptr = talloc_move(NULL, &sub_ctx);
1849
1850 /* Tell the main thread it's ready for pickup. */
1851 pthread_cond_broadcast(&condvar);
1852 ret = pthread_mutex_unlock(&mtx);
1853 assert(ret == 0);
1854
1855 talloc_free(top_ctx);
1856 return NULL;
1857 }
1858
1859 /* Main thread. */
test_pthread_talloc_passing(void)1860 static bool test_pthread_talloc_passing(void)
1861 {
1862 int i;
1863 int ret;
1864 char str_array[NUM_THREADS][20];
1865 pthread_t thread_id;
1866 void *mem_ctx;
1867
1868 /*
1869 * Important ! Null tracking breaks threaded talloc.
1870 * It *must* be turned off.
1871 */
1872 talloc_disable_null_tracking();
1873
1874 printf("test: pthread_talloc_passing\n# PTHREAD TALLOC PASSING\n");
1875
1876 /* Main thread toplevel context. */
1877 mem_ctx = talloc_named_const(NULL, 0, "toplevel");
1878 if (mem_ctx == NULL) {
1879 printf("failed to create toplevel context\n");
1880 return false;
1881 }
1882
1883 /*
1884 * Spin off NUM_THREADS threads.
1885 * They will use their own toplevel contexts.
1886 */
1887 for (i = 0; i < NUM_THREADS; i++) {
1888 ret = snprintf(str_array[i],
1889 20,
1890 "thread:%d",
1891 i);
1892 if (ret < 0) {
1893 printf("snprintf %d failed\n", i);
1894 return false;
1895 }
1896 ret = pthread_create(&thread_id,
1897 NULL,
1898 thread_fn,
1899 str_array[i]);
1900 if (ret != 0) {
1901 printf("failed to create thread %d (%d)\n", i, ret);
1902 return false;
1903 }
1904 }
1905
1906 printf("Created %d threads\n", NUM_THREADS);
1907
1908 /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */
1909 for (i = 0; i < NUM_THREADS; i++) {
1910 ret = pthread_mutex_lock(&mtx);
1911 if (ret != 0) {
1912 printf("pthread_mutex_lock %d failed (%d)\n", i, ret);
1913 talloc_free(mem_ctx);
1914 return false;
1915 }
1916
1917 /* Wait for intermediate_ptr to have our data. */
1918 while (intermediate_ptr == NULL) {
1919 ret = pthread_cond_wait(&condvar, &mtx);
1920 if (ret != 0) {
1921 printf("pthread_cond_wait %d failed (%d)\n", i,
1922 ret);
1923 talloc_free(mem_ctx);
1924 ret = pthread_mutex_unlock(&mtx);
1925 assert(ret == 0);
1926 }
1927 }
1928
1929 /* and move it onto our toplevel hierarchy. */
1930 (void)talloc_move(mem_ctx, &intermediate_ptr);
1931
1932 /* Tell the sub-threads we're ready for another. */
1933 pthread_cond_broadcast(&condvar);
1934 ret = pthread_mutex_unlock(&mtx);
1935 assert(ret == 0);
1936 }
1937
1938 CHECK_SIZE("pthread_talloc_passing", mem_ctx, NUM_THREADS * 100);
1939 #if 1
1940 /* Dump the hierarchy. */
1941 talloc_report(mem_ctx, stdout);
1942 #endif
1943 talloc_free(mem_ctx);
1944 printf("success: pthread_talloc_passing\n");
1945 return true;
1946 }
1947 #endif
1948
test_magic_protection_abort(const char * reason)1949 static void test_magic_protection_abort(const char *reason)
1950 {
1951 /* exit with errcode 42 to communicate successful test to the parent process */
1952 if (strcmp(reason, "Bad talloc magic value - unknown value") == 0) {
1953 _exit(42);
1954 } else {
1955 printf("talloc aborted for an unexpected reason\n");
1956 }
1957 }
1958
test_magic_protection_destructor(int * ptr)1959 static int test_magic_protection_destructor(int *ptr)
1960 {
1961 _exit(404); /* Not 42 */
1962 }
1963
test_magic_protection(void)1964 static bool test_magic_protection(void)
1965 {
1966 void *pool = talloc_pool(NULL, 1024);
1967 int *p1, *p2;
1968 pid_t pid;
1969 int exit_status;
1970
1971 printf("test: magic_protection\n");
1972 p1 = talloc(pool, int);
1973 p2 = talloc(pool, int);
1974
1975 /* To avoid complaints from the compiler assign values to the p1 & p2. */
1976 *p1 = 6;
1977 *p2 = 9;
1978
1979 pid = fork();
1980 if (pid == 0) {
1981 talloc_set_abort_fn(test_magic_protection_abort);
1982 talloc_set_destructor(p2, test_magic_protection_destructor);
1983
1984 /*
1985 * Simulate a security attack
1986 * by triggering a buffer overflow in memset to overwrite the
1987 * constructor in the next pool chunk.
1988 *
1989 * Real attacks would attempt to set a real destructor.
1990 */
1991 memset(p1, '\0', 32);
1992
1993 /* Then the attack takes effect when the memory's freed. */
1994 talloc_free(pool);
1995
1996 /* Never reached. Make compilers happy */
1997 return true;
1998 }
1999
2000 while (wait(&exit_status) != pid);
2001
2002 talloc_free(pool); /* make ASAN happy */
2003
2004 if (!WIFEXITED(exit_status)) {
2005 printf("Child exited through unexpected abnormal means\n");
2006 return false;
2007 }
2008 if (WEXITSTATUS(exit_status) != 42) {
2009 printf("Child exited with wrong exit status\n");
2010 return false;
2011 }
2012 if (WIFSIGNALED(exit_status)) {
2013 printf("Child received unexpected signal\n");
2014 return false;
2015 }
2016
2017 printf("success: magic_protection\n");
2018 return true;
2019 }
2020
test_magic_free_protection_abort(const char * reason)2021 static void test_magic_free_protection_abort(const char *reason)
2022 {
2023 /* exit with errcode 42 to communicate successful test to the parent process */
2024 if (strcmp(reason, "Bad talloc magic value - access after free") == 0) {
2025 _exit(42);
2026 }
2027 /* not 42 */
2028 _exit(404);
2029 }
2030
test_magic_free_protection(void)2031 static bool test_magic_free_protection(void)
2032 {
2033 void *pool = talloc_pool(NULL, 1024);
2034 int *p1, *p2, *p3;
2035 pid_t pid;
2036 int exit_status;
2037
2038 printf("test: magic_free_protection\n");
2039 p1 = talloc(pool, int);
2040 p2 = talloc(pool, int);
2041
2042 /* To avoid complaints from the compiler assign values to the p1 & p2. */
2043 *p1 = 6;
2044 *p2 = 9;
2045
2046 p3 = talloc_realloc(pool, p2, int, 2048);
2047 torture_assert("pool realloc 2048",
2048 p3 != p2,
2049 "failed: pointer not changed");
2050
2051 /*
2052 * Now access the memory in the pool after the realloc(). It
2053 * should be marked as free, so use of the old pointer should
2054 * trigger the abort function
2055 */
2056 pid = fork();
2057 if (pid == 0) {
2058 talloc_set_abort_fn(test_magic_free_protection_abort);
2059
2060 talloc_get_name(p2);
2061
2062 /* Never reached. Make compilers happy */
2063 return true;
2064 }
2065
2066 while (wait(&exit_status) != pid);
2067
2068 if (!WIFEXITED(exit_status)) {
2069 printf("Child exited through unexpected abnormal means\n");
2070 return false;
2071 }
2072 if (WEXITSTATUS(exit_status) != 42) {
2073 printf("Child exited with wrong exit status\n");
2074 return false;
2075 }
2076 if (WIFSIGNALED(exit_status)) {
2077 printf("Child received unexpected signal\n");
2078 return false;
2079 }
2080
2081 talloc_free(pool);
2082
2083 printf("success: magic_free_protection\n");
2084 return true;
2085 }
2086
test_reset(void)2087 static void test_reset(void)
2088 {
2089 talloc_set_log_fn(test_log_stdout);
2090 test_abort_stop();
2091 talloc_disable_null_tracking();
2092 talloc_enable_null_tracking_no_autofree();
2093 }
2094
torture_local_talloc(struct torture_context * tctx)2095 bool torture_local_talloc(struct torture_context *tctx)
2096 {
2097 bool ret = true;
2098
2099 setlinebuf(stdout);
2100
2101 test_reset();
2102 ret &= test_pooled_object();
2103 test_reset();
2104 ret &= test_pool_nest();
2105 test_reset();
2106 ret &= test_ref1();
2107 test_reset();
2108 ret &= test_ref2();
2109 test_reset();
2110 ret &= test_ref3();
2111 test_reset();
2112 ret &= test_ref4();
2113 test_reset();
2114 ret &= test_unlink1();
2115 test_reset();
2116 ret &= test_misc();
2117 test_reset();
2118 ret &= test_realloc();
2119 test_reset();
2120 ret &= test_realloc_child();
2121 test_reset();
2122 ret &= test_steal();
2123 test_reset();
2124 ret &= test_move();
2125 test_reset();
2126 ret &= test_unref_reparent();
2127 test_reset();
2128 ret &= test_realloc_fn();
2129 test_reset();
2130 ret &= test_type();
2131 test_reset();
2132 ret &= test_lifeless();
2133 test_reset();
2134 ret &= test_loop();
2135 test_reset();
2136 ret &= test_free_parent_deny_child();
2137 test_reset();
2138 ret &= test_realloc_on_destructor_parent();
2139 test_reset();
2140 ret &= test_free_parent_reparent_child();
2141 test_reset();
2142 ret &= test_free_parent_reparent_child_in_pool();
2143 test_reset();
2144 ret &= test_talloc_ptrtype();
2145 test_reset();
2146 ret &= test_talloc_free_in_destructor();
2147 test_reset();
2148 ret &= test_pool();
2149 test_reset();
2150 ret &= test_pool_steal();
2151 test_reset();
2152 ret &= test_free_ref_null_context();
2153 test_reset();
2154 ret &= test_rusty();
2155 test_reset();
2156 ret &= test_free_children();
2157 test_reset();
2158 ret &= test_memlimit();
2159 #ifdef HAVE_PTHREAD
2160 test_reset();
2161 ret &= test_pthread_talloc_passing();
2162 #endif
2163
2164
2165 if (ret) {
2166 test_reset();
2167 ret &= test_speed();
2168 }
2169 test_reset();
2170 ret &= test_autofree();
2171 test_reset();
2172 ret &= test_magic_protection();
2173 test_reset();
2174 ret &= test_magic_free_protection();
2175
2176 test_reset();
2177 talloc_disable_null_tracking();
2178 return ret;
2179 }
2180