diff options
author | Stefan Metzmacher <metze@samba.org> | 2010-08-25 11:07:29 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2010-08-28 10:59:19 +0200 |
commit | aa3b75ad1fa60dbf1ea3bd61782c59b39020b2e3 (patch) | |
tree | de5c221a1a3f565476bf781a9d8e54c94deec67c | |
parent | eeebaa63f1fe85fe9d58bad50920432263de84c0 (diff) | |
download | samba-aa3b75ad1fa60dbf1ea3bd61782c59b39020b2e3.tar.gz samba-aa3b75ad1fa60dbf1ea3bd61782c59b39020b2e3.tar.bz2 samba-aa3b75ad1fa60dbf1ea3bd61782c59b39020b2e3.zip |
pidl:Samba4/NDR/Client: correctly copy [out,charset()] buffers
If the conversion from CH_UTF16 to CH_UNIX uses multi-byte characters
in CH_UNIX, we should not silently truncate the string, but return
an error.
metze
-rw-r--r-- | pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm | 82 |
1 files changed, 62 insertions, 20 deletions
diff --git a/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm b/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm index 8dc9d252b6..9be7641799 100644 --- a/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm +++ b/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm @@ -347,35 +347,77 @@ sub ParseOutputArgument($$$$$$) my $in_env = GenerateFunctionInEnv($fn, $r); my $out_env = GenerateFunctionOutEnv($fn, $r); my $l = $e->{LEVELS}[$level]; + + my $in_var = undef; + if (grep(/in/, @{$e->{DIRECTION}})) { + $in_var = ParseExpr($e->{NAME}, $in_env, $e->{ORIGINAL}); + } + my $out_var = ParseExpr($e->{NAME}, $out_env, $e->{ORIGINAL}); + + my $in_size_is = undef; + my $out_size_is = undef; + my $out_length_is = undef; + + my $avail_len = undef; + my $needed_len = undef; + + $self->pidl("{"); + $self->indent; + my $copy_len_var = "_copy_len_$e->{NAME}"; + $self->pidl("size_t $copy_len_var;"); + unless (defined($l->{SIZE_IS})) { fatal($e->{ORIGINAL}, "no size known for [out] array `$e->{NAME}'"); } else { - 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; + $in_size_is = ParseExpr($l->{SIZE_IS}, $in_env, $e->{ORIGINAL}); + $out_size_is = ParseExpr($l->{SIZE_IS}, $out_env, $e->{ORIGINAL}); + $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->ParseInvalidResponse($invalid_response_type); - $self->deindent; - $self->pidl("}"); - } - if ($out_length_is ne $out_size_is) { - $self->pidl("if (($out_length_is) > ($out_size_is)) {"); - $self->indent; - $self->ParseInvalidResponse($invalid_response_type); - $self->deindent; - $self->pidl("}"); - } if (has_property($e, "charset")) { - $self->pidl("memcpy(discard_const_p(uint8_t *, $o$e->{NAME}), ${r}out.$e->{NAME}, ($out_length_is) * sizeof(*$o$e->{NAME}));"); - } else { - $self->pidl("memcpy($o$e->{NAME}, ${r}out.$e->{NAME}, ($out_length_is) * sizeof(*$o$e->{NAME}));"); + if (defined($in_var)) { + $avail_len = "ndr_charset_length($in_var, CH_UNIX)"; + } else { + $avail_len = $out_length_is; + } + $needed_len = "ndr_charset_length($out_var, CH_UNIX)"; } } + + if ($out_size_is ne $in_size_is) { + $self->pidl("if (($out_size_is) > ($in_size_is)) {"); + $self->indent; + $self->ParseInvalidResponse($invalid_response_type); + $self->deindent; + $self->pidl("}"); + } + if ($out_length_is ne $out_size_is) { + $self->pidl("if (($out_length_is) > ($out_size_is)) {"); + $self->indent; + $self->ParseInvalidResponse($invalid_response_type); + $self->deindent; + $self->pidl("}"); + } + if (defined($needed_len)) { + $self->pidl("$copy_len_var = $needed_len;"); + $self->pidl("if ($copy_len_var > $avail_len) {"); + $self->indent; + $self->ParseInvalidResponse($invalid_response_type); + $self->deindent; + $self->pidl("}"); + } else { + $self->pidl("$copy_len_var = $out_length_is;"); + } + + if (has_property($e, "charset")) { + $self->pidl("memcpy(discard_const_p(uint8_t *, $o$e->{NAME}), $out_var, $copy_len_var * sizeof(*$o$e->{NAME}));"); + } else { + $self->pidl("memcpy($o$e->{NAME}, $out_var, $copy_len_var * sizeof(*$o$e->{NAME}));"); + } + + $self->deindent; + $self->pidl("}"); } else { $self->pidl("*$o$e->{NAME} = *${r}out.$e->{NAME};"); } |