summaryrefslogtreecommitdiff
path: root/pidl/lib/Parse
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2010-08-25 11:07:29 +0200
committerStefan Metzmacher <metze@samba.org>2010-08-28 10:59:19 +0200
commitaa3b75ad1fa60dbf1ea3bd61782c59b39020b2e3 (patch)
treede5c221a1a3f565476bf781a9d8e54c94deec67c /pidl/lib/Parse
parenteeebaa63f1fe85fe9d58bad50920432263de84c0 (diff)
downloadsamba-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
Diffstat (limited to 'pidl/lib/Parse')
-rw-r--r--pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm82
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};");
}