[Patch] fix IDL hang
Jelmer Vernooij
jelmer at samba.org
Thu Aug 7 05:32:55 MDT 2014
On Thu, Aug 07, 2014 at 12:22:59PM +0100, Noel Power wrote:
> Hi,
>
> issuing
>
> ./pidl/pidl --header --ndr-parser -- foo.idl
>
> will cause pidl to hang, the attached patch prevents the recursion that
> triggers that. Note: I compared the contents of
> bin/default/librpc/gen_ndr before and after the patch and the contents
> are identical
What's the reason for supporting this rather than errorring out? What does midl do in this case?
Cheers,
Jelmer
> From f524baef07c27ea4aba1a7527fcda12cfcb5f247 Mon Sep 17 00:00:00 2001
> From: Noel Power <noel.power at suse.com>
> Date: Wed, 6 Aug 2014 11:32:19 +0100
> Subject: [PATCH] detect and prevent recursions (that cause infinite loops)
>
> add recusrion detection logic for can_contain_deferred & align_type
> functions
> ---
> pidl/lib/Parse/Pidl/NDR.pm | 71 +++++++++++++++++++++++++++++++++++++---------
> 1 file changed, 58 insertions(+), 13 deletions(-)
>
> diff --git a/pidl/lib/Parse/Pidl/NDR.pm b/pidl/lib/Parse/Pidl/NDR.pm
> index 6827152..95964b0 100644
> --- a/pidl/lib/Parse/Pidl/NDR.pm
> +++ b/pidl/lib/Parse/Pidl/NDR.pm
> @@ -402,16 +402,37 @@ sub can_contain_deferred($)
>
> return 0 if (Parse::Pidl::Typelist::is_scalar($type));
>
> - return can_contain_deferred($type->{DATA}) if ($type->{TYPE} eq "TYPEDEF");
> + if ( not defined($type->{INCANCONTAINDERRED})) {
> + $type->{INCANCONTAINDERRED} = 0;
> + }
> +
> + my $res;
> +
> + if ($type->{INCANCONTAINDERRED} == 1 ){
> + $res = 0;
Why wouldn't deferreds be possible in this case?
> + goto out;
> + }
>
> - return 0 unless defined($type->{ELEMENTS});
> + $type->{INCANCONTAINDERRED} = 1;
> + if ($type->{TYPE} eq "TYPEDEF") {
> + $res = can_contain_deferred($type->{DATA});
> + goto out;
> + }
> +
> + if (!defined($type->{ELEMENTS})) {
> + $res = 0;
> + goto out;
> + }
>
> foreach (@{$type->{ELEMENTS}}) {
> - return 1 if ($_->{POINTERS});
> - return 1 if (can_contain_deferred ($_->{TYPE}));
> + if (($_->{POINTERS}) || can_contain_deferred ($_->{TYPE})) {
> + $res = 1;
> + goto out;
> + }
> }
> -
> - return 0;
> +out:
> + $type->{INCANCONTAINDERRED} = 0;
> + return $res;
> }
>
> sub pointer_type($)
> @@ -481,23 +502,47 @@ sub align_type($)
>
> my $dt = getType($e);
>
> + if ( not defined($dt->{INGETALIGNTYPE})) {
> + $dt->{INGETALIGNTYPE} = 0;
> + }
> +
> + my $res;
> + if ($dt->{INGETALIGNTYPE} == 1 ){
> + # reset it
> + $res = 0;
> + goto out;
> + }
> +
> + $dt->{INGETALIGNTYPE} = 1;
> +
> if ($dt->{TYPE} eq "TYPEDEF") {
> - return align_type($dt->{DATA});
> + $res = align_type($dt->{DATA});
> + goto out;
> } elsif ($dt->{TYPE} eq "CONFORMANCE") {
> - return $dt->{DATA}->{ALIGN};
> + $res = $dt->{DATA}->{ALIGN};
> + goto out;
> } elsif ($dt->{TYPE} eq "ENUM") {
> - return align_type(Parse::Pidl::Typelist::enum_type_fn($dt));
> + $res = align_type(Parse::Pidl::Typelist::enum_type_fn($dt));
> + goto out;
> } elsif ($dt->{TYPE} eq "BITMAP") {
> - return align_type(Parse::Pidl::Typelist::bitmap_type_fn($dt));
> + $res = align_type(Parse::Pidl::Typelist::bitmap_type_fn($dt));
> + goto out;
> } elsif (($dt->{TYPE} eq "STRUCT") or ($dt->{TYPE} eq "UNION")) {
> # Struct/union without body: assume 4
> - return 4 unless (defined($dt->{ELEMENTS}));
> - return find_largest_alignment($dt);
> + $res = 4;
> + if (defined($dt->{ELEMENTS})) {
> + $res = find_largest_alignment($dt);
> + }
> + goto out;
> } elsif (($dt->{TYPE} eq "PIPE")) {
> - return 5;
> + $res = 5;
> + goto out;
> }
>
> die("Unknown data type type $dt->{TYPE}");
> +out:
> + $dt->{INGETALIGNTYPE} = 0;
> + return $res;
> }
>
> sub ParseElement($$$)
> --
> 1.8.4.5
>
> interface foobar
> {
>
> typedef [public] struct {
> baz anode;
> } foo;
>
> typedef [public,nodiscriminant,switch_type(uint32)] union {
> [case(1)] foo afoo;
> } values;
>
> typedef [public] struct {
> [switch_is(ultype)] values avalue;
> } baz;
>
> };
More information about the samba-technical
mailing list