1
Description: Fix PIDL compiler to do proper array allocation and length checks
2
Bug: https://bugzilla.samba.org/show_bug.cgi?id=8815
3
Origin: upstream, http://gitweb.samba.org/?p=samba.git;a=commit;h=94622cea2b2f4914b4ced35e952680c20cc4985b
4
Origin: upstream, http://gitweb.samba.org/?p=samba.git;a=commit;h=d15b71523d228f78f317f44181900dbf10b52e33
5
Origin: upstream, http://gitweb.samba.org/?p=samba.git;a=commit;h=dc9c68c8992db8225c93043757c4d33b8814c428
6
Origin: upstream, http://gitweb.samba.org/?p=samba.git;a=commit;h=8e99484dec90690ec1e00c17580150278963e063
7
Origin: upstream, http://gitweb.samba.org/?p=samba.git;a=commit;h=25f68811af3399c6148fa5d31d932465e27a2125
8
Origin: upstream, http://gitweb.samba.org/?p=samba.git;a=commit;h=e94415cf237d1e434daa5da70e6df0b4b6926bae
9
Origin: upstream, http://gitweb.samba.org/?p=samba.git;a=commit;h=3e0e6f56a671b40b21c37838ff292fe8902889bb
10
Origin: upstream, http://gitweb.samba.org/?p=samba.git;a=commit;h=0b9d59d256a74594e89467e5ebe4e62c25c9572e
12
Index: samba-3.6.3/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
13
===================================================================
14
--- samba-3.6.3.orig/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm 2012-01-29 13:40:43.000000000 -0600
15
+++ samba-3.6.3/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm 2012-04-12 02:42:54.862479019 -0500
20
-#####################################################################
21
-# parse an array - pull side
22
-sub ParseArrayPullHeader($$$$$$)
23
+sub ParseArrayPullGetSize($$$$$$)
25
my ($self,$e,$l,$ndr,$var_name,$env) = @_;
30
if ($l->{IS_CONFORMANT}) {
31
- $length = $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_name) . ")";
32
+ $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_name) . ")";
33
} elsif ($l->{IS_ZERO_TERMINATED} and $l->{SIZE_IS} == 0 and $l->{LENGTH_IS} == 0) { # Noheader arrays
34
- $length = $size = "ndr_get_string_size($ndr, sizeof(*$var_name))";
35
+ $size = "ndr_get_string_size($ndr, sizeof(*$var_name))";
37
- $length = $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL},
38
+ $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL},
39
check_null_pointer($e, $env, sub { $self->pidl(shift); },
40
"return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"),
41
check_fully_dereferenced($e, $env));
44
+ $self->pidl("size_$e->{NAME}_$l->{LEVEL_INDEX} = $size;");
45
+ my $array_size = "size_$e->{NAME}_$l->{LEVEL_INDEX}";
47
+ if (my $range = has_property($e, "range")) {
48
+ my ($low, $high) = split(/,/, $range, 2);
50
+ warning(0, "$low is invalid for the range of an array size");
53
+ $self->pidl("if ($array_size > $high) {");
55
+ $self->pidl("if ($array_size < $low || $array_size > $high) {");
57
+ $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");");
64
+#####################################################################
65
+# parse an array - pull side
66
+sub ParseArrayPullGetLength($$$$$$;$)
68
+ my ($self,$e,$l,$ndr,$var_name,$env,$array_size) = @_;
70
+ if (not defined($array_size)) {
71
+ $array_size = $self->ParseArrayPullGetSize($e, $l, $ndr, $var_name, $env);
74
+ if (not $l->{IS_VARYING}) {
78
+ my $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")";
79
+ $self->pidl("length_$e->{NAME}_$l->{LEVEL_INDEX} = $length;");
80
+ my $array_length = "length_$e->{NAME}_$l->{LEVEL_INDEX}";
82
+ if (my $range = has_property($e, "range")) {
83
+ my ($low, $high) = split(/,/, $range, 2);
85
+ warning(0, "$low is invalid for the range of an array size");
88
+ $self->pidl("if ($array_length > $high) {");
90
+ $self->pidl("if ($array_length < $low || $array_length > $high) {");
92
+ $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");");
96
+ return $array_length;
99
+#####################################################################
100
+# parse an array - pull side
101
+sub ParseArrayPullHeader($$$$$$)
103
+ my ($self,$e,$l,$ndr,$var_name,$env) = @_;
105
if ((!$l->{IS_SURROUNDING}) and $l->{IS_CONFORMANT}) {
106
$self->pidl("NDR_CHECK(ndr_pull_array_size($ndr, " . get_pointer_to($var_name) . "));");
109
if ($l->{IS_VARYING}) {
110
$self->pidl("NDR_CHECK(ndr_pull_array_length($ndr, " . get_pointer_to($var_name) . "));");
111
- $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")";
114
- if ($length ne $size) {
115
- $self->pidl("if ($length > $size) {");
116
+ my $array_size = $self->ParseArrayPullGetSize($e, $l, $ndr, $var_name, $env);
117
+ my $array_length = $self->ParseArrayPullGetLength($e, $l, $ndr, $var_name, $env, $array_size);
119
+ if ($array_length ne $array_size) {
120
+ $self->pidl("if ($array_length > $array_size) {");
122
- $self->pidl("return ndr_pull_error($ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should exceed array length %u\", $size, $length);");
123
+ $self->pidl("return ndr_pull_error($ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should exceed array length %u\", $array_size, $array_length);");
127
@@ -377,10 +437,10 @@
130
if (ArrayDynamicallyAllocated($e,$l) and not is_charset_array($e,$l)) {
131
- $self->AllocateArrayLevel($e,$l,$ndr,$var_name,$size);
132
+ $self->AllocateArrayLevel($e,$l,$ndr,$var_name,$array_size);
136
+ return $array_length;
139
sub compression_alg($$)
141
my($self,$e,$l,$ndr,$var_name,$env,$primitives,$deferred) = @_;
143
my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
144
+ my $array_length = undef;
146
if ($l->{TYPE} eq "ARRAY" and ($l->{IS_VARYING} or $l->{IS_CONFORMANT})) {
147
$var_name = get_pointer_to($var_name);
148
@@ -1012,20 +1073,7 @@
149
$self->ParseSubcontextPullEnd($e, $l, $ndr, $env);
150
} elsif ($l->{TYPE} eq "ARRAY") {
151
my $length = $self->ParseArrayPullHeader($e, $l, $ndr, $var_name, $env);
153
- if (my $range = has_property($e, "range")) {
154
- my ($low, $high) = split(/,/, $range, 2);
156
- warning(0, "$low is invalid for the range of an array size");
159
- $self->pidl("if ($length > $high) {");
161
- $self->pidl("if ($length < $low || $length > $high) {");
163
- $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");");
166
+ $array_length = $length;
168
my $nl = GetNextLevel($e, $l);
170
@@ -1091,26 +1139,12 @@
172
} elsif ($l->{TYPE} eq "ARRAY" and
173
not has_fast_array($e,$l) and not is_charset_array($e, $l)) {
174
- my $length = ParseExpr($l->{LENGTH_IS}, $env, $e->{ORIGINAL});
175
+ my $length = $array_length;
176
my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
177
my $array_name = $var_name;
179
- if ($l->{IS_VARYING}) {
180
- $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")";
183
- if (my $range = has_property($e, "range")) {
184
- my ($low, $high) = split(/,/, $range, 2);
186
- warning(0, "$low is invalid for the range of an array size");
189
- $self->pidl("if ($length > $high) {");
191
- $self->pidl("if ($length < $low || $length > $high) {");
193
- $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");");
195
+ if (not defined($length)) {
196
+ $length = $self->ParseArrayPullGetLength($e, $l, $ndr, $var_name, $env);
199
$var_name = get_array_element($var_name, $counter);
200
@@ -1527,16 +1561,21 @@
204
-sub DeclareArrayVariables($$)
205
+sub DeclareArrayVariables($$;$)
207
- my ($self,$e) = @_;
208
+ my ($self,$e,$pull) = @_;
210
foreach my $l (@{$e->{LEVELS}}) {
211
+ next if ($l->{TYPE} ne "ARRAY");
212
+ if (defined($pull)) {
213
+ $self->pidl("uint32_t size_$e->{NAME}_$l->{LEVEL_INDEX} = 0;");
214
+ if ($l->{IS_VARYING}) {
215
+ $self->pidl("uint32_t length_$e->{NAME}_$l->{LEVEL_INDEX} = 0;");
218
next if has_fast_array($e,$l);
219
next if is_charset_array($e,$l);
220
- if ($l->{TYPE} eq "ARRAY") {
221
- $self->pidl("uint32_t cntr_$e->{NAME}_$l->{LEVEL_INDEX};");
223
+ $self->pidl("uint32_t cntr_$e->{NAME}_$l->{LEVEL_INDEX};");
227
@@ -1545,15 +1584,14 @@
228
my ($self,$e,$env) = @_;
230
foreach my $l (@{$e->{LEVELS}}) {
231
+ next if ($l->{TYPE} ne "ARRAY");
232
next if has_fast_array($e,$l);
233
next if is_charset_array($e,$l);
234
- if ($l->{TYPE} eq "ARRAY") {
235
- my $length = ParseExpr($l->{LENGTH_IS}, $env, $e->{ORIGINAL});
236
- if ($length eq "0") {
237
+ my $length = ParseExpr($l->{LENGTH_IS}, $env, $e->{ORIGINAL});
238
+ if ($length eq "0") {
239
warning($e->{ORIGINAL}, "pointless array cntr: 'cntr_$e->{NAME}_$l->{LEVEL_INDEX}': length=$length");
242
$self->pidl("uint32_t cntr_$e->{NAME}_$l->{LEVEL_INDEX};");
247
@@ -1619,7 +1657,7 @@
248
# declare any internal pointers we need
249
foreach my $e (@{$struct->{ELEMENTS}}) {
250
$self->DeclarePtrVariables($e);
251
- $self->DeclareArrayVariables($e);
252
+ $self->DeclareArrayVariables($e, "pull");
253
$self->DeclareMemCtxVariables($e);
256
@@ -1882,8 +1920,6 @@
258
if ($el->{TYPE} ne "EMPTY") {
260
- $self->DeclarePtrVariables($el);
261
- $self->DeclareArrayVariables($el);
262
if (defined($e->{PROPERTIES}{relative_base})) {
263
$self->pidl("NDR_CHECK(ndr_pull_align($ndr, $el->{ALIGN}));");
264
# set the current offset as base for relative pointers
265
@@ -1960,6 +1996,8 @@
266
next if ($el->{TYPE} eq "EMPTY");
267
next if ($double_cases{"$el->{NAME}"});
268
$self->DeclareMemCtxVariables($el);
269
+ $self->DeclarePtrVariables($el);
270
+ $self->DeclareArrayVariables($el, "pull");
271
$double_cases{"$el->{NAME}"} = 1;
274
@@ -2325,7 +2363,7 @@
275
# declare any internal pointers we need
276
foreach my $e (@{$fn->{ELEMENTS}}) {
277
$self->DeclarePtrVariables($e);
278
- $self->DeclareArrayVariables($e);
279
+ $self->DeclareArrayVariables($e, "pull");
282
my %double_cases = ();