The branch, master has been updated
       via  57a57a189bd lib/torture: assert that a test doesn't create new 
talloc children of context->ev
       via  2099da9d42e lib/torture: use temporary memory for each test/suites
       via  17f815644b3 lib/torture: give torture_context_child() a dedicated 
talloc parent and avoid talloc_reference
       via  d1bdbaa149e lib/torture: extend torture_context_init()
       via  087e6af9d21 s4:rpc_server: don't use event_ctx as talloc parent of 
dcesrv_sock
       via  07c8b79d853 s4:libnet: pass an explicit talloc parent to 
libnet_context_init()
       via  3d2ccb74f55 s4:messaging/tests: correctly teardown imessage contexts
       via  d6ff4cf024f charset/tests: avoid static variables in test_buffer()
       via  ede15e46f13 lib/util: activate panic on dangling talloc stackframes
       via  470ebe77080 s3:pylibsmb: don't use an unbound talloc_stackframe() 
in libsmb_samba_cwrapper()
       via  2cb962fcea2 s3:pylibsmb: add explicit talloc_stackframes to most 
functions
       via  9076ad2a9f6 s3:pylibsmb: fix a few (potential) memory leaks
       via  f00ed1a95e0 s3:pylibsmb: avoid using PyErr_NTSTATUS_NOT_OK_RAISE()
       via  658ddb8ada9 libcli/smb: create explicit talloc stackframe in 
reparse_data_buffer_marshall()
       via  dd5616dc92d lib/util: add pthread support to talloc_stack.c
       via  917ae94cf36 lib/util: add atexit handling and complain about 
dangling frames.
       via  b3a5f9748cf lib/util: remove unused SMB_THREAD handling from 
talloc_stack.c
      from  b6757378be2 s4:torture/smb2: let smb2.bench tests start the loop 
only when everything is ready

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 57a57a189bd9a7348656990b2c888a328b524bb0
Author: Stefan Metzmacher <[email protected]>
Date:   Fri May 9 11:28:44 2025 +0200

    lib/torture: assert that a test doesn't create new talloc children of 
context->ev
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>
    
    Autobuild-User(master): Andreas Schneider <[email protected]>
    Autobuild-Date(master): Mon May 19 10:13:25 UTC 2025 on atb-devel-224

commit 2099da9d42e3eb7ba67faeee3a2a0c9d41694643
Author: Stefan Metzmacher <[email protected]>
Date:   Fri May 9 11:19:47 2025 +0200

    lib/torture: use temporary memory for each test/suites
    
    We use torture_context_child() and tevent_re_initialise() in order
    to run each test with it's own memory and also a cleared event context.
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

commit 17f815644b3c6d7e7be2964eee1ab7fc67a357d9
Author: Stefan Metzmacher <[email protected]>
Date:   Fri May 9 11:18:18 2025 +0200

    lib/torture: give torture_context_child() a dedicated talloc parent and 
avoid talloc_reference
    
    The caller should manage the liftimes.
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

commit d1bdbaa149e37c437e55d965008491a8aa760b38
Author: Stefan Metzmacher <[email protected]>
Date:   Fri May 9 10:41:52 2025 +0200

    lib/torture: extend torture_context_init()
    
    Give it a dedicated talloc parent and avoid
    talloc_references, the caller needs to take care
    that the lifetime of the arguments is longer.
    
    This makes sure any talloc destructors of torture_context
    children run before torture->ev is destroyed.
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

commit 087e6af9d21b052c88c2229c66c61441875e021e
Author: Stefan Metzmacher <[email protected]>
Date:   Fri May 9 14:40:38 2025 +0200

    s4:rpc_server: don't use event_ctx as talloc parent of dcesrv_sock
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

commit 07c8b79d85330ff4ddd29eb1a797fae3f893d96a
Author: Stefan Metzmacher <[email protected]>
Date:   Fri May 9 13:30:36 2025 +0200

    s4:libnet: pass an explicit talloc parent to libnet_context_init()
    
    We should not implicitly use the tevent_context as talloc parent.
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

