]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
shrunk cfgobj down to 48bytes
authorColin Vidal <colin@isc.org>
Fri, 7 Nov 2025 13:58:36 +0000 (14:58 +0100)
committerColin Vidal <colin@isc.org>
Fri, 5 Dec 2025 07:59:53 +0000 (08:59 +0100)
Make all non-scalar properties of `cfg_obj_t` allocated values, which
ensures the union size is the width of one pointer. Also reorder the
fields inside `cfg_obj_t` to avoid alignment padding that would increase
the size. As a result, a `cfg_obj_t` instance is now 48 bytes on a
64-bit platform.

Add a static assertion to avoid increasing the size of the struct by
mistake.

The function `parse_sockaddrsub` was taking advantage of the fact that
both sockaddr and sockaddrtls were in the same position, and used to
initialize the sockaddr field independently if this was a -tls one or
not. This doesn't work anymore now that all fields are allocated,
so it has been slightly rewritten to take both cases into account
separately.

bin/named/server.c
bin/plugins/synthrecord.c
bin/tests/system/hooks/driver/test-syncplugin.c
lib/isccfg/include/isccfg/grammar.h
lib/isccfg/namedconf.c
lib/isccfg/parser.c
tests/isccfg/parser_test.c

index cb03db4d6208644c43c9a34829ce65881c61a975..2d67b7adc33ea4831d9140ba7a6db8033ab10601 100644 (file)
@@ -12088,7 +12088,7 @@ nzf_writeconf(const cfg_obj_t *config, dns_view_t *view) {
                CLEANUP(ISC_R_FAILURE);
        }
 
-       list = UNCONST(&zl->value.list);
+       list = UNCONST(zl->value.list);
 
        CHECK(add_comment(fp, view->name)); /* force a comment */
 
@@ -12750,7 +12750,7 @@ delete_zoneconf(dns_view_t *view, const cfg_obj_t *config,
                CLEANUP(ISC_R_FAILURE);
        }
 
