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