only three small things were missing for it to work: * on the cli, we have to get the option as an array if the type is an array * the untainting must be done recursively, otherwise, the regex matching converts an array hash into the string 'ARRAY(0x123412341234)' * JSONSchema::parse_config did not handle array formats specially, but we want to allow to specify them multiple time
Signed-off-by: Dominik Csapak <d.csa...@proxmox.com> --- src/PVE/JSONSchema.pm | 12 ++++++++++++ src/PVE/RESTHandler.pm | 41 ++++++++++++++++++++++++++++++++++------- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/PVE/JSONSchema.pm b/src/PVE/JSONSchema.pm index 527e409..526fc2b 100644 --- a/src/PVE/JSONSchema.pm +++ b/src/PVE/JSONSchema.pm @@ -1709,6 +1709,8 @@ sub get_options { } else { if ($pd->{format} && $pd->{format} =~ m/-a?list/) { push @getopt, "$prop=s@"; + } elsif ($pd->{type} eq 'array') { + push @getopt, "$prop=s@"; } else { push @getopt, "$prop=s"; } @@ -1869,6 +1871,16 @@ sub parse_config : prototype($$$;$) { $value = parse_boolean($value) // $value; } + if ($schema->{properties}->{$key} && + $schema->{properties}->{$key}->{type} eq 'array') { + + if (defined($cfg->{$key})) { + push $cfg->{$key}->@*, $value; + } else { + $cfg->{$key} = [$value]; + } + next; + } $cfg->{$key} = $value; } else { warn "ignore config line: $line\n" diff --git a/src/PVE/RESTHandler.pm b/src/PVE/RESTHandler.pm index 944a04b..20714a5 100644 --- a/src/PVE/RESTHandler.pm +++ b/src/PVE/RESTHandler.pm @@ -426,6 +426,38 @@ sub find_handler { return ($handler_class, $method_info); } +my $untaint_recursive; + +$untaint_recursive = sub { + my ($param) = @_; + + my $ref = ref $param; + if ($ref eq 'HASH') { + while (my ($key, $val) = each %$param) { + my $newval = $untaint_recursive->($val); + if (defined($newval)) { + ($param->{$key}) = $newval; + } else { + $param->{$key} = undef; + } + } + } elsif ($ref eq 'ARRAY') { + my $newparam = []; + for my $val (@$param) { + my $newval = $untaint_recursive->($val); + push @$newparam, $newval if defined($newval); + } + $param = $newparam; + } else { + if (defined($param)) { + my ($newval) = $param =~ /^(.*)$/s; + $param = $newval; + } + } + + return $param; +}; + sub handle { my ($self, $info, $param, $result_verification) = @_; @@ -437,16 +469,11 @@ sub handle { if (my $schema = $info->{parameters}) { # warn "validate ". Dumper($param}) . "\n" . Dumper($schema); + PVE::JSONSchema::validate($param, $schema); # untaint data (already validated) my $extra = delete $param->{'extra-args'}; - while (my ($key, $val) = each %$param) { - if (defined($val)) { - ($param->{$key}) = $val =~ /^(.*)$/s; - } else { - $param->{$key} = undef; - } - } + $param = $untaint_recursive->($param); $param->{'extra-args'} = [map { /^(.*)$/ } @$extra] if $extra; } -- 2.30.2 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel