pidl: Samba3/ClientNDR - Correctly copy arrays, if r.out.size < r.in.size.
authorStefan Metzmacher <metze@samba.org>
Mon, 9 Aug 2010 09:14:52 +0000 (11:14 +0200)
committerKarolin Seeger <kseeger@samba.org>
Thu, 13 Jan 2011 16:58:51 +0000 (17:58 +0100)
metze

Signed-off-by: Andreas Schneider <asn@samba.org>
(similar to commit 33d1879d5b50e2d98c1bb13b835e7cfb178e3336)
(similar to commit d1e92cd2944983ecabd0511ff7c8221c1033a3a8)
Fixes bug #7607.
(cherry picked from commit d04e5c4d0ae4bb20497748771aa1467cc14f2265)

pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm

index a45abdbc35532bc94222d7efa32c3d75936faad0..a5052e2e4159ba9186cc98fa625c0da4c6238183 100644 (file)
@@ -15,7 +15,7 @@ use strict;
 use Parse::Pidl qw(fatal warning error);
 use Parse::Pidl::Util qw(has_property ParseExpr);
 use Parse::Pidl::Samba4 qw(DeclLong);
-use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv);
+use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv);
 
 use vars qw($VERSION);
 $VERSION = '0.01';
@@ -95,12 +95,38 @@ sub ParseOutputArgument($$$)
                # Since the data is being copied into a user-provided data 
                # structure, the user should be able to know the size beforehand 
                # to allocate a structure of the right size.
-               my $env = GenerateFunctionInEnv($fn, "r.");
-               my $size_is = ParseExpr($e->{LEVELS}[$level]->{SIZE_IS}, $env, $e->{ORIGINAL});
-               if (has_property($e, "charset")) {
-                   $self->pidl("memcpy(discard_const_p(uint8_t *, $e->{NAME}), r.out.$e->{NAME}, ($size_is) * sizeof(*$e->{NAME}));");
+               my $in_env = GenerateFunctionInEnv($fn, "r.");
+               my $out_env = GenerateFunctionOutEnv($fn, "r.");
+               my $l = $e->{LEVELS}[$level];
+               unless (defined($l->{SIZE_IS})) {
+                       $self->pidl('#error No size known for [out] array `$e->{NAME}');
+                       error($e->{ORIGINAL}, "no size known for [out] array `$e->{NAME}'");
                } else {
-                   $self->pidl("memcpy($e->{NAME}, r.out.$e->{NAME}, ($size_is) * sizeof(*$e->{NAME}));");
+                       my $in_size_is = ParseExpr($l->{SIZE_IS}, $in_env, $e->{ORIGINAL});
+                       my $out_size_is = ParseExpr($l->{SIZE_IS}, $out_env, $e->{ORIGINAL});
+                       my $out_length_is = $out_size_is;
+                       if (defined($l->{LENGTH_IS})) {
+                               $out_length_is = ParseExpr($l->{LENGTH_IS}, $out_env, $e->{ORIGINAL});
+                       }
+                       if ($out_size_is ne $in_size_is) {
+                               $self->pidl("if (($out_size_is) > ($in_size_is)) {");
+                               $self->indent;
+                               $self->pidl("return NT_STATUS_INVALID_NETWORK_RESPONSE;");
+                               $self->deindent;
+                               $self->pidl("}");
+                       }
+                       if ($out_length_is ne $out_size_is) {
+                               $self->pidl("if (($out_length_is) > ($out_size_is)) {");
+                               $self->indent;
+                               $self->pidl("return NT_STATUS_INVALID_NETWORK_RESPONSE;");
+                               $self->deindent;
+                               $self->pidl("}");
+                       }
+                       if (has_property($e, "charset")) {
+                               $self->pidl("memcpy(discard_const_p(uint8_t *, $e->{NAME}), r.out.$e->{NAME}, ($out_length_is) * sizeof(*$e->{NAME}));");
+                       } else {
+                               $self->pidl("memcpy($e->{NAME}, r.out.$e->{NAME}, ($out_length_is) * sizeof(*$e->{NAME}));");
+                       }
                }
        } else {
                $self->pidl("*$e->{NAME} = *r.out.$e->{NAME};");