diff options
author | Andrew Bartlett <abartlet@samba.org> | 2021-05-22 18:40:13 +1200 |
---|---|---|
committer | Douglas Bagnall <dbagnall@samba.org> | 2021-06-02 03:56:36 +0000 |
commit | 3bc680c1e38bef75d5b212992e15f094c523923b (patch) | |
tree | e49d92cfa4079786a243329868a80d86a7916ad0 /pidl | |
parent | a7d4f93cfdee0a2005be11880f8dd31f55149369 (diff) | |
download | samba-3bc680c1e38bef75d5b212992e15f094c523923b.tar.gz |
pidl: Avoid leaving array_size NDR tokens around
In many cases these can and should be consumed as soon as
they are used.
This is not a complete fix, we don't clean up the array_size
token after using it split between an NDR_SCALARS and
an NDR_BUFFERS pass, but it is much better than it was
and helps the winbind case with a large number of groups
(eg 100,000) as otherwise we hit the 65535 NDR token limit.
(This is an arbitary Samba-only limit to avoid DoS conditions)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14710
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Diffstat (limited to 'pidl')
-rw-r--r-- | pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm index 5927e973c32..db992aa9e47 100644 --- a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm +++ b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm @@ -342,11 +342,17 @@ sub ParseArrayPullGetSize($$$$$$) my $array_size = "size_$e->{NAME}_$l->{LEVEL_INDEX}"; - if ($l->{IS_CONFORMANT}) { + if ($l->{IS_CONFORMANT} and (defined($l->{SIZE_IS}) or not $l->{IS_ZERO_TERMINATED})) { $self->pidl("NDR_CHECK(ndr_get_array_size($ndr, (void*)" . get_pointer_to($var_name) . ", &$array_size));"); + + } elsif ($l->{IS_CONFORMANT}) { + # This will be the last use of the array_size token + $self->pidl("NDR_CHECK(ndr_steal_array_size($ndr, (void*)" . get_pointer_to($var_name) . ", &$array_size));"); + } elsif ($l->{IS_ZERO_TERMINATED} and $l->{SIZE_IS} == 0 and $l->{LENGTH_IS} == 0) { # Noheader arrays $size = "ndr_get_string_size($ndr, sizeof(*$var_name))"; $self->pidl("$array_size = $size;"); + } else { $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->pidl(shift); }, @@ -443,7 +449,14 @@ sub ParseArrayPullHeader($$$$$$) check_null_pointer($e, $env, sub { $self->defer(shift); }, "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"), check_fully_dereferenced($e, $env)); - $self->defer("NDR_CHECK(ndr_check_array_size($ndr, (void*)" . get_pointer_to($var_name) . ", $size));"); + if (ContainsDeferred($e, $l)) { + # We will be needing the array_size token in + # the NDR_BUFFERS call, so don't steal it now + $self->defer("NDR_CHECK(ndr_check_array_size($ndr, (void*)" . get_pointer_to($var_name) . ", $size));"); + } else { + # This will be deferred until after the last ndr_get_array_size() + $self->defer("NDR_CHECK(ndr_check_steal_array_size($ndr, (void*)" . get_pointer_to($var_name) . ", $size));"); + } $self->defer_deindent; $self->defer("}"); } |