commit 3d2ccb74f5511c3d4eeb64a117b89600e430a40c
Author: Stefan Metzmacher <[email protected]>
Date:   Mon May 12 17:45:31 2025 +0200

    s4:messaging/tests: correctly teardown imessage contexts
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

commit d6ff4cf024f8411d1113ba2d7ed9c60f6f5c4b70
Author: Stefan Metzmacher <[email protected]>
Date:   Mon May 12 17:42:45 2025 +0200

    charset/tests: avoid static variables in test_buffer()
    
    Add an explicit cache which is destroyed via a talloc
    destructor instead, so we don't leak stale pointers
    in the static variables.
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

commit ede15e46f13211087e7ebb2e1b1e2170739f0d25
Author: Stefan Metzmacher <[email protected]>
Date:   Tue May 13 17:01:22 2025 +0200

    lib/util: activate panic on dangling talloc stackframes
    
    We can do that now as pylibsmb.c doesn't trigger it anymore.
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

commit 470ebe77080911b0491a6e737ef5fbe8309a9848
Author: Stefan Metzmacher <[email protected]>
Date:   Mon May 12 17:53:45 2025 +0200

    s3:pylibsmb: don't use an unbound talloc_stackframe() in 
libsmb_samba_cwrapper()
    
    Code should use there own explicit stackframes.
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

commit 2cb962fcea2e9b64e1c2635b7c38e0a24f8db8cb
Author: Stefan Metzmacher <[email protected]>
Date:   Tue May 13 16:58:14 2025 +0200

    s3:pylibsmb: add explicit talloc_stackframes to most functions
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

commit 9076ad2a9f686beedaa77cae1830ed1fca026be4
Author: Stefan Metzmacher <[email protected]>
Date:   Tue May 13 16:55:02 2025 +0200

    s3:pylibsmb: fix a few (potential) memory leaks
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

commit f00ed1a95e03e45903dcd5cf865cd7733686a911
Author: Stefan Metzmacher <[email protected]>
Date:   Tue May 13 15:36:58 2025 +0200

    s3:pylibsmb: avoid using PyErr_NTSTATUS_NOT_OK_RAISE()
    
    Doing explicit if statements will allow us to do
    memory cleanup on error.
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

commit 658ddb8ada99cd600665626bc08ffacda6b057bc
Author: Stefan Metzmacher <[email protected]>
Date:   Wed May 14 11:24:36 2025 +0200

    libcli/smb: create explicit talloc stackframe in 
reparse_data_buffer_marshall()
    
    This is needed in order to allow helper functions to use talloc_tos().
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

commit dd5616dc92da38f38fc1d6128f762b285ab0167f
Author: Stefan Metzmacher <[email protected]>
Date:   Mon May 12 20:44:46 2025 +0200

    lib/util: add pthread support to talloc_stack.c
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

commit 917ae94cf360479d5fd1e7561fbec2ae31362109
Author: Stefan Metzmacher <[email protected]>
Date:   Mon May 12 20:50:10 2025 +0200

    lib/util: add atexit handling and complain about dangling frames.
    
    We don't panic yet as pylibsmb.c would trigger that...
    This will be fixed in the next commits.
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

commit b3a5f9748cf3d6115a1c65647875b506c4c551fb
Author: Stefan Metzmacher <[email protected]>
Date:   Mon May 12 20:43:08 2025 +0200

    lib/util: remove unused SMB_THREAD handling from talloc_stack.c
    
    This does not support any threads as smb_thread_set_functions()
    is never called anywhere.
    
    We'll add plain pthread handling in the next commit.
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>

-----------------------------------------------------------------------

Summary of changes:
 lib/torture/torture.c                    | 239 +++++++++++++++--
 lib/torture/torture.h                    |   9 +-
 lib/torture/wscript_build                |   2 +-
 lib/util/charset/tests/iconv.c           | 144 ++++++++---
 lib/util/talloc_stack.c                  | 126 ++++++---
 libcli/smb/reparse.c                     |   2 +
 source3/libsmb/pylibsmb.c                | 423 +++++++++++++++++++++++++------
 source4/lib/messaging/tests/irpc.c       |  15 +-
 source4/lib/policy/gp_ldap.c             |   2 +-
 source4/libnet/libnet.c                  |   5 +-
 source4/libnet/py_net.c                  |  10 +-
 source4/rpc_server/dcerpc_server.c       |   8 +-
 source4/torture/libnet/domain.c          |   2 +-
 source4/torture/libnet/libnet_BecomeDC.c |   2 +-
 source4/torture/libnet/libnet_domain.c   |  10 +-
 source4/torture/libnet/libnet_group.c    |   4 +-
 source4/torture/libnet/libnet_lookup.c   |   8 +-
 source4/torture/libnet/libnet_rpc.c      |   2 +-
 source4/torture/libnet/libnet_share.c    |   4 +-
 source4/torture/libnet/libnet_user.c     |   2 +-
 source4/torture/libnet/utils.c           |   2 +-
 source4/torture/rpc/dfs.c                |   4 +-
 source4/torture/rpc/testjoin.c           |   2 +-
 source4/torture/smbtorture.c             |  34 ++-
 24 files changed, 837 insertions(+), 224 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/torture/torture.c b/lib/torture/torture.c
index 41226ef7504..78caaa8c9ba 100644
--- a/lib/torture/torture.c
+++ b/lib/torture/torture.c
@@ -19,6 +19,8 @@
 */
 
 #include "source4/include/includes.h"
+#include <tevent.h>
+#include "../lib/util/talloc_report.h"
 #include "../torture/torture.h"
 #include "../lib/util/dlinklist.h"
 #include "param/param.h"
@@ -42,40 +44,72 @@ struct torture_results *torture_results_init(TALLOC_CTX 
*mem_ctx, const struct t
 /**
  * Initialize a torture context
  */
-struct torture_context *torture_context_init(struct tevent_context *event_ctx, 
-                                                                               
         struct torture_results *results)
+struct torture_context *torture_context_init(TALLOC_CTX *mem_ctx,
+                                            struct tevent_context *event_ctx,
+                                            struct loadparm_context *lp_ctx,
+                                            struct torture_results *results,
+                                            char *outputdir_template)
 {
-       struct torture_context *torture = talloc_zero(event_ctx, 
-                                                     struct torture_context);
+       struct torture_context *torture = NULL;
 
-       if (torture == NULL)
+       SMB_ASSERT(event_ctx);
+       SMB_ASSERT(lp_ctx);
+       SMB_ASSERT(results);
+       SMB_ASSERT(outputdir_template);
+
+       torture = talloc_zero(mem_ctx, struct torture_context);
+       if (torture == NULL) {
                return NULL;
+       }
 
        torture->ev = event_ctx;
-       torture->results = talloc_reference(torture, results);
+       torture->lp_ctx = lp_ctx;
+       torture->results = results;
 
        /*
         * We start with an empty subunit prefix
         */
        torture_subunit_prefix_reset(torture, NULL);
 
+       torture->outputdir = mkdtemp(outputdir_template);
+       if (torture->outputdir == NULL) {
+               TALLOC_FREE(torture);
+               return NULL;
+       }
+
        return torture;
 }
 
 /**
  * Create a sub torture context
  */
-struct torture_context *torture_context_child(struct torture_context *parent)
+struct torture_context *torture_context_child(TALLOC_CTX *mem_ctx,
+                                             struct torture_context *parent)
 {
-       struct torture_context *subtorture = talloc_zero(parent, struct 
torture_context);
+       struct torture_context *subtorture = NULL;
+
+       SMB_ASSERT(parent);
+       SMB_ASSERT(parent->ev);
+       SMB_ASSERT(parent->lp_ctx);
+       SMB_ASSERT(parent->results);
+       SMB_ASSERT(parent->outputdir);
 
-       if (subtorture == NULL)
+       subtorture = talloc_zero(mem_ctx, struct torture_context);
+       if (subtorture == NULL) {
                return NULL;
+       }
 
-       subtorture->ev = talloc_reference(subtorture, parent->ev);
-       subtorture->lp_ctx = talloc_reference(subtorture, parent->lp_ctx);
-       subtorture->outputdir = talloc_reference(subtorture, parent->outputdir);
-       subtorture->results = talloc_reference(subtorture, parent->results);
+       subtorture->ev = parent->ev;
+       subtorture->lp_ctx = parent->lp_ctx;
+       subtorture->results = parent->results;
+       subtorture->outputdir = parent->outputdir;
+
+       if (parent->active_prefix != NULL) {
+               memcpy(subtorture->_initial_prefix.subunit_prefix,
+                      parent->active_prefix->subunit_prefix,
+                      sizeof(subtorture->active_prefix->subunit_prefix));
+       }
+       subtorture->active_prefix = &subtorture->_initial_prefix;
 
        return subtorture;
 }
@@ -484,23 +518,97 @@ static bool test_needs_running(const char *name, const 
char **restricted)
        return false;
 }
 
