if ($l->{IS_CONFORMANT}) {
$length = $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_name) . ")";
- } elsif ($l->{IS_ZERO_TERMINATED}) { # Noheader arrays
+ } elsif ($l->{IS_ZERO_TERMINATED} and $l->{SIZE_IS} == 0 and $l->{LENGTH_IS} == 0) { # Noheader arrays
$length = $size = "ndr_get_string_size($ndr, sizeof(*$var_name))";
} else {
$length = $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL},
}
if ($l->{TYPE} eq "POINTER" and $deferred) {
+ my $rel_var_name = $var_name;
if ($l->{POINTER_TYPE} ne "ref") {
$self->pidl("if ($var_name) {");
$self->indent;
if ($l->{POINTER_TYPE} eq "relative") {
- $self->pidl("NDR_CHECK(ndr_push_relative_ptr2($ndr, $var_name));");
+ $self->pidl("NDR_CHECK(ndr_push_relative_ptr2_start($ndr, $rel_var_name));");
}
}
$var_name = get_value_of($var_name);
$self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 1);
if ($l->{POINTER_TYPE} ne "ref") {
+ if ($l->{POINTER_TYPE} eq "relative") {
+ $self->pidl("NDR_CHECK(ndr_push_relative_ptr2_end($ndr, $rel_var_name));");
+ }
$self->deindent;
$self->pidl("}");
}
my $length = ParseExpr($l->{LENGTH_IS}, $env, $e->{ORIGINAL});
my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
+ my $array_pointless = ($length eq "0");
+
+ if ($array_pointless) {
+ warning($e->{ORIGINAL}, "pointless array `$e->{NAME}' will always have size 0");
+ }
+
$var_name = get_array_element($var_name, $counter);
- if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) {
+ if ((($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) and not $array_pointless) {
$self->pidl("for ($counter = 0; $counter < $length; $counter++) {");
$self->indent;
$self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 0);
$self->pidl("}");
}
- if ($deferred and ContainsDeferred($e, $l)) {
+ if ($deferred and ContainsDeferred($e, $l) and not $array_pointless) {
$self->pidl("for ($counter = 0; $counter < $length; $counter++) {");
$self->indent;
$self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 0, 1);
$self->pidl("NDR_CHECK(".TypeFunctionName("ndr_pull", $l->{DATA_TYPE})."($ndr, $ndr_flags, $var_name));");
- if (my $range = has_property($e, "range")) {
+ my $pl = GetPrevLevel($e, $l);
+
+ my $range = has_property($e, "range");
+ if ($range and $pl->{TYPE} ne "ARRAY") {
$var_name = get_value_of($var_name);
my $signed = Parse::Pidl::Typelist::is_signed($l->{DATA_TYPE});
my ($low, $high) = split(/,/, $range, 2);
} elsif ($l->{TYPE} eq "ARRAY") {
my $length = $self->ParseArrayPullHeader($e, $l, $ndr, $var_name, $env);
+ if (my $range = has_property($e, "range")) {
+ my ($low, $high) = split(/,/, $range, 2);
+ if ($low < 0) {
+ warning(0, "$low is invalid for the range of an array size");
+ }
+ if ($low == 0) {
+ $self->pidl("if ($length > $high) {");
+ } else {
+ $self->pidl("if ($length < $low || $length > $high) {");
+ }
+ $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");");
+ $self->pidl("}");
+ }
+
my $nl = GetNextLevel($e, $l);
if (is_charset_array($e,$l)) {
my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
my $array_name = $var_name;
+ if ($l->{IS_VARYING}) {
+ $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")";
+ }
+
+ if (my $range = has_property($e, "range")) {
+ my ($low, $high) = split(/,/, $range, 2);
+ if ($low < 0) {
+ warning(0, "$low is invalid for the range of an array size");
+ }
+ if ($low == 0) {
+ $self->pidl("if ($length > $high) {");
+ } else {
+ $self->pidl("if ($length < $low || $length > $high) {");
+ }
+ $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");");
+ $self->pidl("}");
+ }
+
$var_name = get_array_element($var_name, $counter);
$self->ParseMemCtxPullStart($e, $l, $ndr, $array_name);
EnvSubstituteValue($env, $struct);
- $self->DeclareArrayVariables($_) foreach (@{$struct->{ELEMENTS}});
+ $self->DeclareArrayVariablesNoZero($_, $env) foreach (@{$struct->{ELEMENTS}});
$self->start_flags($struct, $ndr);
my ($self,$e) = @_;
foreach my $l (@{$e->{LEVELS}}) {
+ next if ($l->{TYPE} ne "ARRAY");
next if has_fast_array($e,$l);
next if is_charset_array($e,$l);
- if ($l->{TYPE} eq "ARRAY") {
+ $self->pidl("uint32_t cntr_$e->{NAME}_$l->{LEVEL_INDEX};");
+ }
+}
+
+sub DeclareArrayVariablesNoZero($$$)
+{
+ my ($self,$e,$env) = @_;
+
+ foreach my $l (@{$e->{LEVELS}}) {
+ next if ($l->{TYPE} ne "ARRAY");
+ next if has_fast_array($e,$l);
+ next if is_charset_array($e,$l);
+ my $length = ParseExpr($l->{LENGTH_IS}, $env, $e->{ORIGINAL});
+ if ($length eq "0") {
+ warning($e->{ORIGINAL}, "pointless array cntr: 'cntr_$e->{NAME}_$l->{LEVEL_INDEX}': length=$length");
+ } else {
$self->pidl("uint32_t cntr_$e->{NAME}_$l->{LEVEL_INDEX};");
}
}
if ($el->{TYPE} ne "EMPTY") {
$self->indent;
- $self->DeclarePtrVariables($el);
- $self->DeclareArrayVariables($el);
if (defined($e->{PROPERTIES}{relative_base})) {
$self->pidl("NDR_CHECK(ndr_pull_align($ndr, $el->{ALIGN}));");
# set the current offset as base for relative pointers
next if ($el->{TYPE} eq "EMPTY");
next if ($double_cases{"$el->{NAME}"});
$self->DeclareMemCtxVariables($el);
+ $self->DeclarePtrVariables($el);
+ $self->DeclareArrayVariables($el);
$double_cases{"$el->{NAME}"} = 1;
}
$self->pidl("}");
if (grep(/in/,@{$e->{DIRECTION}}) and
grep(/out/,@{$e->{DIRECTION}})) {
- $self->pidl("memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, $size * sizeof(*r->in.$e->{NAME}));");
+ $self->pidl("memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, ($size) * sizeof(*r->in.$e->{NAME}));");
}
return;
}