]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Fixup dict free functions to work in the gctx the dictionary was allocated
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 6 Nov 2019 23:29:58 +0000 (17:29 -0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 6 Nov 2019 23:29:58 +0000 (17:29 -0600)
Fixup unit_test_attribute to allocate test dictionaries in a different gctx

src/bin/unit_test_attribute.c
src/lib/util/dict.h
src/lib/util/dict_util.c

index 562ab760847729a42268a969e152bfb7ab594457..7fad4861ae7aae68cc06825cdadace88e7d9734a 100644 (file)
@@ -186,7 +186,8 @@ typedef struct {
 
        fr_dict_t               *active_dict;           //!< Active dictionary passed to encoders
                                                        ///< and decoders.
-       fr_dict_gctx_t          *test_gctx;             //!< Dictionary context for test dictionaries.
+       fr_dict_t               *test_internal_dict;    //!< Internal dictionary of test_gctx.
+       fr_dict_gctx_t const    *test_gctx;             //!< Dictionary context for test dictionaries.
 
        command_config_t const  *config;
 } command_ctx_t;
@@ -800,9 +801,8 @@ static ssize_t load_test_point_by_command(void **symbol, char *command, char con
 
 /** Common dictionary load function
  *
- * Callers call fr_dict_global_dir_set to set the dictionary root to
- * load dictionaries from, then provide a relative path to
- * navigate through test subdirectories or protocols
+ * Callers call fr_dict_global_ctx_set to set the context
+ * the dictionaries will be loaded into.
  */
 static int dictionary_load_common(command_result_t *result, command_ctx_t *cc, char *in, char const *default_subdir)
 {
@@ -1598,7 +1598,7 @@ static size_t command_proto(command_result_t *result, command_ctx_t *cc,
                RETURN_PARSE_ERROR(0);
        }
 
-       fr_dict_global_dir_set(cc->config->dict_dir);
+       fr_dict_global_ctx_set(cc->config->dict_gctx);
        slen = load_proto_library(in);
        if (slen <= 0) RETURN_PARSE_ERROR(-(slen));
 
@@ -1608,8 +1608,7 @@ static size_t command_proto(command_result_t *result, command_ctx_t *cc,
 static size_t command_proto_dictionary(command_result_t *result, command_ctx_t *cc,
                                       UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
 {
-       fr_dict_global_dir_set(cc->config->dict_dir);
-
+       fr_dict_global_ctx_set(cc->config->dict_gctx);
        return dictionary_load_common(result, cc, in, NULL);
 }
 
@@ -1628,9 +1627,13 @@ static size_t command_touch(command_result_t *result, UNUSED command_ctx_t *cc,
 static size_t command_test_dictionary(command_result_t *result, command_ctx_t *cc,
                                      UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
 {
-       fr_dict_global_dir_set(cc->path);
+       int ret;
+
+       fr_dict_global_ctx_set(cc->test_gctx);
+       ret = dictionary_load_common(result, cc, in, ".");
+       fr_dict_global_ctx_set(cc->config->dict_gctx);
 
-       return dictionary_load_common(result, cc, in, ".");
+       return ret;
 }
 
 static size_t command_value_box_normalise(command_result_t *result, UNUSED command_ctx_t *cc,
@@ -1987,25 +1990,58 @@ size_t process_line(command_result_t *result, command_ctx_t *cc, char *data, siz
        return data_used;
 }
 
+static int _command_ctx_free(command_ctx_t *cc)
+{
+       fr_dict_free(&cc->test_internal_dict);
+       return 0;
+}
+
 static command_ctx_t *command_ctx_alloc(TALLOC_CTX *ctx,
                                        command_config_t const *config, char const *path, char const *filename)
 {
        command_ctx_t *cc;
 
        cc = talloc_zero(ctx, command_ctx_t);
+       talloc_set_destructor(cc, _command_ctx_free);
+
        cc->tmp_ctx = talloc_named_const(ctx, 0, "tmp_ctx");
        cc->path = talloc_strdup(cc, path);
        cc->filename = filename;
        cc->config = config;
 
+       /*
+        *      Initialise a special temporary dictionary context
+        *
+        *      Any protocol dictionaries loaded by "test-dictionary"
+        *      go in this context, and don't affect the main
+        *      dictionary context.
+        */
+       cc->test_gctx = fr_dict_global_ctx_init(cc, cc->config->dict_dir);
+       if (!cc->test_gctx) {
+               PERROR("Failed allocating test dict_gctx");
+               return NULL;
+       }
+
+       fr_dict_global_ctx_set(cc->test_gctx);
+       if (fr_dict_internal_afrom_file(&cc->test_internal_dict, FR_DICTIONARY_INTERNAL_DIR) < 0) {
+               PERROR("Failed loading test dict_gctx internal dictionary");
+               return NULL;
+       }
+
+       fr_dict_global_ctx_dir_set(cc->path);   /* Load new dictionaries relative to the test file */
+       fr_dict_global_ctx_set(cc->config->dict_gctx);
+
        return cc;
 }
 
 static void command_ctx_reset(command_ctx_t *cc, TALLOC_CTX *ctx)
 {
-       TALLOC_FREE(cc->tmp_ctx);
+       talloc_free(cc->tmp_ctx);
        cc->tmp_ctx = talloc_named_const(ctx, 0, "tmp_ctx");
        cc->test_count = 0;
+
+       fr_dict_global_ctx_free(cc->test_gctx);
+       cc->test_gctx = fr_dict_global_ctx_init(cc, cc->config->dict_dir);
 }
 
 static int process_file(bool *exit_now, TALLOC_CTX *ctx, command_config_t const *config,
@@ -2142,11 +2178,11 @@ finish:
        /*
         *      Free any residual resources we loaded.
         */
+       if (cc) fr_dict_free(&cc->active_dict);
+       fr_dict_global_ctx_set(config->dict_gctx);      /* Switch back to the main dict ctx */
        unload_proto_library();
-       fr_dict_free(&cc->active_dict);
        talloc_free(cc);
 
-
        return ret;
 }
 
@@ -2381,7 +2417,7 @@ cleanup:
         *      because it breaks "autofree".
         */
        if (fr_dict_global_ctx_free(config.dict_gctx) < 0) {
-               fr_perror("unit_test_attribute - dict_gctx - ");        /* Print free order issues */
+               fr_perror("unit_test_attribute");       /* Print free order issues */
        }
 
        if (receipt_file && (ret == EXIT_SUCCESS) && (fr_touch(NULL, receipt_file, 0644, true, 0755) <= 0)) {
index 3ebb1b855ed1c4d0ca4a1546585f1a01916a941a..1c728cf8ce6a3b4bb3cd722549f83fd827f01947 100644 (file)
@@ -433,7 +433,7 @@ void                        fr_dict_global_ctx_set(fr_dict_gctx_t const *gctx);
 
 int                    fr_dict_global_ctx_free(fr_dict_gctx_t const *gctx);
 
-int                    fr_dict_global_dir_set(char const *dict_dir);
+int                    fr_dict_global_ctx_dir_set(char const *dict_dir);
 
 void                   fr_dict_global_read_only(void);
 
index 4885910e33abc7624afa12e6c57cfec4611d5e55..f828503390a7b23163515c39902c12932b21d3b8 100644 (file)
@@ -2234,17 +2234,15 @@ static int _dict_free(fr_dict_t *dict)
         *      We don't necessarily control the order of freeing
         *      children.
         */
-       if (dict_gctx) {
-               if (dict == dict_gctx->internal) dict_gctx->internal = NULL;
+       if (dict == dict->gctx->internal) dict->gctx->internal = NULL;
 
-               if (!fr_cond_assert(!dict->in_protocol_by_name || fr_hash_table_delete(dict_gctx->protocol_by_name, dict))) {
-                       fr_strerror_printf("Failed removing dictionary from protocol hash \"%s\"", dict->root->name);
-                       return -1;
-               }
-               if (!fr_cond_assert(!dict->in_protocol_by_num || fr_hash_table_delete(dict_gctx->protocol_by_num, dict))) {
-                       fr_strerror_printf("Failed removing dictionary from protocol number_hash \"%s\"", dict->root->name);
-                       return -1;
-               }
+       if (!fr_cond_assert(!dict->in_protocol_by_name || fr_hash_table_delete(dict->gctx->protocol_by_name, dict))) {
+               fr_strerror_printf("Failed removing dictionary from protocol hash \"%s\"", dict->root->name);
+               return -1;
+       }
+       if (!fr_cond_assert(!dict->in_protocol_by_num || fr_hash_table_delete(dict->gctx->protocol_by_num, dict))) {
+               fr_strerror_printf("Failed removing dictionary from protocol number_hash \"%s\"", dict->root->name);
+               return -1;
        }
 
        if (dict->autoref &&
@@ -2265,6 +2263,11 @@ fr_dict_t *dict_alloc(TALLOC_CTX *ctx)
 {
        fr_dict_t *dict;
 
+       if (!dict_gctx) {
+               fr_strerror_printf("Initialise global dictionary ctx with fr_dict_global_ctx_init()");
+               return NULL;
+       }
+
        dict = talloc_zero(ctx, fr_dict_t);
        if (!dict) {
                fr_strerror_printf("Failed allocating memory for dictionary");
@@ -2272,7 +2275,6 @@ fr_dict_t *dict_alloc(TALLOC_CTX *ctx)
                talloc_free(dict);
                return NULL;
        }
-
        talloc_set_destructor(dict, _dict_free);
 
        /*
@@ -2346,6 +2348,8 @@ fr_dict_t *dict_alloc(TALLOC_CTX *ctx)
                goto error;
        }
 
+       dict->gctx = dict_gctx; /* Record which global context this was allocated in */
+
        /*
         *      Set default type size and length.
         */
@@ -2633,7 +2637,7 @@ fr_dict_gctx_t const *fr_dict_global_ctx_init(TALLOC_CTX *ctx, char const *dict_
        if (dl_symbol_init_cb_register(new_ctx->dict_loader, 0, "dict_protocol",
                                       dict_onload_func, NULL) < 0) goto error;
 
-       dict_gctx = new_ctx;
+       if (!dict_gctx) dict_gctx = new_ctx;    /* Set as the default */
        talloc_set_destructor(dict_gctx, _dict_global_free);
 
        return new_ctx;
@@ -2671,7 +2675,7 @@ int fr_dict_global_ctx_free(fr_dict_gctx_t const *gctx)
  *     - 0 on success.
  *     - -1 on failure.
  */
-int fr_dict_global_dir_set(char const *dict_dir)
+int fr_dict_global_ctx_dir_set(char const *dict_dir)
 {
        if (!dict_gctx) return -1;