r10030: Add hierarchical memory allocation to TDR's pull functions
authorJelmer Vernooij <jelmer@samba.org>
Sun, 4 Sep 2005 20:17:21 +0000 (20:17 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:36:31 +0000 (13:36 -0500)
(This used to be commit 0e358de93a007db921ad5e9a892114122254de39)

source4/lib/registry/config.mk
source4/lib/registry/reg_backend_nt4.c
source4/lib/tdr/TODO
source4/lib/tdr/tdr.c
source4/lib/tdr/tdr.h
source4/pidl/lib/Parse/Pidl/Samba/TDR.pm

index a1bb62f7df182fae732704d874c498fe6f43cb7d..43149f88aa9796a9573874ab52a3c86e6ab02d6d 100644 (file)
@@ -17,7 +17,6 @@ NOPROTO = YES
 INIT_OBJ_FILES = lib/registry/tdr_regf.o
 
 lib/registry/tdr_regf.c: lib/registry/regf.idl
-       @echo "Compiling lib/registry/regf.idl"
        @./pidl/pidl --header --outputdir=lib/registry --parse --tdr-header --tdr-parser -- lib/registry/regf.idl
 
 ################################################
index 4a3576f85eeed56af42e13cc32c1a413d4de1001..f31a2f52e7e2a00c641a5c59fe17afe3aaff3919 100644 (file)
@@ -104,28 +104,23 @@ static DATA_BLOB hbin_get(const struct regf_data *data, uint32_t offset)
        return ret;
 }
 
-static BOOL hbin_get_tdr (struct regf_data *regf, uint32_t offset, tdr_pull_fn_t pull_fn, void *p)
+static BOOL hbin_get_tdr (struct regf_data *regf, uint32_t offset, TALLOC_CTX *ctx, tdr_pull_fn_t pull_fn, void *p)
 {
-       DATA_BLOB data;
-       struct tdr_pull *pull;
+       struct tdr_pull pull;
 
-       data = hbin_get(regf, offset);
-       if (!data.data) {
+       ZERO_STRUCT(pull);
+
+       pull.data = hbin_get(regf, offset);
+       if (!pull.data.data) {
                DEBUG(1, ("Unable to get data at 0x%04x\n", offset));
                return False;
        }
        
-       pull = talloc_zero(regf, struct tdr_pull);
-       pull->data = data;
-
-       if (NT_STATUS_IS_ERR(pull_fn(pull, p))) {
+       if (NT_STATUS_IS_ERR(pull_fn(&pull, ctx, p))) {
                DEBUG(1, ("Error parsing record at 0x%04x using tdr\n", offset));
-               talloc_free(pull);
                return False;
        }
 
-       /* FIXME: Free pull ! */
-
        return True;
 }
 
@@ -397,7 +392,7 @@ static struct registry_key *regf_get_key (TALLOC_CTX *ctx, struct regf_data *reg
 
        ret = talloc_zero(ctx, struct registry_key);
        nk = talloc(ret, struct nk_block);
-       if (!hbin_get_tdr(regf, offset, (tdr_pull_fn_t)tdr_pull_nk_block, nk)) {
+       if (!hbin_get_tdr(regf, offset, nk, (tdr_pull_fn_t)tdr_pull_nk_block, nk)) {
                DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset));
                return NULL;
        }
@@ -451,7 +446,7 @@ static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx
        if (!vk)
                return WERR_NOMEM;
        
-       if (!hbin_get_tdr(regf, vk_offset, (tdr_pull_fn_t)tdr_pull_vk_block, vk)) {
+       if (!hbin_get_tdr(regf, vk_offset, vk, (tdr_pull_fn_t)tdr_pull_vk_block, vk)) {
                DEBUG(0, ("Unable to get VK block at %d\n", vk_offset));
                return WERR_GENERAL_FAILURE;
        }
@@ -493,12 +488,13 @@ static WERROR regf_get_subkey (TALLOC_CTX *ctx, struct registry_key *key, int id
                SMB_ASSERT(0);
        } else if (!strncmp((char *)data.data, "lf", 2)) {
                struct lf_block lf;
-               struct tdr_pull *pull = talloc_zero(ctx, struct tdr_pull);
+               struct tdr_pull pull;
 
                DEBUG(10, ("Subkeys in LF list\n"));
-               pull->data = data;
+               ZERO_STRUCT(pull);
+               pull.data = data;
 
-               if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, &lf))) {
+               if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, nk, &lf))) {
                        DEBUG(0, ("Error parsing LF list\n"));
                        return WERR_GENERAL_FAILURE;
                }
