From 3bc680c1e38bef75d5b212992e15f094c523923b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 22 May 2021 18:40:13 +1200 Subject: 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 Reviewed-by: Douglas Bagnall --- pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'pidl') 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("}"); } -- cgit v1.2.1