-static bool internal_torture_run_test(struct torture_context *context,
+static void torture_dummy_signal0_handler(struct tevent_context *ev,
+                                         struct tevent_signal *se,
+                                         int signum,
+                                         int count,
+                                         void *siginfo,
+                                         void *private_data)
+{
+}
+
+static bool internal_torture_run_test(struct torture_context *_context,
                                          struct torture_tcase *tcase,
                                          struct torture_test *test,
                                          bool already_setup,
                                          const char **restricted)
 {
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct torture_context *context = NULL;
+       char *subunit_testname = NULL;
        bool success;
-       char *subunit_testname = torture_subunit_test_name(context, tcase, 
test);
+       size_t evtb1 = 0;
+       size_t evtb2 = 0;
+
+       if (already_setup) {
+               context = _context;
+       } else {
+               context = torture_context_child(frame, _context);
+               if (context == NULL) {
+                       torture_ui_test_start(_context, tcase, test);
+                       torture_ui_test_result(_context, TORTURE_ERROR,
+                                              "torture_context_child() 
failed");
+                       TALLOC_FREE(frame);
+                       return false;
+               }
+       }
 
-       if (!test_needs_running(subunit_testname, restricted))
+       subunit_testname = torture_subunit_test_name(context, tcase, test);
+       if (subunit_testname == NULL) {
+               torture_ui_test_start(context, tcase, test);
+               torture_ui_test_result(context, TORTURE_ERROR,
+                                      "torture_subunit_test_name() failed");
+               TALLOC_FREE(frame);
+               return false;
+       }
+       talloc_steal(frame, subunit_testname);
+
+       if (!test_needs_running(subunit_testname, restricted)) {
+               TALLOC_FREE(frame);
                return true;
+       }
 
        context->active_tcase = tcase;
        context->active_test = test;
 
        torture_ui_test_start(context, tcase, test);
 
+       if (!already_setup) {
+               struct tevent_signal *dummy_se = NULL;
+               int rc;
+
+               rc = tevent_re_initialise(context->ev);
+               if (rc != 0) {
+                       torture_ui_test_result(context, TORTURE_ERROR,
+                                              "tevent_re_initialise() failed");
+                       TALLOC_FREE(frame);
+                       return false;
+               }
+
+               /*
+                * We call tevent_add_signal() in order
+                * to have tevent_common_wakeup_init()
+                * called.
+                *
+                * So that talloc_total_blocks(context->ev)
+                * gives stable results.
+                */
+               dummy_se = tevent_add_signal(context->ev,
+                                            context,
+                                            SIGCONT,
+                                            0, /* sa_flags */
+                                            torture_dummy_signal0_handler,
+                                            NULL);
+               if (dummy_se == NULL) {
+                       torture_ui_test_result(context, TORTURE_ERROR,
+                                              "tevent_add_signal() failed");
+                       TALLOC_FREE(frame);
+                       return false;
+               }
+
+               evtb1 = talloc_total_blocks(context->ev);
+       }
+
        context->last_reason = NULL;
        context->last_result = TORTURE_OK;
 
@@ -537,11 +645,25 @@ static bool internal_torture_run_test(struct 
torture_context *context,
        torture_ui_test_result(context, context->last_result,
                               context->last_reason);
 
-       talloc_free(context->last_reason);
-       context->last_reason = NULL;
+       if (!already_setup) {
+               TALLOC_FREE(context);
+
+               evtb2 = talloc_total_blocks(_context->ev);
+               if (evtb1 != evtb2) {
+                       char *rp = talloc_report_str(frame, _context->ev);
+                       DBG_ERR("%s: evtb1[%zu] evtb2[%zu]\n%s\n",
+                               subunit_testname, evtb1, evtb2, rp);
+                       TALLOC_FREE(rp);
+                       if (success) {
+                               SMB_ASSERT(evtb1 == evtb2);
+                       }
+               }
+       }
 
-       context->active_test = NULL;
-       context->active_tcase = NULL;
+       TALLOC_FREE(frame);
+       if (!already_setup) {
+               tevent_re_initialise(_context->ev);
+       }
 
        return success;
 }
@@ -552,19 +674,70 @@ bool torture_run_tcase(struct torture_context *context,
        return torture_run_tcase_restricted(context, tcase, NULL);
 }
 
-bool torture_run_tcase_restricted(struct torture_context *context,
+bool torture_run_tcase_restricted(struct torture_context *_context,
                       struct torture_tcase *tcase, const char **restricted)
 {
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct torture_context *context = NULL;
+       struct tevent_signal *dummy_se = NULL;
        bool ret = true;
        struct torture_test *test;
        bool setup_succeeded = true;
        const char * setup_reason = "Setup failed";
+       enum torture_result fail_result = TORTURE_FAIL;
+       size_t evtb1 = 0;
+       size_t evtb2 = 0;
+       int rc;
+
+       context = torture_context_child(frame, _context);
+       if (context == NULL) {
+               setup_succeeded = false;
+               setup_reason = "torture_context_child() failed";
+               fail_result = TORTURE_ERROR;
+               context = _context;
+               goto setup_failed;
+       }
+
+       rc = tevent_re_initialise(context->ev);
+       if (rc != 0) {
+               setup_succeeded = false;
+               setup_reason = "tevent_re_initialise() failed";
+               fail_result = TORTURE_ERROR;
+               context = _context;
+               goto setup_failed;
+       }
+
+       /*
+        * We call tevent_add_signal() in order
+        * to have tevent_common_wakeup_init()
+        * called.
+        *
+        * So that talloc_total_blocks(context->ev)
+        * gives stable results.
+        */
+       dummy_se = tevent_add_signal(context->ev,
+                                    context,
+                                    SIGCONT,
+                                    0, /* sa_flags */
+                                    torture_dummy_signal0_handler,
+                                    NULL);
+       if (dummy_se == NULL) {
+               setup_succeeded = false;
+               setup_reason = "tevent_add_signal() failed";
+               fail_result = TORTURE_ERROR;
+               context = _context;
+               goto setup_failed;
+       }
+
+       evtb1 = talloc_total_blocks(context->ev);
+
+setup_failed:
 
        context->active_tcase = tcase;
        if (context->results->ui_ops->tcase_start) 
                context->results->ui_ops->tcase_start(context, tcase);
 
-       if (tcase->fixture_persistent && tcase->setup) {
+       if (setup_succeeded && tcase->fixture_persistent && tcase->setup) {
                setup_succeeded = tcase->setup(context, &tcase->data);
        }
 
@@ -588,7 +761,7 @@ bool torture_run_tcase_restricted(struct torture_context 
*context,
                        context->active_tcase = tcase;
                        context->active_test = test;
                        torture_ui_test_start(context, tcase, test);
-                       torture_ui_test_result(context, TORTURE_FAIL, 
setup_reason);
+                       torture_ui_test_result(context, fail_result, 
setup_reason);
                }
        }
 
@@ -603,6 +776,26 @@ bool torture_run_tcase_restricted(struct torture_context 
*context,
        if (context->results->ui_ops->tcase_finish)
                context->results->ui_ops->tcase_finish(context, tcase);
 
+       if (setup_succeeded) {
+               if (context != _context) {
+                       TALLOC_FREE(context);
+               }
+
+               evtb2 = talloc_total_blocks(_context->ev);
+               if (evtb1 != evtb2) {
+                       char *rp = talloc_report_str(frame, _context->ev);
+                       DBG_ERR("%s: evtb1[%zu] evtb2[%zu]\n%s\n",
+                               tcase->name, evtb1, evtb2, rp);
+                       TALLOC_FREE(rp);
+                       if (ret) {
+                               SMB_ASSERT(evtb1 == evtb2);
+                       }
+               }
+       }
+
+       TALLOC_FREE(frame);
+       tevent_re_initialise(_context->ev);
+
        return (!setup_succeeded) ? false : ret;
 }
 
diff --git a/lib/torture/torture.h b/lib/torture/torture.h
index 1bea7bd2c34..8c8fa326345 100644
--- a/lib/torture/torture.h
+++ b/lib/torture/torture.h
@@ -908,11 +908,16 @@ bool torture_suite_init_tcase(struct torture_suite *suite,
                              const char *name);
 int torture_suite_children_count(const struct torture_suite *suite);
 
-struct torture_context *torture_context_init(struct tevent_context *event_ctx, 
struct torture_results *results);
+struct torture_context *torture_context_init(TALLOC_CTX *mem_ctx,
+                                            struct tevent_context *event_ctx,
+                                            struct loadparm_context *lp_ctx,
+                                            struct torture_results *results,
+                                            char *outputdir_template);
 
 struct torture_results *torture_results_init(TALLOC_CTX *mem_ctx, const struct 
torture_ui_ops *ui_ops);
 
-struct torture_context *torture_context_child(struct torture_context *tctx);
+struct torture_context *torture_context_child(TALLOC_CTX *mem_ctx,
+                                             struct torture_context *parent);
 
 extern const struct torture_ui_ops torture_subunit_ui_ops;
 extern const struct torture_ui_ops torture_simple_ui_ops;
diff --git a/lib/torture/wscript_build b/lib/torture/wscript_build
index 31c386277fb..2e7dc301971 100644
--- a/lib/torture/wscript_build
+++ b/lib/torture/wscript_build
@@ -3,6 +3,6 @@
 bld.SAMBA_LIBRARY('torture',
     private_library=True,
     source='torture.c subunit.c simple.c',
-    public_deps='samba-hostconfig samba-util samba-errors talloc tevent',
+    public_deps='samba-hostconfig samba-util samba-errors talloc tevent 
talloc_report',
     private_headers='torture.h'
     )
diff --git a/lib/util/charset/tests/iconv.c b/lib/util/charset/tests/iconv.c
index 3733c3c6b66..2139795d0a8 100644
--- a/lib/util/charset/tests/iconv.c
+++ b/lib/util/charset/tests/iconv.c
@@ -129,8 +129,88 @@ static void show_buf(const char *name, uint8_t *buf, 
size_t size)
   "charset", then convert it back again and ensure we get the same
   buffer back
 */
+
+struct test_buffer_cache {
+       const char *charset;
+       iconv_t cd;
+       smb_iconv_t cd2;
+       smb_iconv_t cd3;
+};
+
+static int test_buffer_cache_destructor(struct test_buffer_cache *c)
+{
+       if (c->cd3 != (smb_iconv_t)-1) {
+               smb_iconv_close(c->cd3);
+               c->cd3 = (smb_iconv_t)-1;
+       }
+       if (c->cd2 != (smb_iconv_t)-1) {
+               smb_iconv_close(c->cd2);
+               c->cd2 = (smb_iconv_t)-1;
+       }
+       if (c->cd != (iconv_t)-1) {
+               iconv_close(c->cd);
+               c->cd = (iconv_t)-1;
+       }
+
+       return 0;
+}
+
+static bool test_buffer_create_cache(struct torture_context *test,
+                                    const char *charset,
+                                    struct test_buffer_cache **_cache)
+{
+       struct test_buffer_cache *c = NULL;
+       bool use_builtin;
+
+       use_builtin = lpcfg_parm_bool(test->lp_ctx,
+                                     NULL,
+                                     "iconv",
+                                     "use_builtin_handlers",
+                                     true);
+
+       c = talloc_zero(test, struct test_buffer_cache);
+       torture_assert(test, c != NULL, "talloc_zero");
+       c->cd = (iconv_t)-1;
+       c->cd2 = (smb_iconv_t)-1;
+       c->cd3 = (smb_iconv_t)-1;
+       talloc_set_destructor(c, test_buffer_cache_destructor);
+
+       c->charset = talloc_strdup(c, charset);
+       torture_assert(test, c->charset != NULL, "talloc_strdup");
+
+       c->cd = iconv_open(charset, "UTF-16LE");
+       if (c->cd == (iconv_t)-1) {
+               torture_fail_goto(test, fail, talloc_asprintf(test,
+                       "failed to open %s to UTF-16LE",
+                       charset));
+       }
+       c->cd2 = smb_iconv_open_ex(c, charset, "UTF-16LE", use_builtin);
+       if (c->cd2 == (smb_iconv_t)-1) {
+               int saved_errno = errno;
+               torture_fail_goto(test, fail, talloc_asprintf(c,
+                       "failed to open %s to UTF-16LE via smb_iconv_open_ex"
+                       "use_builtin[%u] %s",
+                       charset, use_builtin, strerror(saved_errno)));
+       }
+       c->cd3 = smb_iconv_open_ex(c, "UTF-16LE", charset, use_builtin);
+       if (c->cd3 == (smb_iconv_t)-1) {
+               int saved_errno = errno;
+               torture_fail_goto(test, fail, talloc_asprintf(c,
+                       "failed to open UTF-16LE to %s via smb_iconv_open_ex"
+                       "use_builtin[%u] %s",
+                       charset, use_builtin, strerror(saved_errno)));
+       }
+
+       *_cache = c;
+       return true;
+fail:
+       TALLOC_FREE(c);
+       return false;
+}
+
 static bool test_buffer(struct torture_context *test, 
-                       uint8_t *inbuf, size_t size, const char *charset)
+                       struct test_buffer_cache *c,
+                       uint8_t *inbuf, size_t size)
 {
        uint8_t buf1[1000], buf2[1000], buf3[1000];
        size_t outsize1, outsize2, outsize3;
@@ -140,41 +220,10 @@ static bool test_buffer(struct torture_context *test,
        size_t size_in1, size_in2, size_in3;
        size_t ret1, ret2, ret3, len1, len2;
        int errno1, errno2;
-       static iconv_t cd;
-       static smb_iconv_t cd2, cd3;
-       static const char *last_charset;
-
-       if (cd && last_charset) {
-               iconv_close(cd);
-               smb_iconv_close(cd2);
-               smb_iconv_close(cd3);
-               cd = NULL;
-       }
-
-       if (!cd) {
-               cd = iconv_open(charset, "UTF-16LE");
-               if (cd == (iconv_t)-1) {
-                       torture_fail(test, 
-                                    talloc_asprintf(test, 
-                                                    "failed to open %s to 
UTF-16LE",
-                                                    charset));
-               }
-               cd2 = smb_iconv_open_ex(test, charset, "UTF-16LE", 
lpcfg_parm_bool(test->lp_ctx, NULL, "iconv", "use_builtin_handlers", true));
-               if (cd2 == (iconv_t)-1) {
-                       torture_fail(test, 
-                                    talloc_asprintf(test, 
-                                                    "failed to open %s to 
UTF-16LE via smb_iconv_open_ex",
-                                                    charset));
-               }
-               cd3 = smb_iconv_open_ex(test, "UTF-16LE", charset, 
lpcfg_parm_bool(test->lp_ctx, NULL, "iconv", "use_builtin_handlers", true));
-               if (cd3 == (iconv_t)-1) {


-- 
Samba Shared Repository

Reply via email to