From a3e0e69196cc5e3420ebb1a83b026ee36cbaab83 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 4 Sep 2005 20:17:21 +0000 Subject: r10030: Add hierarchical memory allocation to TDR's pull functions (This used to be commit 0e358de93a007db921ad5e9a892114122254de39) --- source4/lib/registry/config.mk | 1 - source4/lib/registry/reg_backend_nt4.c | 61 ++++++++++++++------------------ source4/lib/tdr/TODO | 1 - source4/lib/tdr/tdr.c | 28 +++++++-------- source4/lib/tdr/tdr.h | 6 ++-- source4/pidl/lib/Parse/Pidl/Samba/TDR.pm | 23 +++++++----- 6 files changed, 59 insertions(+), 61 deletions(-) diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index a1bb62f7df..43149f88aa 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -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 ################################################ diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index 4a3576f85e..f31a2f52e7 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -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; } diff --git a/source4/lib/tdr/TODO b/source4/lib/tdr/TODO index 93c9cb255f..5093afd438 100644 --- a/source4/lib/tdr/TODO +++ b/source4/lib/tdr/TODO @@ -1,2 +1 @@ - Support read/write (to fd) as well as push/pull (to DATA_BLOB) -- Specify memory context explicitly diff --git a/source4/lib/tdr/tdr.c b/source4/lib/tdr/tdr.c index fdb6f1ca6e..34611683e2 100644 --- a/source4/lib/tdr/tdr.c +++ b/source4/lib/tdr/tdr.c @@ -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; diff --git a/source4/lib/tdr/tdr.h b/source4/lib/tdr/tdr.h index fdd877f41d..f882a63275 100644 --- a/source4/lib/tdr/tdr.h +++ b/source4/lib/tdr/tdr.h @@ -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 *); diff --git a/source4/pidl/lib/Parse/Pidl/Samba/TDR.pm b/source4/pidl/lib/Parse/Pidl/Samba/TDR.pm index 041170c152..9bcf7f1a77 100644 --- a/source4/pidl/lib/Parse/Pidl/Samba/TDR.pm +++ b/source4/pidl/lib/Parse/Pidl/Samba/TDR.pm @@ -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);"; } -- cgit