@@ -509,8 +505,6 @@ static WERROR regf_get_subkey (TALLOC_CTX *ctx, struct registry_key *key, int id
                }
 
                key_off = lf.hr[idx].nk_off;
-               
-               talloc_free(pull);
        } else if (!strncmp((char *)data.data, "ri", 2)) {
                DEBUG(4, ("Subkeys in RI list\n"));
                SMB_ASSERT(0);
@@ -541,7 +535,7 @@ static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, struct registry_key *key, struc
        struct regf_data *regf = key->hive->backend_data;
        DATA_BLOB data;
 
-       if (!hbin_get_tdr(regf, nk->sk_offset, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
+       if (!hbin_get_tdr(regf, nk->sk_offset, ctx, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
                DEBUG(0, ("Unable to find security descriptor\n"));
                return WERR_GENERAL_FAILURE;
        }
@@ -576,7 +570,7 @@ static uint32_t lf_add_entry (struct regf_data *regf, uint32_t list_offset, cons
                lf.key_count = 0;
                lf.hr = NULL;
        } else {
-               if (!hbin_get_tdr(regf, list_offset, (tdr_pull_fn_t)tdr_pull_lf_block, &lf)) {
+               if (!hbin_get_tdr(regf, list_offset, regf, (tdr_pull_fn_t)tdr_pull_lf_block, &lf)) {
                        DEBUG(0, ("Can't get subkeys list\n"));
                        return -1;
                }
@@ -588,6 +582,8 @@ static uint32_t lf_add_entry (struct regf_data *regf, uint32_t list_offset, cons
        lf.key_count++;
 
        ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t)tdr_push_lf_block, list_offset, &lf);
+
+       talloc_free(lf.hr);
        
        return ret;
 }
@@ -678,7 +674,7 @@ static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key)
 {
        struct regf_data *regf;
        struct regf_hdr *regf_hdr;
-       struct tdr_pull *pull;
+       struct tdr_pull pull;
        int i;
 
        regf = (struct regf_data *)talloc_zero(h, struct regf_data);
@@ -695,19 +691,16 @@ static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key)
                return WERR_GENERAL_FAILURE;
        }
 
-       pull = talloc_zero(regf, struct tdr_pull);
-       if (!pull)
-               return WERR_NOMEM;
-
-       pull->data.data = (uint8_t*)fd_load(regf->fd, &pull->data.length, regf);
+       ZERO_STRUCT(pull);
+       pull.data.data = (uint8_t*)fd_load(regf->fd, &pull.data.length, regf);
 
-       if (pull->data.data == NULL) {
+       if (pull.data.data == NULL) {
                DEBUG(0, ("Error reading data\n"));
                return WERR_GENERAL_FAILURE;
        }
 
        regf_hdr = talloc(regf, struct regf_hdr);
-       if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(pull, regf_hdr))) {
+       if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(&pull, regf_hdr, regf_hdr))) {
                return WERR_GENERAL_FAILURE;
        }
 
@@ -726,23 +719,23 @@ static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key)
        /*
         * Validate the header ...
         */
-       if (regf_hdr_checksum(pull->data.data) != regf_hdr->chksum) {
+       if (regf_hdr_checksum(pull.data.data) != regf_hdr->chksum) {
                DEBUG(0, ("Registry file checksum error: %s: %d,%d\n",
-                                 h->location, regf_hdr->chksum, regf_hdr_checksum(pull->data.data)));
+                                 h->location, regf_hdr->chksum, regf_hdr_checksum(pull.data.data)));
                return WERR_GENERAL_FAILURE;
        }
 
-       pull->offset = 0x1000;
+       pull.offset = 0x1000;
 
        i = 0;
        /* Read in all hbin blocks */
        regf->hbins = talloc_array(regf, struct hbin_block *, 1);
        regf->hbins[0] = NULL;
 
