LCOV - code coverage report
Current view: top level - lib/talloc - testsuite.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 1291 1367 94.4 %
Date: 2024-04-21 15:09:00 Functions: 46 50 92.0 %

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

Generated by: LCOV version 1.14