From 628bd29082ec0a632eca2e0bde9ed50e1fc0dee0 Mon Sep 17 00:00:00 2001 From: Thomas Lamprecht Date: Mon, 18 Nov 2024 20:01:25 +0100 Subject: [PATCH] ovf import: disks: allow whitespaces in file path Add a SAFE_CHAR_WITH_WHITESPACE_CLASS_RE sister variant of the shared SAFE_CHAR_CLASS_RE shared regex to the base storage module, this use case exist is a generic one after all, and use swap the untaint method that parses the file a disk references to it. Note that this is only the disk file name from inside the archive and thus during the extraction to a staging/working directory, from there it will be imported as volume allocated by the common storage system, and thus follow our ordinary volume name scheme. Improves disk detection when importing, e.g., the from upstream provided GNS3 OVA. Signed-off-by: Thomas Lamprecht --- src/PVE/GuestImport.pm | 2 +- src/PVE/GuestImport/OVF.pm | 2 +- src/PVE/Storage.pm | 3 ++- src/PVE/Storage/Plugin.pm | 4 ++-- src/test/parse_volname_test.pm | 5 +++++ 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/PVE/GuestImport.pm b/src/PVE/GuestImport.pm index f7ebf92..c473d88 100644 --- a/src/PVE/GuestImport.pm +++ b/src/PVE/GuestImport.pm @@ -28,7 +28,7 @@ sub extract_disk_from_import_file { my $archive_volid; my $inner_file; my $inner_fmt; - if ($name =~ m!^(.*\.ova)/(${PVE::Storage::SAFE_CHAR_CLASS_RE}+)$!) { + if ($name =~ m!^(.*\.ova)/(${PVE::Storage::SAFE_CHAR_WITH_WHITESPACE_CLASS_RE}+)$!) { $archive_volid = "$source_storeid:import/$1"; $inner_file = $2; ($inner_fmt) = $fmt =~ /^ova\+(.*)$/; diff --git a/src/PVE/GuestImport/OVF.pm b/src/PVE/GuestImport/OVF.pm index 4a00039..9e9f8b3 100644 --- a/src/PVE/GuestImport/OVF.pm +++ b/src/PVE/GuestImport/OVF.pm @@ -323,7 +323,7 @@ ovf:Item[rasd:InstanceID='%s']/rasd:ResourceType", $controller_id); } print "file path: $filepath\n" if $debug; my $original_filepath = $filepath; - ($filepath) = $filepath =~ m|^(${PVE::Storage::SAFE_CHAR_CLASS_RE}+)$|; # untaint & check no sub/parent dirs + ($filepath) = $filepath =~ m|^(${PVE::Storage::SAFE_CHAR_WITH_WHITESPACE_CLASS_RE}+)$|; # untaint & check no sub/parent dirs die "referenced path '$original_filepath' is invalid\n" if !$filepath || $filepath eq "." || $filepath eq ".."; # resolve symlinks and relative path components diff --git a/src/PVE/Storage.pm b/src/PVE/Storage.pm index 1e12b51..230c57b 100755 --- a/src/PVE/Storage.pm +++ b/src/PVE/Storage.pm @@ -119,8 +119,9 @@ our $IMPORT_EXT_RE_1 = qr/\.(ova|ovf|qcow2|raw|vmdk)/; our $UPLOAD_IMPORT_EXT_RE_1 = qr/\.(ova)/; our $SAFE_CHAR_CLASS_RE = qr/[a-zA-Z0-9\-\.\+\=\_]/; +our $SAFE_CHAR_WITH_WHITESPACE_CLASS_RE = qr/[ a-zA-Z0-9\-\.\+\=\_]/; -our $OVA_CONTENT_RE_1 = qr/${SAFE_CHAR_CLASS_RE}+\.(qcow2|raw|vmdk)/; +our $OVA_CONTENT_RE_1 = qr/${SAFE_CHAR_WITH_WHITESPACE_CLASS_RE}+\.(qcow2|raw|vmdk)/; # FIXME remove with PVE 9.0, add versioned breaks for pve-manager our $vztmpl_extension_re = $VZTMPL_EXT_RE_1; diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm index 2407eba..25e2a4d 100644 --- a/src/PVE/Storage/Plugin.pm +++ b/src/PVE/Storage/Plugin.pm @@ -663,11 +663,11 @@ sub parse_volname { return ('backup', $fn); } elsif ($volname =~ m!^snippets/([^/]+)$!) { return ('snippets', $1); - } elsif ($volname =~ m!^import/(${PVE::Storage::SAFE_CHAR_CLASS_RE}+\.ova\/${PVE::Storage::OVA_CONTENT_RE_1})$!) { + } elsif ($volname =~ m!^import/(${PVE::Storage::SAFE_CHAR_WITH_WHITESPACE_CLASS_RE}+\.ova\/${PVE::Storage::OVA_CONTENT_RE_1})$!) { my $packed_image = $1; my $format = $2; return ('import', $packed_image, undef, undef, undef, undef, "ova+$format"); - } elsif ($volname =~ m!^import/(${PVE::Storage::SAFE_CHAR_CLASS_RE}+$PVE::Storage::IMPORT_EXT_RE_1)$!) { + } elsif ($volname =~ m!^import/(${PVE::Storage::SAFE_CHAR_WITH_WHITESPACE_CLASS_RE}+$PVE::Storage::IMPORT_EXT_RE_1)$!) { return ('import', $1, undef, undef, undef, undef, $2); } diff --git a/src/test/parse_volname_test.pm b/src/test/parse_volname_test.pm index eecd7df..2739cf1 100644 --- a/src/test/parse_volname_test.pm +++ b/src/test/parse_volname_test.pm @@ -108,6 +108,11 @@ my $tests = [ volname => 'import/import.ova/disk.vmdk', expected => ['import', 'import.ova/disk.vmdk', undef, undef, undef, undef, 'ova+vmdk'], }, + { + description => "Import, innner file of ova with whitespace in name", + volname => 'import/import.ova/OS disk.vmdk', + expected => ['import', 'import.ova/OS disk.vmdk', undef, undef, undef, undef, 'ova+vmdk'], + }, { description => "Import, innner file of ova", volname => 'import/import.ova/disk.raw',