-       while (pull->offset < pull->data.length) {
+       while (pull.offset < pull.data.length) {
                struct hbin_block *hbin = talloc(regf->hbins, struct hbin_block);
 
-               if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(pull, hbin))) {
+               if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(&pull, hbin, hbin))) {
                        DEBUG(0, ("[%d] Error parsing HBIN block\n", i));
                        return WERR_FOOBAR;
                }
index 93c9cb255f0a0eb466239decaf5532a871e3f027..5093afd438716d0e162bc7e77eaf1b47c6da7eec 100644 (file)
@@ -1,2 +1 @@
 - Support read/write (to fd) as well as push/pull (to DATA_BLOB)
-- Specify memory context explicitly
index fdb6f1ca6e61fb6135f7fe5387d7afe48d3939ed..34611683e2847da2ea23542d14f1aed6c39f7ce1 100644 (file)
@@ -64,7 +64,7 @@ NTSTATUS tdr_push_expand(struct tdr_push *tdr, uint32_t size)
 }
 
 
-NTSTATUS tdr_pull_uint8(struct tdr_pull *tdr, uint8_t *v)
+NTSTATUS tdr_pull_uint8(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint8_t *v)
 {
        TDR_PULL_NEED_BYTES(tdr, 1);
        *v = TDR_CVAL(tdr, tdr->offset);
@@ -86,7 +86,7 @@ NTSTATUS tdr_print_uint8(struct tdr_print *tdr, const char *name, uint8_t *v)
        return NT_STATUS_OK;
 }
 
-NTSTATUS tdr_pull_uint16(struct tdr_pull *tdr, uint16_t *v)
+NTSTATUS tdr_pull_uint16(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint16_t *v)
 {
        TDR_PULL_NEED_BYTES(tdr, 2);
        *v = TDR_SVAL(tdr, tdr->offset);
@@ -108,7 +108,7 @@ NTSTATUS tdr_print_uint16(struct tdr_print *tdr, const char *name, uint16_t *v)
        return NT_STATUS_OK;
 }
 
-NTSTATUS tdr_pull_uint32(struct tdr_pull *tdr, uint32_t *v)
+NTSTATUS tdr_pull_uint32(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint32_t *v)
 {
        TDR_PULL_NEED_BYTES(tdr, 4);
        *v = TDR_IVAL(tdr, tdr->offset);
@@ -130,7 +130,7 @@ NTSTATUS tdr_print_uint32(struct tdr_print *tdr, const char *name, uint32_t *v)
        return NT_STATUS_OK;
 }
 
-NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, const char **v, uint32_t length, uint32_t el_size, int chset)
+NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, TALLOC_CTX *ctx, const char **v, uint32_t length, uint32_t el_size, int chset)
 {
        int ret;
 
@@ -149,13 +149,13 @@ NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, const char **v, uint32_t length,
        }
 
        if (length == 0) {
-               *v = talloc_strdup(tdr, "");
+               *v = talloc_strdup(ctx, "");
                return NT_STATUS_OK;
        }
 
        TDR_PULL_NEED_BYTES(tdr, el_size*length);
        
