diff options
author | Stefan Metzmacher <metze@samba.org> | 2015-06-11 09:01:24 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2015-06-12 17:08:20 +0200 |
commit | cf7e1c7597dac52c4efd37da1d8130899bfd7509 (patch) | |
tree | cfb1ee803f5619ef5d0ae8161e217dca8345a540 | |
parent | 3c97bfe9de538d9f551f2c3d77ee3ab820a39b4a (diff) | |
download | samba-cf7e1c7597dac52c4efd37da1d8130899bfd7509.tar.gz |
pidl:NDR/Parser: check [ref] pointers before pushing anything else
This was reported by Coverity as
CID 1288527: Null pointer dereferences (REVERSE_INULL)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
-rw-r--r-- | pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm | 52 |
1 files changed, 45 insertions, 7 deletions
diff --git a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm index fe5f3900cee..a267fb1680b 100644 --- a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm +++ b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm @@ -737,13 +737,15 @@ sub ParsePtrPush($$$$$) my ($self,$e,$l,$ndr,$var_name) = @_; if ($l->{POINTER_TYPE} eq "ref") { - $self->pidl("if ($var_name == NULL) {"); - $self->indent; - $self->pidl("return ndr_push_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL [ref] pointer\");"); - $self->deindent; - $self->pidl("}"); + if ($l->{LEVEL_INDEX} > 0) { + $self->pidl("if ($var_name == NULL) {"); + $self->indent; + $self->pidl("return ndr_push_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL [ref] pointer\");"); + $self->deindent; + $self->pidl("}"); + } if ($l->{LEVEL} eq "EMBEDDED") { - $self->pidl("NDR_CHECK(ndr_push_ref_ptr(ndr));"); + $self->pidl("NDR_CHECK(ndr_push_ref_ptr(ndr)); /* $var_name */"); } } elsif ($l->{POINTER_TYPE} eq "relative") { $self->pidl("NDR_CHECK(ndr_push_relative_ptr1($ndr, $var_name));"); @@ -1331,10 +1333,30 @@ sub ParsePtrPull($$$$$) $self->pidl("}"); } +sub CheckRefPtrs($$$$) +{ + my ($self,$e,$ndr,$env) = @_; + + return if ContainsPipe($e, $e->{LEVELS}[0]); + return if ($e->{LEVELS}[0]->{TYPE} ne "POINTER"); + return if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref"); + + my $var_name = $env->{$e->{NAME}}; + $var_name = append_prefix($e, $var_name); + + $self->pidl("if ($var_name == NULL) {"); + $self->indent; + $self->pidl("return ndr_push_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL [ref] pointer\");"); + $self->deindent; + $self->pidl("}"); +} + sub ParseStructPushPrimitives($$$$$) { my ($self, $struct, $ndr, $varname, $env) = @_; + $self->CheckRefPtrs($_, $ndr, $env) foreach (@{$struct->{ELEMENTS}}); + # see if the structure contains a conformant array. If it # does, then it must be the last element of the structure, and # we need to push the conformant length early, as it fits on @@ -1834,7 +1856,9 @@ sub ParseUnionPushPrimitives($$$$) $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset1($ndr, $varname, $ndr->offset));"); } $self->DeclareArrayVariables($el); - $self->ParseElementPush($el, $ndr, {$el->{NAME} => "$varname->$el->{NAME}"}, 1, 0); + my $el_env = {$el->{NAME} => "$varname->$el->{NAME}"}; + $self->CheckRefPtrs($el, $ndr, $el_env); + $self->ParseElementPush($el, $ndr, $el_env, 1, 0); $self->deindent; } $self->pidl("break; }"); @@ -2365,6 +2389,12 @@ sub ParseFunctionPush($$) foreach my $e (@{$fn->{ELEMENTS}}) { if (grep(/in/,@{$e->{DIRECTION}})) { + $self->CheckRefPtrs($e, $ndr, $env); + } + } + + foreach my $e (@{$fn->{ELEMENTS}}) { + if (grep(/in/,@{$e->{DIRECTION}})) { $self->ParseElementPush($e, $ndr, $env, 1, 1); } } @@ -2376,6 +2406,14 @@ sub ParseFunctionPush($$) $self->indent; $env = GenerateFunctionOutEnv($fn); + EnvSubstituteValue($env, $fn); + + foreach my $e (@{$fn->{ELEMENTS}}) { + if (grep(/out/,@{$e->{DIRECTION}})) { + $self->CheckRefPtrs($e, $ndr, $env); + } + } + foreach my $e (@{$fn->{ELEMENTS}}) { if (grep(/out/,@{$e->{DIRECTION}})) { $self->ParseElementPush($e, $ndr, $env, 1, 1); |