-       cfg_list_t *list = UNCONST(&zl->value.list);
+       cfg_list_t *list = UNCONST(zl->value.list);
        ISC_LIST_FOREACH(*list, elt, link) {
                dns_fixedname_t myfixed;
                dns_name_t *myname = dns_fixedname_initname(&myfixed);
index 895f2f7df2ec3b44e2de0cc431ff00768aa705e4..fc2f79450bbdce39e60b4c46f28fa09318b47415 100644 (file)
@@ -408,7 +408,6 @@ static cfg_type_t synthrecord_cfgparams = {
 static isc_result_t
 synthrecord_initprefix(synthrecord_t *inst, const cfg_obj_t *synthrecordcfg) {
        isc_result_t result;
-       size_t len;
        const char *base = NULL;
        const cfg_obj_t *obj = NULL;
 
@@ -419,9 +418,7 @@ synthrecord_initprefix(synthrecord_t *inst, const cfg_obj_t *synthrecordcfg) {
                return result;
        }
 
-       len = obj->value.string.length;
-       base = obj->value.string.base;
-
+       base = obj->value.string;
        if (strstr(base, ".") != NULL) {
                isc_log_write(NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS,
                              ISC_LOG_ERROR,
@@ -430,10 +427,9 @@ synthrecord_initprefix(synthrecord_t *inst, const cfg_obj_t *synthrecordcfg) {
                return ISC_R_UNEXPECTEDTOKEN;
        }
 
-       inst->prefix = (isc_region_t){
-               .base = isc_mem_allocate(inst->mctx, len), .length = len
-       };
-       memmove(inst->prefix.base, base, len);
+       inst->prefix = (isc_region_t){ .base = (unsigned char *)isc_mem_strdup(
+                                              inst->mctx, base),
+                                      .length = strlen(base) };
 
        /*
         * Avoid dynamically lower-casing the prefix when parsing the
index c125f335d67337c2990dbb3e80a691683fb0de8f..3ac08a2dc99e310768afb2b6a440ca27859094e7 100644 (file)
@@ -80,7 +80,7 @@ syncplugin__parse_rcode(const cfg_obj_t *syncplugincfg, uint8_t *rcode) {
 
        RETERR(cfg_map_get(syncplugincfg, "rcode", &obj));
 
-       rcodestr = obj->value.string.base;
+       rcodestr = obj->value.string;
 
        if (strcmp("servfail", rcodestr) == 0) {
                *rcode = dns_rcode_servfail;
@@ -141,7 +141,7 @@ plugin_register(const char *parameters, const void *cfg, const char *cfgfile,
 
        obj = NULL;
        CHECK(cfg_map_get(syncplugincfg, "source", &obj));
-       sourcestr = obj->value.string.base;
+       sourcestr = obj->value.string;
 
        if (strcmp(sourcestr, "zone") == 0) {
                if (ctx->source != NS_HOOKSOURCE_ZONE) {
index 975385409edd31c6418d4ca81f3554545767b89e..6d1ef1e503c36e346ef1455abe9b78aa195fb070 100644 (file)
@@ -196,37 +196,43 @@ struct cfg_rep {
  * A configuration object.  This is the main building block
  * of the configuration parse tree.
  */
+typedef struct {
+       isc_sockaddr_t sockaddr;
+       char          *tls;
+} cfg_sockaddrtls_t;
 
 struct cfg_obj {
-       unsigned int   magic;
-       isc_refcount_t references;
-
-       /*%
-        * Indicates that an object was cloned from the defaults
-        * or otherwise generated during the configuration merge
-        * process:
+       /*
+        * These two 4 byte fields are contiguous to avoid an extra
+        * padding of 4 bytes each, avoiding an extra 8 bytes in the
+        * struct.
         */
-       bool cloned;
+       unsigned int magic;
+       unsigned int line;
 
+       isc_refcount_t    references;
+       cfg_obj_t        *file; /*%< separate string with its own refcount */
        const cfg_type_t *type;
        union {
-               uint32_t         uint32;
-               uint64_t         uint64;
-               isc_textregion_t string; /*%< null terminated, too */
-               bool             boolean;
-               cfg_map_t        map;
-               cfg_list_t       list;
-               cfg_obj_t      **tuple;
-               isc_sockaddr_t  *sockaddr;
-               struct {
-                       isc_sockaddr_t  *sockaddr;
-                       isc_textregion_t tls;
-               } sockaddrtls;
+               uint32_t           uint32;
+               uint64_t           uint64;
+               char              *string; /*%< null terminated */
+               bool               boolean;
+               cfg_map_t         *map;
+               cfg_list_t        *list;
+               cfg_obj_t        **tuple;
+               isc_sockaddr_t    *sockaddr;
+               cfg_sockaddrtls_t *sockaddrtls;
                cfg_netprefix_t   *netprefix;
                isccfg_duration_t *duration;
        } value;
-       cfg_obj_t   *file; /*%< separate string with its own refcount */
-       unsigned int line;
+
+       /*%
+        * Indicates that an object was cloned from the defaults
+        * or otherwise generated during the configuration merge
+        * process.
+        */
+       bool cloned;
 };
 
 /*% A list element. */
index c6ecbf041b1f236a5ae0ef661da8d1d953907924..90fc49a74e2f0d8608974394f10fa288ab87f7a0 100644 (file)
@@ -2297,8 +2297,8 @@ checknames_merge(const cfg_obj_t *config ISC_ATTR_UNUSED,
                        const cfg_obj_t *etype = cfg_tuple_get(echeckname,
                                                               "type");
 
-                       if (strcasecmp(type->value.string.base,
-                                      etype->value.string.base) == 0)
+                       if (strcasecmp(type->value.string,
+                                      etype->value.string) == 0)
                        {
                                found = true;
                                break;
@@ -2311,7 +2311,7 @@ checknames_merge(const cfg_obj_t *config ISC_ATTR_UNUSED,
                        cfg_listelt_create(&eelt);
                        *eelt = (cfg_listelt_t){ .link = ISC_LINK_INITIALIZER };
                        cfg_obj_clone(checkname, &eelt->obj);
-                       ISC_LIST_APPEND(effectiveobj->value.list, eelt, link);
+                       ISC_LIST_APPEND(*effectiveobj->value.list, eelt, link);
                }
        }
 }
index 8b9a99c8e4175196eeca50da49e5b88c364023fe..e7980be9cd3a957ad82d3a522f86024b293c1dd0 100644 (file)
 #include <isccfg/cfg.h>
 #include <isccfg/grammar.h>
 
+/*
+ * cfg_obj_t is used _a lot_ when building the configuration tree, which
+ * can take a significant amount of memory. This assert ensures that we
+ * won't increase its size by mistake without getting a warning.
+ */
+static_assert(sizeof(struct cfg_obj) <= 48,
+             "sizeof(cfg_obj_t) must be 48 bytes");
+
 /* Shorthand */
 #define CAT CFG_LOGCATEGORY_CONFIG
 #define MOD CFG_LOGMODULE_PARSER
@@ -77,7 +85,6 @@
 #define SYMTAB_DUMMY_TYPE 1
 
 #define TOKEN_STRING(pctx) (pctx->token.value.as_textregion.base)
-#define TOKEN_REGION(pctx) (pctx->token.value.as_textregion)
 
 /* cfg_obj_t magic number */
 #define CFGOBJ_MAGIC     ISC_MAGIC('c', 'f', 'g', 'o')
@@ -188,19 +195,12 @@ copy_sockaddr(cfg_obj_t *to, const cfg_obj_t *from) {
 
 static void
 copy_sockaddrtls(cfg_obj_t *to, const cfg_obj_t *from) {
-       to->value.sockaddrtls.sockaddr = isc_mem_get(isc_g_mctx,
-                                                    sizeof(isc_sockaddr_t));
-       memmove(to->value.sockaddrtls.sockaddr,
-               from->value.sockaddrtls.sockaddr, sizeof(isc_sockaddr_t));
-
-       if (from->value.sockaddrtls.tls.base != NULL) {
-               size_t len = from->value.sockaddrtls.tls.length;
-
-               to->value.sockaddrtls.tls.base = isc_mem_get(isc_g_mctx,
-                                                            len + 1);
-               to->value.sockaddrtls.tls.length = len;
-               memmove(to->value.sockaddrtls.tls.base,
-                       from->value.sockaddrtls.tls.base, len + 1);
+       to->value.sockaddrtls = isc_mem_cget(isc_g_mctx, 1,
+                                            sizeof(*to->value.sockaddrtls));
+       to->value.sockaddrtls->sockaddr = from->value.sockaddrtls->sockaddr;
+       if (from->value.sockaddrtls->tls != NULL) {
+               to->value.sockaddrtls->tls = isc_mem_strdup(
+                       isc_g_mctx, from->value.sockaddrtls->tls);
        }
 }
 
@@ -230,11 +230,7 @@ copy_duration(cfg_obj_t *to, const cfg_obj_t *from) {
 
 static void
 copy_string(cfg_obj_t *to, const cfg_obj_t *from) {
-       to->value.string.length = from->value.string.length;
-       to->value.string.base = isc_mem_get(isc_g_mctx,
-                                           to->value.string.length + 1);
-       memmove(to->value.string.base, from->value.string.base,
-               to->value.string.length + 1);
+       to->value.string = isc_mem_strdup(isc_g_mctx, from->value.string);
 }
 
 static void
@@ -261,7 +257,7 @@ copy_map_add(char *key, unsigned int type, isc_symvalue_t value, void *arg) {
        cfg_obj_clone(value.as_pointer, &toelt);
        value.as_pointer = toelt;
 
-       INSIST(isc_symtab_define(to->value.map.symtab, key, type, value,
+       INSIST(isc_symtab_define(to->value.map->symtab, key, type, value,
                                 isc_symexists_reject) == ISC_R_SUCCESS);
 
        /*
@@ -272,24 +268,28 @@ copy_map_add(char *key, unsigned int type, isc_symvalue_t value, void *arg) {
 
 static void
 copy_map(cfg_obj_t *to, const cfg_obj_t *from) {
-       if (from->value.map.id != NULL) {
-               cfg_obj_clone(from->value.map.id, &to->value.map.id);
+       to->value.map = isc_mem_cget(isc_g_mctx, 1, sizeof(*to->value.map));
+
+       if (from->value.map->id != NULL) {
+               cfg_obj_clone(from->value.map->id, &to->value.map->id);
        }
+
        isc_symtab_create(isc_g_mctx, copy_map_destroy, NULL, false,
-                         &to->value.map.symtab);
-       isc_symtab_foreach(from->value.map.symtab, copy_map_add, to);
+                         &to->value.map->symtab);
+       isc_symtab_foreach(from->value.map->symtab, copy_map_add, to);
 
        /*
         * clausesets are statically defined
         */
-       to->value.map.clausesets = from->value.map.clausesets;
+       to->value.map->clausesets = from->value.map->clausesets;
 }
 
 static void
 copy_list(cfg_obj_t *to, const cfg_obj_t *from) {
        const cfg_listelt_t *fromelt = cfg_list_first(from);
 
-       ISC_LIST_INIT(to->value.list);
+       to->value.list = isc_mem_get(isc_g_mctx, sizeof(*to->value.list));
+       ISC_LIST_INIT(*to->value.list);
 
        while (fromelt != NULL) {
                cfg_listelt_t *toelt = isc_mem_get(isc_g_mctx, sizeof(*toelt));
@@ -297,7 +297,7 @@ copy_list(cfg_obj_t *to, const cfg_obj_t *from) {
                *toelt = (cfg_listelt_t){ .link = ISC_LINK_INITIALIZER };
                cfg_obj_clone(fromelt->obj, &toelt->obj);
 
-               ISC_LIST_APPEND(to->value.list, toelt, link);
+               ISC_LIST_APPEND(*to->value.list, toelt, link);
 
                fromelt = cfg_list_next(fromelt);
        }
@@ -418,7 +418,7 @@ cfg_parser_currentfile(cfg_parser_t *pctx) {
                return NULL;
        }
 
-       elt = ISC_LIST_TAIL(pctx->open_files->value.list);
+       elt = ISC_LIST_TAIL(*pctx->open_files->value.list);
        if (elt == NULL) {
                return NULL;
        }
@@ -755,7 +755,7 @@ parser_openfile(cfg_parser_t *pctx, const char *filename) {
        cfg_string_create(pctx, filename, &cfg_type_qstring, &stringobj);
        cfg_listelt_create(&elt);
        elt->obj = stringobj;
-       ISC_LIST_APPEND(pctx->open_files->value.list, elt, link);
+       ISC_LIST_APPEND(*pctx->open_files->value.list, elt, link);
 
        return ISC_R_SUCCESS;
 cleanup:
@@ -823,10 +823,10 @@ cfg_parse_file(const char *filename, const cfg_type_t *type, unsigned int flags,
        result = parse2(pctx, type, ret);
 
        /* Clean up the opened file */
-       elt = ISC_LIST_TAIL(pctx->open_files->value.list);
+       elt = ISC_LIST_TAIL(*pctx->open_files->value.list);
        INSIST(elt != NULL);
-       ISC_LIST_UNLINK(pctx->open_files->value.list, elt, link);
-       ISC_LIST_APPEND(pctx->closed_files->value.list, elt, link);
+       ISC_LIST_UNLINK(*pctx->open_files->value.list, elt, link);
+       ISC_LIST_APPEND(*pctx->closed_files->value.list, elt, link);
 
 cleanup:
        parser_destroy(&pctx);
@@ -1397,15 +1397,9 @@ void
 cfg_string_create(cfg_parser_t *pctx, const char *contents,
                  const cfg_type_t *type, cfg_obj_t **ret) {
        cfg_obj_t *obj = NULL;
-       int len;
 
        cfg_obj_create(cfg_parser_currentfile(pctx), pctx->line, type, &obj);
-       len = strlen(contents);
-       obj->value.string.length = len;
-       obj->value.string.base = isc_mem_get(isc_g_mctx, len + 1);
-       memmove(obj->value.string.base, contents, len);
-       obj->value.string.base[len] = '\0';
-
+       obj->value.string = isc_mem_strdup(isc_g_mctx, contents);
        *ret = obj;
 }
 
@@ -1508,7 +1502,7 @@ print_btext(cfg_printer_t *pctx, const cfg_obj_t *obj) {
         */
        pctx->indent++;
        cfg_print_cstr(pctx, "{");
-       cfg_print_chars(pctx, obj->value.string.base, obj->value.string.length);
+       cfg_print_chars(pctx, obj->value.string, strlen(obj->value.string));
        print_close(pctx);
 }
 
@@ -1538,7 +1532,7 @@ check_enum(cfg_parser_t *pctx, cfg_obj_t *obj, const char *const *enums) {
 
        REQUIRE(VALID_CFGOBJ(obj));
 
-       s = obj->value.string.base;
+       s = obj->value.string;
        if (cfg_is_enum(s, enums)) {
                return ISC_R_SUCCESS;
        }
@@ -1636,17 +1630,17 @@ cfg_print_ustring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
        REQUIRE(pctx != NULL);
        REQUIRE(VALID_CFGOBJ(obj));
 
-       cfg_print_chars(pctx, obj->value.string.base, obj->value.string.length);
+       cfg_print_chars(pctx, obj->value.string, strlen(obj->value.string));
 }
 
 static void
-print_rawqstring(cfg_printer_t *pctx, const isc_textregion_t string) {
+print_rawqstring(cfg_printer_t *pctx, const char *string) {
        cfg_print_cstr(pctx, "\"");
-       for (size_t i = 0; i < string.length; i++) {
-               if (string.base[i] == '"') {
+       for (size_t i = 0; i < strlen(string); i++) {
+               if (string[i] == '"') {
                        cfg_print_cstr(pctx, "\\");
                }
-               cfg_print_chars(pctx, (const char *)&string.base[i], 1);
+               cfg_print_chars(pctx, (const char *)&string[i], 1);
        }
        cfg_print_cstr(pctx, "\"");
 }
@@ -1662,7 +1656,7 @@ print_sstring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
        REQUIRE(VALID_CFGOBJ(obj));
        cfg_print_cstr(pctx, "\"");
        if ((pctx->flags & CFG_PRINTER_XKEY) != 0) {
-               unsigned int len = obj->value.string.length;
+               size_t len = strlen(obj->value.string);
                while (len-- > 0) {
                        cfg_print_cstr(pctx, "?");
                }
@@ -1674,8 +1668,7 @@ print_sstring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
 
 static void
 free_string(cfg_obj_t *obj) {
-       isc_mem_put(isc_g_mctx, obj->value.string.base,
-                   obj->value.string.length + 1);
+       isc_mem_free(isc_g_mctx, obj->value.string);
 }
 
 static void
@@ -1685,13 +1678,11 @@ free_sockaddr(cfg_obj_t *obj) {
 
 static void
 free_sockaddrtls(cfg_obj_t *obj) {
-       isc_mem_put(isc_g_mctx, obj->value.sockaddrtls.sockaddr,
-                   sizeof(isc_sockaddr_t));
-       if (obj->value.sockaddrtls.tls.base != NULL) {
-               INSIST(obj->value.sockaddrtls.tls.length != 0);
-               isc_mem_put(isc_g_mctx, obj->value.sockaddrtls.tls.base,
-                           obj->value.sockaddrtls.tls.length + 1);
+       if (obj->value.sockaddrtls->tls != NULL) {
+               isc_mem_free(isc_g_mctx, obj->value.sockaddrtls->tls);
        }
+       isc_mem_put(isc_g_mctx, obj->value.sockaddrtls,
+                   sizeof(*obj->value.sockaddrtls));
 }
 
 bool
@@ -1704,7 +1695,7 @@ const char *
 cfg_obj_asstring(const cfg_obj_t *obj) {
        REQUIRE(VALID_CFGOBJ(obj));
        REQUIRE(obj->type->rep == &cfg_rep_string);
-       return obj->value.string.base;
+       return obj->value.string;
 }
 
 /* Quoted string only */
@@ -1949,7 +1940,7 @@ print_optional_btext(cfg_printer_t *pctx, const cfg_obj_t *obj) {
 
        pctx->indent++;
        cfg_print_cstr(pctx, "{");
-       cfg_print_chars(pctx, obj->value.string.base, obj->value.string.length);
+       cfg_print_chars(pctx, obj->value.string, strlen(obj->value.string));
        print_close(pctx);
 }
 
@@ -2050,7 +2041,9 @@ create_list(cfg_obj_t *file, size_t line, const cfg_type_t *type,
        REQUIRE(obj != NULL && *obj == NULL);
 
        cfg_obj_create(file, line, type, obj);
-       ISC_LIST_INIT((*obj)->value.list);
+       (*obj)->value.list = isc_mem_get(isc_g_mctx,
+                                        sizeof(*(*obj)->value.list));
+       ISC_LIST_INIT(*(*obj)->value.list);
 }
 
 void
@@ -2076,9 +2069,10 @@ free_listelt(cfg_listelt_t **eltp) {
 
 static void
 free_list(cfg_obj_t *obj) {
-       ISC_LIST_FOREACH(obj->value.list, elt, link) {
+       ISC_LIST_FOREACH(*obj->value.list, elt, link) {
                free_listelt(&elt);
        }
+       isc_mem_put(isc_g_mctx, obj->value.list, sizeof(*obj->value.list));
 }
 
 isc_result_t
@@ -2124,7 +2118,7 @@ parse_list(cfg_parser_t *pctx, const cfg_type_t *listtype, cfg_obj_t **ret) {
                }
                CHECK(cfg_parse_listelt(pctx, listobj, listof, &elt));
                CHECK(parse_semicolon(pctx));
-               ISC_LIST_APPEND(listobj->value.list, elt, link);
+               ISC_LIST_APPEND(*listobj->value.list, elt, link);
                elt = NULL;
        }
        *ret = listobj;
@@ -2144,7 +2138,7 @@ print_list(cfg_printer_t *pctx, const cfg_obj_t *obj) {
 
        REQUIRE(VALID_CFGOBJ(obj));
 
-       list = UNCONST(&obj->value.list);
+       list = UNCONST(obj->value.list);
        ISC_LIST_FOREACH(*list, elt, link) {
                if ((pctx->flags & CFG_PRINTER_ONELINE) != 0) {
                        cfg_print_obj(pctx, elt->obj);
@@ -2224,7 +2218,7 @@ cfg_parse_spacelist(cfg_parser_t *pctx, const cfg_type_t *listtype,
                        break;
                }
                CHECK(cfg_parse_listelt(pctx, listobj, listof, &elt));
-               ISC_LIST_APPEND(listobj->value.list, elt, link);
+               ISC_LIST_APPEND(*listobj->value.list, elt, link);
        }
        *ret = listobj;
        return ISC_R_SUCCESS;
@@ -2241,7 +2235,7 @@ cfg_print_spacelist(cfg_printer_t *pctx, const cfg_obj_t *obj) {
        REQUIRE(pctx != NULL);
        REQUIRE(VALID_CFGOBJ(obj));
 
-       list = UNCONST(&obj->value.list);
+       list = UNCONST(obj->value.list);
 
        ISC_LIST_FOREACH(*list, elt, link) {
                cfg_print_obj(pctx, elt->obj);
@@ -2264,7 +2258,7 @@ cfg_list_first(const cfg_obj_t *obj) {
        if (obj == NULL) {
                return NULL;
        }
-       return ISC_LIST_HEAD(obj->value.list);
+       return ISC_LIST_HEAD(*obj->value.list);
 }
 
 const cfg_listelt_t *
@@ -2276,7 +2270,7 @@ cfg_list_next(const cfg_listelt_t *elt) {
 void
 cfg_list_unlink(cfg_obj_t *list, cfg_listelt_t *elt) {
        REQUIRE(VALID_CFGOBJ(list));
-       ISC_LIST_UNLINK(list->value.list, elt, link);
+       ISC_LIST_UNLINK(*list->value.list, elt, link);
        free_listelt(&elt);
 }
 
@@ -2342,7 +2336,7 @@ cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
 
        create_map(pctx, type, &obj);
 
-       obj->value.map.clausesets = clausesets;
+       obj->value.map->clausesets = clausesets;
 
        for (;;) {
                /*
@@ -2372,7 +2366,7 @@ cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
                                            &includename));
                        CHECK(parse_semicolon(pctx));
 
-                       if (includename->value.string.length == 0) {
+                       if (includename->value.string[0] == 0) {
                                CLEANUP(ISC_R_FILENOTFOUND);
                        }
 
@@ -2498,7 +2492,7 @@ cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
                                    &cfg_type_implicitlist, &listobj);
                        symval.as_pointer = listobj;
                        result = isc_symtab_define_and_return(
-                               obj->value.map.symtab, clause->name,
+                               obj->value.map->symtab, clause->name,
                                SYMTAB_DUMMY_TYPE, symval, isc_symexists_reject,
                                &symval);
                        if (result == ISC_R_EXISTS) {
@@ -2508,12 +2502,12 @@ cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
 
                        CHECK(cfg_parse_listelt(pctx, listobj, clause->type,
                                                &elt));
-                       ISC_LIST_APPEND(listobj->value.list, elt, link);
+                       ISC_LIST_APPEND(*listobj->value.list, elt, link);
                        CHECK(parse_semicolon(pctx));
                } else {
                        /* Single-valued clause */
                        result = parse_symtab_elt(pctx, clause,
-                                                 obj->value.map.symtab);
+                                                 obj->value.map->symtab);
                        if (result == ISC_R_EXISTS) {
                                cfg_parser_error(pctx, CFG_LOG_NEAR,
                                                 "'%s' redefined",
@@ -2628,7 +2622,7 @@ parse_any_named_map(cfg_parser_t *pctx, cfg_type_t *nametype,
 
        CHECK(cfg_parse_obj(pctx, nametype, &idobj));
        CHECK(cfg_parse_map(pctx, type, &mapobj));
-       mapobj->value.map.id = idobj;
+       mapobj->value.map->id = idobj;
        *ret = mapobj;
        return result;
 cleanup:
@@ -2691,7 +2685,7 @@ cfg_print_mapbody(cfg_printer_t *pctx, const cfg_obj_t *obj) {
        REQUIRE(pctx != NULL);
        REQUIRE(VALID_CFGOBJ(obj));
 
-       for (clauseset = obj->value.map.clausesets; *clauseset != NULL;
+       for (clauseset = obj->value.map->clausesets; *clauseset != NULL;
             clauseset++)
        {
                isc_symvalue_t symval;
@@ -2704,14 +2698,14 @@ cfg_print_mapbody(cfg_printer_t *pctx, const cfg_obj_t *obj) {
                                continue;
                        }
 
-                       result = isc_symtab_lookup(obj->value.map.symtab,
+                       result = isc_symtab_lookup(obj->value.map->symtab,
                                                   clause->name,
                                                   SYMTAB_DUMMY_TYPE, &symval);
                        if (result == ISC_R_SUCCESS) {
                                cfg_obj_t *symobj = symval.as_pointer;
                                if (symobj->type == &cfg_type_implicitlist) {
                                        /* Multivalued. */
-                                       cfg_list_t *list = &symobj->value.list;
+                                       cfg_list_t *list = symobj->value.list;
                                        ISC_LIST_FOREACH(*list, elt, link) {
                                                print_symval(pctx, clause->name,
                                                             elt->obj);
@@ -2798,8 +2792,8 @@ cfg_print_map(cfg_printer_t *pctx, const cfg_obj_t *obj) {
        REQUIRE(pctx != NULL);
        REQUIRE(VALID_CFGOBJ(obj));
 
-       if (obj->value.map.id != NULL) {
-               cfg_print_obj(pctx, obj->value.map.id);
+       if (obj->value.map->id != NULL) {
+               cfg_print_obj(pctx, obj->value.map->id);
                cfg_print_cstr(pctx, " ");
        }
        print_open(pctx);
@@ -2870,7 +2864,7 @@ cfg_map_get(const cfg_obj_t *mapobj, const char *name, const cfg_obj_t **obj) {
        REQUIRE(name != NULL);
        REQUIRE(obj != NULL && *obj == NULL);
 
-       map = &mapobj->value.map;
+       map = mapobj->value.map;
 
        RETERR(isc_symtab_lookup(map->symtab, name, SYMTAB_DUMMY_TYPE, &val));
        *obj = val.as_pointer;
@@ -2881,7 +2875,7 @@ const cfg_obj_t *
 cfg_map_getname(const cfg_obj_t *mapobj) {
        REQUIRE(VALID_CFGOBJ(mapobj));
        REQUIRE(mapobj->type->rep == &cfg_rep_map);
-       return mapobj->value.map.id;
+       return mapobj->value.map->id;
 }
 
 unsigned int
@@ -2891,7 +2885,7 @@ cfg_map_count(const cfg_obj_t *mapobj) {
        REQUIRE(VALID_CFGOBJ(mapobj));
        REQUIRE(mapobj->type->rep == &cfg_rep_map);
 
-       map = &mapobj->value.map;
+       map = mapobj->value.map;
        return isc_symtab_count(map->symtab);
 }
 
@@ -2961,6 +2955,17 @@ cfg_map_findclause(const cfg_type_t *map, const char *name) {
        return ((cfg_clausedef_t *)clauses) + idx;
 }
 
+static char *
+region_to_string(isc_region_t region) {
+       size_t len = region.length + 1;
+       char *str = isc_mem_allocate(isc_g_mctx, len);
+
+       memmove(str, region.base, region.length);
+       str[region.length] = 0;
+
+       return str;
+}
+
 /* Parse an arbitrary token, storing its raw text representation. */
 static isc_result_t
 parse_token(cfg_parser_t *pctx, const cfg_type_t *type ISC_ATTR_UNUSED,
@@ -2978,11 +2983,8 @@ parse_token(cfg_parser_t *pctx, const cfg_type_t *type ISC_ATTR_UNUSED,
        }
 
        isc_lex_getlasttokentext(pctx->lexer, &pctx->token, &r);
+       obj->value.string = region_to_string(r);
 
-       obj->value.string.base = isc_mem_get(isc_g_mctx, r.length + 1);
-       obj->value.string.length = r.length;
-       memmove(obj->value.string.base, r.base, r.length);
-       obj->value.string.base[r.length] = '\0';
        *ret = obj;
        return result;
 
@@ -3032,7 +3034,7 @@ parse_unsupported(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
                }
 
                CHECK(cfg_parse_listelt(pctx, listobj, &cfg_type_token, &elt));
-               ISC_LIST_APPEND(listobj->value.list, elt, link);
+               ISC_LIST_APPEND(*listobj->value.list, elt, link);
        }
        INSIST(braces == 0);
        *ret = listobj;
@@ -3404,16 +3406,6 @@ cfg_type_t cfg_type_netprefix = { "netprefix",         cfg_parse_netprefix,
                                  print_netprefix,    cfg_doc_terminal,
                                  &cfg_rep_netprefix, NULL };
 
-static void
-copy_textregion(isc_mem_t *mctx, isc_textregion_t *dest, isc_textregion_t src) {
-       size_t dest_mem_length = (dest->base != NULL) ? dest->length + 1 : 0;
-       dest->base = isc_mem_creget(mctx, dest->base, dest_mem_length,
-                                   src.length + 1, sizeof(char));
-       dest->length = src.length;
-       memmove(dest->base, src.base, src.length);
-       dest->base[dest->length] = '\0';
-}
-
 static isc_result_t
 parse_sockaddrsub(cfg_parser_t *pctx, const cfg_type_t *type, int flags,
                  cfg_obj_t **ret) {
@@ -3423,12 +3415,10 @@ parse_sockaddrsub(cfg_parser_t *pctx, const cfg_type_t *type, int flags,
        cfg_obj_t *obj = NULL;
        int have_address = 0;
        int have_port = 0;
-       int have_tls = 0;
        int is_port_ok = (flags & CFG_ADDR_PORTOK) != 0;
        int is_tls_ok = (flags & CFG_ADDR_TLSOK) != 0;
        int is_address_ok = (flags & CFG_ADDR_TRAILINGOK) != 0;
-
-       isc_textregion_t tls = { .base = NULL, .length = 0 };
+       char *tls = NULL;
 
        CHECK(cfg_peektoken(pctx, 0));
        if (cfg_lookingat_netaddr(pctx, flags)) {
@@ -3457,10 +3447,15 @@ parse_sockaddrsub(cfg_parser_t *pctx, const cfg_type_t *type, int flags,
                                CHECK(cfg_gettoken(pctx, 0)); /* read "tls" */
                                CHECK(cfg_getstringtoken(pctx));
 
-                               isc_textregion_t tok = TOKEN_REGION(pctx);
-                               copy_textregion(isc_g_mctx, &tls, tok);
+                               if (tls != NULL) {
+                                       cfg_parser_error(
+                                               pctx, 0,
+                                               "expected at most one tls");
+                                       CLEANUP(ISC_R_UNEXPECTEDTOKEN);
+                               }
 
-                               ++have_tls;
+                               tls = region_to_string(
+                                       pctx->token.value.as_region);
                        } else {
                                break;
                        }
@@ -3483,25 +3478,27 @@ parse_sockaddrsub(cfg_parser_t *pctx, const cfg_type_t *type, int flags,
                CLEANUP(ISC_R_UNEXPECTEDTOKEN);
        }
 
-       if (have_tls > 1) {
-               cfg_parser_error(pctx, 0, "expected at most one tls");
-               CLEANUP(ISC_R_UNEXPECTEDTOKEN);
-       }
-
        cfg_obj_create(cfg_parser_currentfile(pctx), pctx->line, type, &obj);
-       if (have_tls == 1) {
-               obj->value.sockaddrtls.tls = tls;
+
+       if (is_tls_ok != 0) {
+               obj->value.sockaddrtls = isc_mem_cget(
+                       isc_g_mctx, 1, sizeof(*obj->value.sockaddrtls));
+               isc_sockaddr_fromnetaddr(&obj->value.sockaddrtls->sockaddr,
+                                        &netaddr, port);
+               obj->value.sockaddrtls->tls = tls;
+               tls = NULL;
+       } else {
+               obj->value.sockaddr = isc_mem_get(isc_g_mctx,
+                                                 sizeof(*obj->value.sockaddr));
+               isc_sockaddr_fromnetaddr(obj->value.sockaddr, &netaddr, port);
        }
-       obj->value.sockaddrtls.sockaddr = isc_mem_get(isc_g_mctx,
-                                                     sizeof(isc_sockaddr_t));
-       isc_sockaddr_fromnetaddr(obj->value.sockaddrtls.sockaddr, &netaddr,
-                                port);
+
        *ret = obj;
        return ISC_R_SUCCESS;
 
 cleanup:
-       if (tls.base != NULL) {
-               isc_mem_put(isc_g_mctx, tls.base, tls.length + 1);
+       if (tls != NULL) {
+               isc_mem_free(isc_g_mctx, tls);
        }
        CLEANUP_OBJ(obj);
        return result;
@@ -3552,21 +3549,30 @@ cfg_print_sockaddr(cfg_printer_t *pctx, const cfg_obj_t *obj) {
        isc_netaddr_t netaddr;
        in_port_t port;
        char buf[ISC_NETADDR_FORMATSIZE];
+       isc_sockaddr_t *sockaddr;
+       bool tls = false;
 
        REQUIRE(pctx != NULL);
        REQUIRE(VALID_CFGOBJ(obj));
 
-       isc_netaddr_fromsockaddr(&netaddr, obj->value.sockaddr);
+       if (obj->type == &cfg_type_sockaddrtls) {
+               sockaddr = &obj->value.sockaddrtls->sockaddr;
+               tls = true;
+       } else {
+               sockaddr = obj->value.sockaddr;
+       }
+
+       isc_netaddr_fromsockaddr(&netaddr, sockaddr);
        isc_netaddr_format(&netaddr, buf, sizeof(buf));
        cfg_print_cstr(pctx, buf);
-       port = isc_sockaddr_getport(obj->value.sockaddr);
+       port = isc_sockaddr_getport(sockaddr);
        if (port != 0) {
                cfg_print_cstr(pctx, " port ");
                cfg_print_rawuint(pctx, port);
        }
-       if (obj->value.sockaddrtls.tls.base != NULL) {
+       if (tls && obj->value.sockaddrtls->tls != NULL) {
                cfg_print_cstr(pctx, " tls ");
-               print_rawqstring(pctx, obj->value.sockaddrtls.tls);
+               print_rawqstring(pctx, obj->value.sockaddrtls->tls);
        }
 }
 
@@ -3637,7 +3643,7 @@ const char *
 cfg_obj_getsockaddrtls(const cfg_obj_t *obj) {
        REQUIRE(VALID_CFGOBJ(obj));
        REQUIRE(obj->type->rep == &cfg_rep_sockaddrtls);
-       return obj->value.sockaddrtls.tls.base;
+       return obj->value.sockaddrtls->tls;
 }
 
 isc_result_t
@@ -3671,11 +3677,11 @@ redo:
                                 */
                                cfg_listelt_t *elt;
                                elt = ISC_LIST_TAIL(
-                                       pctx->open_files->value.list);
+                                       *pctx->open_files->value.list);
                                INSIST(elt != NULL);
-                               ISC_LIST_UNLINK(pctx->open_files->value.list,
+                               ISC_LIST_UNLINK(*pctx->open_files->value.list,
                                                elt, link);
-                               ISC_LIST_APPEND(pctx->closed_files->value.list,
+                               ISC_LIST_APPEND(*pctx->closed_files->value.list,
                                                elt, link);
                                goto redo;
                        }
@@ -3917,16 +3923,18 @@ create_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
        cfg_obj_create(cfg_parser_currentfile(pctx), pctx->line, type, &obj);
        isc_symtab_create(isc_g_mctx, map_symtabitem_destroy, pctx, false,
                          &symtab);
-       obj->value.map.symtab = symtab;
-       obj->value.map.id = NULL;
+
+       obj->value.map = isc_mem_cget(isc_g_mctx, 1, sizeof(*obj->value.map));
+       obj->value.map->symtab = symtab;
 
        *ret = obj;
 }
 
 static void
 free_map(cfg_obj_t *obj) {
-       CLEANUP_OBJ(obj->value.map.id);
-       isc_symtab_destroy(&obj->value.map.symtab);
+       CLEANUP_OBJ(obj->value.map->id);
+       isc_symtab_destroy(&obj->value.map->symtab);
+       isc_mem_put(isc_g_mctx, obj->value.map, sizeof(*obj->value.map));
 }
 
 bool
@@ -3994,7 +4002,7 @@ map_define(cfg_obj_t *mapobj, cfg_obj_t *obj, const cfg_clausedef_t *clause) {
        const cfg_map_t *map;
        isc_symvalue_t symval;
 
-       map = &mapobj->value.map;
+       map = mapobj->value.map;
        result = isc_symtab_lookup(map->symtab, clause->name, SYMTAB_DUMMY_TYPE,
                                   &symval);
        if (result == ISC_R_NOTFOUND) {
@@ -4006,7 +4014,7 @@ map_define(cfg_obj_t *mapobj, cfg_obj_t *obj, const cfg_clausedef_t *clause) {
                                    &cfg_type_implicitlist, &destobj);
                        cfg_listelt_create(&elt);
                        cfg_obj_attach(obj, &elt->obj);
-                       ISC_LIST_APPEND(destobj->value.list, elt, link);
+                       ISC_LIST_APPEND(*destobj->value.list, elt, link);
                        symval.as_pointer = destobj;
                } else {
                        symval.as_pointer = obj;
@@ -4025,7 +4033,7 @@ map_define(cfg_obj_t *mapobj, cfg_obj_t *obj, const cfg_clausedef_t *clause) {
                if (destobj->type == &cfg_type_implicitlist) {
                        cfg_listelt_create(&elt);
                        cfg_obj_attach(obj, &elt->obj);
-                       ISC_LIST_APPEND(destobj->value.list, elt, link);
+                       ISC_LIST_APPEND(*destobj->value.list, elt, link);
                } else {
                        result = ISC_R_EXISTS;
                }
@@ -4114,12 +4122,12 @@ cfg_list_addclone(cfg_obj_t *dst, const cfg_obj_t *src, bool prepend) {
                if (prepend) {
                        ISC_LIST_APPEND(list, dstelt, link);
                } else {
-                       ISC_LIST_APPEND(dst->value.list, dstelt, link);
+                       ISC_LIST_APPEND(*dst->value.list, dstelt, link);
                }
                srcelt = cfg_list_next(srcelt);
        }
        if (prepend) {
-               ISC_LIST_PREPENDLIST(dst->value.list, list, link);
+               ISC_LIST_PREPENDLIST(*dst->value.list, list, link);
        }
 }
 
index d817d3eeaf07e748c1066024defb54ad38d1c55c..90a5a3d94097a2837104e84170ab0a1679ebeb10 100644 (file)
@@ -233,6 +233,9 @@ options {\n\
        answer-cookie yes;\n\
        cookie-algorithm siphash24;\n\
        dump-file \"named_dump.db\";\n\
+       listen-on port 53 tls \"foobar\" {\n\
+               127.0.0.1/32;\n\
+       };\n\
        notify-rate 20;\n\
        allow-recursion {\n\
                \"localhost\";\n\
@@ -250,6 +253,9 @@ view \"_bind\" chaos {\n\
        zone \"version.bind\" chaos {\n\
                type primary;\n\
                database \"_builtin version\";\n\
+               update-policy {\n\
+                       grant \"int\" zonesub \"any\";\n\
+               };\n\
        };\n\
        max-cache-size 2097152;\n\
        rate-limit {\n\
@@ -257,6 +263,7 @@ view \"_bind\" chaos {\n\
                slip 0;\n\
        };\n\
 };\n";
+
        isc_buffer_init(&buf, conf, sizeof(conf));
        isc_buffer_add(&buf, sizeof(conf) - 1);