-       ret = convert_string_talloc(tdr, chset, CH_UNIX, tdr->data.data+tdr->offset, el_size*length, discard_const_p(void *, v));
+       ret = convert_string_talloc(ctx, chset, CH_UNIX, tdr->data.data+tdr->offset, el_size*length, discard_const_p(void *, v));
 
        if (ret == -1) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -198,10 +198,10 @@ NTSTATUS tdr_print_charset(struct tdr_print *tdr, const char *name, const char *
 /*
   pull a ipv4address
 */
-NTSTATUS tdr_pull_ipv4address(struct tdr_pull *tdr, const char **address)
+NTSTATUS tdr_pull_ipv4address(struct tdr_pull *tdr, TALLOC_CTX *ctx, const char **address)
 {
        struct ipv4_addr in;
-       TDR_CHECK(tdr_pull_uint32(tdr, &in.addr));
+       TDR_CHECK(tdr_pull_uint32(tdr, ctx, &in.addr));
        in.addr = htonl(in.addr);
        *address = talloc_strdup(tdr, sys_inet_ntoa(in));
        NT_STATUS_HAVE_NO_MEMORY(*address);
@@ -231,7 +231,7 @@ NTSTATUS tdr_print_ipv4address(struct tdr_print *tdr, const char *name,
 /*
   parse a hyper
 */
-NTSTATUS tdr_pull_hyper(struct tdr_pull *tdr, uint64_t *v)
+NTSTATUS tdr_pull_hyper(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint64_t *v)
 {
        TDR_PULL_NEED_BYTES(tdr, 8);
        *v = TDR_IVAL(tdr, tdr->offset);
@@ -266,9 +266,9 @@ NTSTATUS tdr_push_NTTIME(struct tdr_push *tdr, NTTIME *t)
 /*
   pull a NTTIME
 */
-NTSTATUS tdr_pull_NTTIME(struct tdr_pull *tdr, NTTIME *t)
+NTSTATUS tdr_pull_NTTIME(struct tdr_pull *tdr, TALLOC_CTX *ctx, NTTIME *t)
 {
-       TDR_CHECK(tdr_pull_hyper(tdr, t));
+       TDR_CHECK(tdr_pull_hyper(tdr, ctx, t));
        return NT_STATUS_OK;
 }
 
@@ -283,10 +283,10 @@ NTSTATUS tdr_push_time_t(struct tdr_push *tdr, time_t *t)
 /*
   pull a time_t
 */
-NTSTATUS tdr_pull_time_t(struct tdr_pull *tdr, time_t *t)
+NTSTATUS tdr_pull_time_t(struct tdr_pull *tdr, TALLOC_CTX *ctx, time_t *t)
 {
        uint32_t tt;
-       TDR_CHECK(tdr_pull_uint32(tdr, &tt));
+       TDR_CHECK(tdr_pull_uint32(tdr, ctx, &tt));
        *t = tt;
        return NT_STATUS_OK;
 }
@@ -343,7 +343,7 @@ NTSTATUS tdr_push_DATA_BLOB(struct tdr_push *tdr, DATA_BLOB *blob)
 /*
   pull a DATA_BLOB from the wire. 
 */
-NTSTATUS tdr_pull_DATA_BLOB(struct tdr_pull *tdr, DATA_BLOB *blob)
+NTSTATUS tdr_pull_DATA_BLOB(struct tdr_pull *tdr, TALLOC_CTX *ctx, DATA_BLOB *blob)
 {
        uint32_t length;
 
index fdd877f41d2ee67f18e820bfb658a822a8bad44b..f882a632750516e583e71d083a218ea28203084b 100644 (file)
@@ -47,10 +47,10 @@ struct tdr_print {
                                 return _status; \
                         } while (0)
 
-#define TDR_ALLOC(tdr, s, n) do { \
-                              (s) = talloc_array_size(tdr, sizeof(*(s)), n); \
+#define TDR_ALLOC(ctx, s, n) do { \
+                              (s) = talloc_array_size(ctx, sizeof(*(s)), n); \
                            if ((n) && !(s)) return NT_STATUS_NO_MEMORY; \
                            } while (0)
 
 typedef NTSTATUS (*tdr_push_fn_t) (struct tdr_push *, const void *);
-typedef NTSTATUS (*tdr_pull_fn_t) (struct tdr_pull *, void *);
+typedef NTSTATUS (*tdr_pull_fn_t) (struct tdr_pull *, TALLOC_CTX *, void *);
index 041170c152c9346fba61ad69b46f42708af9f122..9bcf7f1a77b66977a8a065ee87bf4db157e60365 100644 (file)
@@ -17,9 +17,10 @@ sub deindent() { $tabs = substr($tabs, 1); }
 sub pidl($) { $ret .= $tabs.(shift)."\n"; }
 sub fatal($$) { my ($e,$s) = @_; die("$e->{FILE}:$e->{LINE}: $s\n"); }
 sub static($) { my $p = shift; return("static ") unless ($p); return ""; }
-sub printarg($) { 
+sub typearg($) { 
        my $t = shift; 
        return(", const char *name") if ($t eq "print");
+       return(", TALLOC_CTX *mem_ctx") if ($t eq "pull");
        return("");
 }
 
@@ -41,6 +42,7 @@ sub ParserElement($$$)
        my $switch = "";
        my $array = "";
        my $name = "";
+       my $mem_ctx = "mem_ctx";
 
        fatal($e,"Pointers not supported in TDR") if ($e->{POINTERS} > 0);
        fatal($e,"size_is() not supported in TDR") if (has_property($e, "size_is"));
@@ -62,11 +64,11 @@ sub ParserElement($$$)
                
                my $len = ParseExpr(@{$e->{ARRAY_LEN}}[0], $env);
                if ($len eq "*") { $len = "-1"; }
+               $name = ", mem_ctx" if ($t eq "pull");
                pidl "TDR_CHECK(tdr_$t\_charset(tdr$name, &v->$e->{NAME}, $len, sizeof($e->{TYPE}_t), CH_$e->{PROPERTIES}->{charset}));";
                return;
        }
 
-
        if (has_property($e, "switch_is")) {
                $switch = ", " . ParseExpr($e->{PROPERTIES}->{switch_is}, $env);
        }
@@ -75,7 +77,8 @@ sub ParserElement($$$)
                my $len = ParseExpr($e->{ARRAY_LEN}[0], $env);
 
                if ($t eq "pull" and not is_constant($len)) {
-                       pidl "TDR_ALLOC(tdr, v->$e->{NAME}, $len);"
+                       pidl "TDR_ALLOC(mem_ctx, v->$e->{NAME}, $len);";
+                       $mem_ctx = "v->$e->{NAME}";
                }
 
                pidl "for (i = 0; i < $len; i++) {";
@@ -83,6 +86,10 @@ sub ParserElement($$$)
                $array = "[i]";
        }
 
+       if ($t eq "pull") {
+               $name = ", $mem_ctx";
+       }
+
        if (has_property($e, "value") && $t eq "push") {
                pidl "v->$e->{NAME} = ".ParseExpr($e->{PROPERTIES}->{value}, $env).";";
        }
@@ -102,7 +109,7 @@ sub ParserStruct($$$$)
 {
        my ($e,$n,$t,$p) = @_;
 
-       pidl static($p)."NTSTATUS tdr_$t\_$n (struct tdr_$t *tdr".printarg($t).", struct $n *v)";
+       pidl static($p)."NTSTATUS tdr_$t\_$n (struct tdr_$t *tdr".typearg($t).", struct $n *v)";
        pidl "{"; indent;
        pidl "int i;" if (ContainsArray($e));
 
@@ -128,7 +135,7 @@ sub ParserUnion($$$$)
 {
        my ($e,$n,$t,$p) = @_;
 
-       pidl static($p)."NTSTATUS tdr_$t\_$n(struct tdr_$t *tdr".printarg($t).", int level, union $n *v)";
+       pidl static($p)."NTSTATUS tdr_$t\_$n(struct tdr_$t *tdr".typearg($t).", int level, union $n *v)";
        pidl "{"; indent;
        pidl "int i;" if (ContainsArray($e));
 
@@ -169,11 +176,11 @@ sub ParserEnum($$$$)
        my ($e,$n,$t,$p) = @_;
        my $bt = ($e->{PROPERTIES}->{base_type} or "uint8");
        
-       pidl static($p)."NTSTATUS tdr_$t\_$n (struct tdr_$t *tdr".printarg($t).", enum $n *v)";
+       pidl static($p)."NTSTATUS tdr_$t\_$n (struct tdr_$t *tdr".typearg($t).", enum $n *v)";
        pidl "{";
        if ($t eq "pull") {
                pidl "\t$bt\_t r;";
-               pidl "\tTDR_CHECK(tdr_$t\_$bt(tdr, \&r));";
+               pidl "\tTDR_CHECK(tdr_$t\_$bt(tdr, mem_ctx, \&r));";
                pidl "\t*v = r;";
        } elsif ($t eq "push") {
                pidl "\tTDR_CHECK(tdr_$t\_$bt(tdr, ($bt\_t *)v));";
@@ -242,7 +249,7 @@ sub HeaderInterface($$)
                        # FIXME
                } else {
                        my ($n, $d) = ($e->{NAME}, lc($e->{DATA}->{TYPE}));
-                       pidl "NTSTATUS tdr_pull\_$n(struct tdr_pull *tdr$switch, $d $n *v);";
+                       pidl "NTSTATUS tdr_pull\_$n(struct tdr_pull *tdr, TALLOC_CTX *ctx$switch, $d $n *v);";
                        pidl "NTSTATUS tdr_print\_$n(struct tdr_print *tdr, const char *name$switch, $d $n *v);";
                        pidl "NTSTATUS tdr_push\_$n(struct tdr_push *tdr$switch, $d $n *v);";
                }