[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