mirror of
https://github.com/samba-team/samba.git
synced 2025-03-11 16:58:40 +03:00
r9373: - create a hierachical memory tree with recursiv ndr_pull_* functions
- with this it's also possible to talloc_free() the ndr_pull structure and talloc_steal(ndr->current_mem_ctx); to fetch the whole data of the hierachical tree - if the toplevel struct is a valid talloc pointer it's also possible to use NDR_PULL_SET_MEM_CTX(ndr, mem_ctx); to the the toplevel pointer with the struct pointer (NOTE: no callers are using this yet, but they shortly will) metze
This commit is contained in:
parent
09de7e0af7
commit
1a2b836958
@ -836,6 +836,59 @@ sub CalcNdrFlags($$$)
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub ParseMemCtxPullStart($$$)
|
||||
{
|
||||
my $e = shift;
|
||||
my $l = shift;
|
||||
my $ptr_name = shift;
|
||||
|
||||
my $mem_r_ctx = "_mem_save_$e->{NAME}_$l->{LEVEL_INDEX}";
|
||||
my $mem_c_ctx = $ptr_name;
|
||||
my $mem_c_flags = "0";
|
||||
|
||||
return if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED});
|
||||
|
||||
if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) {
|
||||
my $nl = GetNextLevel($e, $l);
|
||||
my $next_is_array = ($nl->{TYPE} eq "ARRAY");
|
||||
my $next_is_string = (($nl->{TYPE} eq "DATA") and
|
||||
($nl->{DATA_TYPE} eq "string"));
|
||||
if ($next_is_array or $next_is_string) {
|
||||
return;
|
||||
} else {
|
||||
$mem_c_flags = "LIBNDR_FLAG_REF_ALLOC";
|
||||
}
|
||||
}
|
||||
|
||||
pidl "$mem_r_ctx = NDR_PULL_GET_MEM_CTX(ndr);";
|
||||
pidl "NDR_PULL_SET_MEM_CTX(ndr, $mem_c_ctx, $mem_c_flags);";
|
||||
}
|
||||
|
||||
sub ParseMemCtxPullEnd($$)
|
||||
{
|
||||
my $e = shift;
|
||||
my $l = shift;
|
||||
|
||||
my $mem_r_ctx = "_mem_save_$e->{NAME}_$l->{LEVEL_INDEX}";
|
||||
my $mem_r_flags = "0";
|
||||
|
||||
return if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED});
|
||||
|
||||
if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) {
|
||||
my $nl = GetNextLevel($e, $l);
|
||||
my $next_is_array = ($nl->{TYPE} eq "ARRAY");
|
||||
my $next_is_string = (($nl->{TYPE} eq "DATA") and
|
||||
($nl->{DATA_TYPE} eq "string"));
|
||||
if ($next_is_array or $next_is_string) {
|
||||
return;
|
||||
} else {
|
||||
$mem_r_flags = "LIBNDR_FLAG_REF_ALLOC";
|
||||
}
|
||||
}
|
||||
|
||||
pidl "NDR_PULL_SET_MEM_CTX(ndr, $mem_r_ctx, $mem_r_flags);";
|
||||
}
|
||||
|
||||
sub ParseElementPullLevel
|
||||
{
|
||||
my($e,$l,$ndr,$var_name,$env,$primitives,$deferred) = @_;
|
||||
@ -890,9 +943,13 @@ sub ParseElementPullLevel
|
||||
}
|
||||
}
|
||||
|
||||
ParseMemCtxPullStart($e,$l, $var_name);
|
||||
|
||||
$var_name = get_value_of($var_name);
|
||||
ParseElementPullLevel($e,GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 1);
|
||||
|
||||
ParseMemCtxPullEnd($e,$l);
|
||||
|
||||
if ($l->{POINTER_TYPE} ne "ref") {
|
||||
if ($l->{POINTER_TYPE} eq "relative") {
|
||||
pidl "ndr_pull_restore(ndr, &_relative_save);";
|
||||
@ -904,9 +961,12 @@ sub ParseElementPullLevel
|
||||
not has_fast_array($e,$l) and not has_property($e, "charset")) {
|
||||
my $length = ParseExpr($l->{LENGTH_IS}, $env);
|
||||
my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
|
||||
my $array_name = $var_name;
|
||||
|
||||
$var_name = $var_name . "[$counter]";
|
||||
|
||||
ParseMemCtxPullStart($e,$l, $array_name);
|
||||
|
||||
if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) {
|
||||
pidl "for ($counter = 0; $counter < $length; $counter++) {";
|
||||
indent;
|
||||
@ -927,6 +987,9 @@ sub ParseElementPullLevel
|
||||
deindent;
|
||||
pidl "}";
|
||||
}
|
||||
|
||||
ParseMemCtxPullEnd($e,$l);
|
||||
|
||||
} elsif ($l->{TYPE} eq "SWITCH") {
|
||||
ParseElementPullLevel($e,GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred);
|
||||
}
|
||||
@ -969,7 +1032,7 @@ sub ParsePtrPull($$$$)
|
||||
|
||||
unless ($next_is_array or $next_is_string) {
|
||||
pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
|
||||
pidl "\tNDR_ALLOC($ndr, $var_name);";
|
||||
pidl "\tNDR_PULL_ALLOC($ndr, $var_name);";
|
||||
pidl "}";
|
||||
}
|
||||
|
||||
@ -987,9 +1050,13 @@ sub ParsePtrPull($$$$)
|
||||
# Don't do this for arrays, they're allocated at the actual level
|
||||
# of the array
|
||||
unless ($next_is_array or $next_is_string) {
|
||||
pidl "NDR_ALLOC($ndr, $var_name);";
|
||||
pidl "NDR_PULL_ALLOC($ndr, $var_name);";
|
||||
} else {
|
||||
pidl "NDR_ALLOC_SIZE($ndr, $var_name, 1);"; # FIXME: Yes, this is nasty. We allocate an array twice - once just to indicate that it's there, then the real allocation...
|
||||
# FIXME: Yes, this is nasty.
|
||||
# We allocate an array twice
|
||||
# - once just to indicate that it's there,
|
||||
# - then the real allocation...
|
||||
pidl "NDR_PULL_ALLOC_SIZE($ndr, $var_name, 1);";
|
||||
}
|
||||
|
||||
#pidl "memset($var_name, 0, sizeof($var_name));";
|
||||
@ -1285,6 +1352,37 @@ sub DeclareArrayVariables($)
|
||||
}
|
||||
}
|
||||
|
||||
sub need_decl_mem_ctx($$)
|
||||
{
|
||||
my $e = shift;
|
||||
my $l = shift;
|
||||
|
||||
return 0 if has_fast_array($e,$l);
|
||||
return 0 if (has_property($e, "charset") and ($l->{TYPE} ne "POINTER"));
|
||||
return 1 if (($l->{TYPE} eq "ARRAY") and not $l->{IS_FIXED});
|
||||
|
||||
if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) {
|
||||
my $nl = GetNextLevel($e, $l);
|
||||
my $next_is_array = ($nl->{TYPE} eq "ARRAY");
|
||||
my $next_is_string = (($nl->{TYPE} eq "DATA") and
|
||||
($nl->{DATA_TYPE} eq "string"));
|
||||
return 0 if ($next_is_array or $next_is_string);
|
||||
}
|
||||
return 1 if ($l->{TYPE} eq "POINTER");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub DeclareMemCtxVariables($)
|
||||
{
|
||||
my $e = shift;
|
||||
foreach my $l (@{$e->{LEVELS}}) {
|
||||
if (need_decl_mem_ctx($e, $l)) {
|
||||
pidl "TALLOC_CTX *_mem_save_$e->{NAME}_$l->{LEVEL_INDEX};";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a struct - pull side
|
||||
sub ParseStructPull($$)
|
||||
@ -1299,6 +1397,7 @@ sub ParseStructPull($$)
|
||||
foreach my $e (@{$struct->{ELEMENTS}}) {
|
||||
DeclarePtrVariables($e);
|
||||
DeclareArrayVariables($e);
|
||||
DeclareMemCtxVariables($e);
|
||||
}
|
||||
|
||||
# save the old relative_base_offset
|
||||
@ -1543,6 +1642,14 @@ sub ParseUnionPull($$)
|
||||
pidl Parse::Pidl::Typelist::mapType($switch_type) . " _level;";
|
||||
}
|
||||
|
||||
my %double_cases = ();
|
||||
foreach my $el (@{$e->{ELEMENTS}}) {
|
||||
next if ($el->{TYPE} eq "EMPTY");
|
||||
next if ($double_cases{"$el->{NAME}"});
|
||||
DeclareMemCtxVariables($el);
|
||||
$double_cases{"$el->{NAME}"} = 1;
|
||||
}
|
||||
|
||||
start_flags($e);
|
||||
|
||||
pidl "level = ndr_pull_get_switch_value(ndr, r);";
|
||||
@ -1846,12 +1953,12 @@ sub AllocateArrayLevel($$$$$)
|
||||
if (defined($pl) and
|
||||
$pl->{TYPE} eq "POINTER" and
|
||||
$pl->{POINTER_TYPE} eq "ref"
|
||||
and not $l->{IS_ZERO_TERMINATED}) {
|
||||
pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
|
||||
pidl "\tNDR_ALLOC_N($ndr, $var, $size);";
|
||||
pidl "}";
|
||||
and not $l->{IS_ZERO_TERMINATED}) {
|
||||
pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
|
||||
pidl "\tNDR_PULL_ALLOC_N($ndr, $var, $size);";
|
||||
pidl "}";
|
||||
} else {
|
||||
pidl "NDR_ALLOC_N($ndr, $var, $size);";
|
||||
pidl "NDR_PULL_ALLOC_N($ndr, $var, $size);";
|
||||
}
|
||||
|
||||
if (grep(/in/,@{$e->{DIRECTION}}) and
|
||||
@ -1876,10 +1983,18 @@ sub ParseFunctionPull($)
|
||||
|
||||
# declare any internal pointers we need
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
DeclarePtrVariables($e);
|
||||
DeclarePtrVariables($e);
|
||||
DeclareArrayVariables($e);
|
||||
}
|
||||
|
||||
my %double_cases = ();
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
next if ($e->{TYPE} eq "EMPTY");
|
||||
next if ($double_cases{"$e->{NAME}"});
|
||||
DeclareMemCtxVariables($e);
|
||||
$double_cases{"$e->{NAME}"} = 1;
|
||||
}
|
||||
|
||||
pidl "if (flags & NDR_IN) {";
|
||||
indent;
|
||||
|
||||
@ -1917,7 +2032,7 @@ sub ParseFunctionPull($)
|
||||
my $size = ParseExpr($e->{LEVELS}[1]->{SIZE_IS}, $env);
|
||||
check_null_pointer($size);
|
||||
|
||||
pidl "NDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);";
|
||||
pidl "NDR_PULL_ALLOC_N(ndr, r->out.$e->{NAME}, $size);";
|
||||
|
||||
if (grep(/in/, @{$e->{DIRECTION}})) {
|
||||
pidl "memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, $size * sizeof(*r->in.$e->{NAME}));";
|
||||
@ -1925,7 +2040,7 @@ sub ParseFunctionPull($)
|
||||
pidl "memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));";
|
||||
}
|
||||
} else {
|
||||
pidl "NDR_ALLOC(ndr, r->out.$e->{NAME});";
|
||||
pidl "NDR_PULL_ALLOC(ndr, r->out.$e->{NAME});";
|
||||
|
||||
if (grep(/in/, @{$e->{DIRECTION}})) {
|
||||
pidl "*r->out.$e->{NAME} = *r->in.$e->{NAME};";
|
||||
|
@ -54,6 +54,8 @@ struct ndr_pull {
|
||||
struct ndr_token_list *array_length_list;
|
||||
struct ndr_token_list *switch_list;
|
||||
|
||||
TALLOC_CTX *current_mem_ctx;
|
||||
|
||||
/* this is used to ensure we generate unique reference IDs
|
||||
between request and reply */
|
||||
uint32_t ptr_count;
|
||||
@ -224,28 +226,46 @@ enum ndr_compression_alg {
|
||||
return _status; \
|
||||
} while (0)
|
||||
|
||||
#define NDR_PULL_GET_MEM_CTX(ndr) (ndr->current_mem_ctx)
|
||||
|
||||
#define NDR_ALLOC_SIZE(ndr, s, size) do { \
|
||||
(s) = talloc_size(ndr, size); \
|
||||
if ((size) && !(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, \
|
||||
"Alloc %u failed\n", \
|
||||
(unsigned)size); \
|
||||
} while (0)
|
||||
#define NDR_PULL_SET_MEM_CTX(ndr, mem_ctx, flgs) do {\
|
||||
if ( !(flgs) || (ndr->flags & flgs) ) {\
|
||||
if (!(mem_ctx)) {\
|
||||
return ndr_pull_error(ndr, NDR_ERR_ALLOC, "NDR_PULL_SET_MEM_CTX(NULL): %s\n", __location__); \
|
||||
}\
|
||||
ndr->current_mem_ctx = discard_const(mem_ctx);\
|
||||
}\
|
||||
} while(0)
|
||||
|
||||
#define NDR_ALLOC(ndr, s) NDR_ALLOC_SIZE(ndr, s, sizeof(*(s)))
|
||||
#define _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr) do {\
|
||||
if (!ndr->current_mem_ctx) {\
|
||||
ndr->current_mem_ctx = talloc_new(ndr);\
|
||||
if (!ndr->current_mem_ctx) {\
|
||||
return ndr_pull_error(ndr, NDR_ERR_ALLOC, "_NDR_PULL_FIX_CURRENT_MEM_CTX() failed: %s\n", __location__); \
|
||||
}\
|
||||
}\
|
||||
} while(0)
|
||||
|
||||
|
||||
#define NDR_ALLOC_N_SIZE(ndr, s, n, elsize) do { \
|
||||
(s) = talloc_array_size(ndr, elsize, n); \
|
||||
if (!(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %u * %u failed\n", (unsigned)n, (unsigned)elsize); \
|
||||
#define NDR_PULL_ALLOC_SIZE(ndr, s, size) do { \
|
||||
_NDR_PULL_FIX_CURRENT_MEM_CTX(ndr);\
|
||||
(s) = talloc_size(ndr->current_mem_ctx, size); \
|
||||
if (!(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %u failed: %s\n",(unsigned)size, __location__); \
|
||||
} while (0)
|
||||
|
||||
#define NDR_ALLOC_N(ndr, s, n) NDR_ALLOC_N_SIZE(ndr, s, n, sizeof(*(s)))
|
||||
#define NDR_PULL_ALLOC(ndr, s) NDR_PULL_ALLOC_SIZE(ndr, s, sizeof(*(s)))
|
||||
|
||||
#define NDR_PULL_ALLOC_N_SIZE(ndr, s, n, elsize) do { \
|
||||
_NDR_PULL_FIX_CURRENT_MEM_CTX(ndr);\
|
||||
(s) = talloc_array_size(ndr->current_mem_ctx, elsize, n); \
|
||||
if (!(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %u * %u failed: %s\n", (unsigned)n, (unsigned)elsize, __location__); \
|
||||
} while (0)
|
||||
|
||||
#define NDR_PULL_ALLOC_N(ndr, s, n) NDR_PULL_ALLOC_N_SIZE(ndr, s, n, sizeof(*(s)))
|
||||
|
||||
|
||||
#define NDR_PUSH_ALLOC_SIZE(ndr, s, size) do { \
|
||||
(s) = talloc_size(ndr, size); \
|
||||
if (!(s)) return ndr_push_error(ndr, NDR_ERR_ALLOC, "push alloc %u failed\n", (unsigned)size); \
|
||||
if (!(s)) return ndr_push_error(ndr, NDR_ERR_ALLOC, "push alloc %u failed: %s\n", (unsigned)size, __location__); \
|
||||
} while (0)
|
||||
|
||||
#define NDR_PUSH_ALLOC(ndr, s) NDR_PUSH_ALLOC_SIZE(ndr, s, sizeof(*(s)))
|
||||
|
@ -50,6 +50,7 @@ struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
|
||||
|
||||
ndr = talloc_zero(mem_ctx, struct ndr_pull);
|
||||
if (!ndr) return NULL;
|
||||
ndr->current_mem_ctx = mem_ctx;
|
||||
|
||||
ndr->data = blob->data;
|
||||
ndr->data_size = blob->length;
|
||||
@ -359,6 +360,7 @@ NTSTATUS ndr_pull_subcontext_start(struct ndr_pull *ndr,
|
||||
subndr = talloc_zero(ndr, struct ndr_pull);
|
||||
NT_STATUS_HAVE_NO_MEMORY(subndr);
|
||||
subndr->flags = ndr->flags;
|
||||
subndr->current_mem_ctx = ndr->current_mem_ctx;
|
||||
|
||||
subndr->data = ndr->data + ndr->offset;
|
||||
subndr->offset = 0;
|
||||
|
@ -105,6 +105,7 @@ static NTSTATUS ndr_pull_compression_mszip(struct ndr_pull *subndr,
|
||||
comndr = talloc_zero(subndr, struct ndr_pull);
|
||||
NT_STATUS_HAVE_NO_MEMORY(comndr);
|
||||
comndr->flags = subndr->flags;
|
||||
comndr->current_mem_ctx = subndr->current_mem_ctx;
|
||||
|
||||
comndr->data = uncompressed.data;
|
||||
comndr->data_size = uncompressed.length;
|
||||
|
@ -78,6 +78,7 @@ NTSTATUS ndr_push_PAC_BUFFER(struct ndr_push *ndr, int ndr_flags, const struct P
|
||||
NTSTATUS ndr_pull_PAC_BUFFER(struct ndr_pull *ndr, int ndr_flags, struct PAC_BUFFER *r)
|
||||
{
|
||||
uint32_t _ptr_info;
|
||||
TALLOC_CTX *_mem_save_info_0;
|
||||
if (ndr_flags & NDR_SCALARS) {
|
||||
NDR_CHECK(ndr_pull_align(ndr, 4));
|
||||
NDR_CHECK(ndr_pull_PAC_TYPE(ndr, NDR_SCALARS, &r->type));
|
||||
@ -87,7 +88,7 @@ NTSTATUS ndr_pull_PAC_BUFFER(struct ndr_pull *ndr, int ndr_flags, struct PAC_BUF
|
||||
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN8);
|
||||
NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info));
|
||||
if (_ptr_info) {
|
||||
NDR_ALLOC(ndr, r->info);
|
||||
NDR_PULL_ALLOC(ndr, r->info);
|
||||
NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->info, _ptr_info));
|
||||
} else {
|
||||
r->info = NULL;
|
||||
@ -104,6 +105,8 @@ NTSTATUS ndr_pull_PAC_BUFFER(struct ndr_pull *ndr, int ndr_flags, struct PAC_BUF
|
||||
struct ndr_pull_save _relative_save;
|
||||
ndr_pull_save(ndr, &_relative_save);
|
||||
NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->info));
|
||||
_mem_save_info_0 = NDR_PULL_GET_MEM_CTX(ndr);
|
||||
NDR_PULL_SET_MEM_CTX(ndr, r->info, 0);
|
||||
{
|
||||
struct ndr_pull *_ndr_info;
|
||||
NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_info, 0, r->_ndr_size));
|
||||
@ -111,6 +114,7 @@ NTSTATUS ndr_pull_PAC_BUFFER(struct ndr_pull *ndr, int ndr_flags, struct PAC_BUF
|
||||
NDR_CHECK(ndr_pull_PAC_INFO(_ndr_info, NDR_SCALARS|NDR_BUFFERS, r->info));
|
||||
NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_info, 0, r->_ndr_size));
|
||||
}
|
||||
NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info_0, 0);
|
||||
ndr_pull_restore(ndr, &_relative_save);
|
||||
}
|
||||
ndr->flags = _flags_save_PAC_INFO;
|
||||
|
@ -70,6 +70,8 @@ NTSTATUS ndr_pull_dom_sid28(struct ndr_pull *ndr, int ndr_flags, struct dom_sid
|
||||
|
||||
subndr = talloc_zero(ndr, struct ndr_pull);
|
||||
NT_STATUS_HAVE_NO_MEMORY(subndr);
|
||||
subndr->flags = ndr->flags;
|
||||
subndr->current_mem_ctx = ndr->current_mem_ctx;
|
||||
|
||||
subndr->data = ndr->data + ndr->offset;
|
||||
subndr->data_size = 28;
|
||||
|
Loading…
x
Reference in New Issue
Block a user