From bb38cc101040311134887bf38c68fe78bd80b58b Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Wed, 13 Mar 2024 16:42:09 -0400 Subject: [PATCH] LibWeb: Do not blindly create File objects when adding FormData entries We were unconditionally creating new File objects for all Blob-type values passed to `FormData.append`. We should only do so if the value is not already a File object (or if the `filename` attribute is present). We must also carry MIME type information forward from the underlying Blob object. --- .../HTML/FormData-append-blob-with-type.txt | 2 ++ .../HTML/FormData-append-blob-with-type.html | 13 +++++++++ .../LibWeb/HTML/FormControlInfrastructure.cpp | 29 +++++++++++++------ 3 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/HTML/FormData-append-blob-with-type.txt create mode 100644 Tests/LibWeb/Text/input/HTML/FormData-append-blob-with-type.html diff --git a/Tests/LibWeb/Text/expected/HTML/FormData-append-blob-with-type.txt b/Tests/LibWeb/Text/expected/HTML/FormData-append-blob-with-type.txt new file mode 100644 index 0000000000..d4e99186d6 --- /dev/null +++ b/Tests/LibWeb/Text/expected/HTML/FormData-append-blob-with-type.txt @@ -0,0 +1,2 @@ +Name: test.txt +Type: text/plain diff --git a/Tests/LibWeb/Text/input/HTML/FormData-append-blob-with-type.html b/Tests/LibWeb/Text/input/HTML/FormData-append-blob-with-type.html new file mode 100644 index 0000000000..bef15b20a1 --- /dev/null +++ b/Tests/LibWeb/Text/input/HTML/FormData-append-blob-with-type.html @@ -0,0 +1,13 @@ + + diff --git a/Userland/Libraries/LibWeb/HTML/FormControlInfrastructure.cpp b/Userland/Libraries/LibWeb/HTML/FormControlInfrastructure.cpp index f12b046c14..3727267ba2 100644 --- a/Userland/Libraries/LibWeb/HTML/FormControlInfrastructure.cpp +++ b/Userland/Libraries/LibWeb/HTML/FormControlInfrastructure.cpp @@ -30,15 +30,26 @@ WebIDL::ExceptionOr create_entry(JS::Realm& realm, String co return TRY_OR_THROW_OOM(vm, Infra::convert_to_scalar_value_string(string)); }, // 3. Otherwise: - [&](JS::NonnullGCPtr const& blob) -> WebIDL::ExceptionOr, String>> { - // 1. If value is not a File object, then set value to a new File object, representing the same bytes, whose name attribute value is "blob". - // 2. If filename is given, then set value to a new File object, representing the same bytes, whose name attribute is filename. - String name_attribute; - if (filename.has_value()) - name_attribute = filename.value(); - else - name_attribute = "blob"_string; - return JS::make_handle(TRY(FileAPI::File::create(realm, { JS::make_handle(*blob) }, move(name_attribute), {}))); + [&](JS::NonnullGCPtr blob) -> WebIDL::ExceptionOr, String>> { + // 1. If value is not a File object, then set value to a new File object, representing the same bytes, whose + // name attribute value is "blob". + if (!is(*blob)) { + FileAPI::FilePropertyBag options {}; + options.type = blob->type(); + + blob = TRY(FileAPI::File::create(realm, { JS::make_handle(*blob) }, "blob"_string, move(options))); + } + + // 2. If filename is given, then set value to a new File object, representing the same bytes, whose name + // attribute is filename. + if (filename.has_value()) { + FileAPI::FilePropertyBag options {}; + options.type = blob->type(); + + blob = TRY(FileAPI::File::create(realm, { JS::make_handle(*blob) }, *filename, move(options))); + } + + return JS::make_handle(verify_cast(*blob)); })); // 4. Return an entry whose name is name and whose value is value.