LibDatabase: Allow String values to contain embedded null bytes
LibDatabase previously truncated String values at the first '\0' when round-tripping through SQLite due to the use of strlen. This is something which we should support according to WPT: https://wpt.live/webstorage/storage_setitem.window.html The above test works fine when run through our test-web harness as we have the SQL database disabled, so this instead adds a C++ test.
This commit is contained in:
parent
d3624c328f
commit
201c9bb154
4 changed files with 69 additions and 1 deletions
|
|
@ -170,8 +170,9 @@ ValueType Database::result_column(StatementID statement_id, int column)
|
|||
auto* statement = prepared_statement(statement_id);
|
||||
|
||||
if constexpr (IsSame<ValueType, String>) {
|
||||
auto length = sqlite3_column_bytes(statement, column);
|
||||
auto const* text = reinterpret_cast<char const*>(sqlite3_column_text(statement, column));
|
||||
return MUST(String::from_utf8(StringView { text, strlen(text) }));
|
||||
return MUST(String::from_utf8(StringView { text, static_cast<size_t>(length) }));
|
||||
} else if constexpr (IsSame<ValueType, ByteString>) {
|
||||
auto length = sqlite3_column_bytes(statement, column);
|
||||
auto const* text = sqlite3_column_blob(statement, column);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ add_subdirectory(AK)
|
|||
add_subdirectory(LibCompress)
|
||||
add_subdirectory(LibCore)
|
||||
add_subdirectory(LibCrypto)
|
||||
add_subdirectory(LibDatabase)
|
||||
add_subdirectory(LibDiff)
|
||||
add_subdirectory(LibDNS)
|
||||
add_subdirectory(LibGC)
|
||||
|
|
|
|||
7
Tests/LibDatabase/CMakeLists.txt
Normal file
7
Tests/LibDatabase/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
set(TEST_SOURCES
|
||||
TestDatabase.cpp
|
||||
)
|
||||
|
||||
foreach(source IN LISTS TEST_SOURCES)
|
||||
ladybird_test("${source}" LibDatabase LIBS LibDatabase)
|
||||
endforeach()
|
||||
59
Tests/LibDatabase/TestDatabase.cpp
Normal file
59
Tests/LibDatabase/TestDatabase.cpp
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2026, Shannon Booth <shannon@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibTest/TestCase.h>
|
||||
#include <Libraries/LibDatabase/Database.h>
|
||||
|
||||
TEST_CASE(string_can_contain_null_bytes)
|
||||
{
|
||||
auto database = TRY_OR_FAIL(Database::Database::create_memory_backed());
|
||||
|
||||
database->execute_statement(TRY_OR_FAIL(database->prepare_statement(R"#(
|
||||
CREATE TABLE WebStorage (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT
|
||||
);
|
||||
)#"sv)),
|
||||
{});
|
||||
|
||||
auto get_item_statement = TRY_OR_FAIL(database->prepare_statement("SELECT value FROM WebStorage WHERE key = ?;"sv));
|
||||
auto set_item_statement = TRY_OR_FAIL(database->prepare_statement("INSERT OR REPLACE INTO WebStorage VALUES (?, ?);"sv));
|
||||
auto delete_item_statement = TRY_OR_FAIL(database->prepare_statement("DELETE FROM WebStorage WHERE key = ?;"sv));
|
||||
|
||||
auto get_item = [&](String const& key) {
|
||||
Optional<String> result;
|
||||
database->execute_statement(
|
||||
get_item_statement,
|
||||
[&](auto statement_id) {
|
||||
result = database->result_column<String>(statement_id, 0);
|
||||
},
|
||||
key);
|
||||
return result;
|
||||
};
|
||||
|
||||
auto set_item = [&](String const& key, String const& value) {
|
||||
database->execute_statement(
|
||||
set_item_statement,
|
||||
{},
|
||||
key,
|
||||
value);
|
||||
};
|
||||
|
||||
auto remove_item = [&](String const& key) {
|
||||
database->execute_statement(
|
||||
delete_item_statement,
|
||||
{},
|
||||
key);
|
||||
};
|
||||
|
||||
EXPECT_EQ(get_item("my_key"_string), Optional<String> {});
|
||||
set_item("my_key"_string, "my_value"_string);
|
||||
EXPECT_EQ(get_item("my_key"_string), Optional<String> { "my_value"_string });
|
||||
set_item("my_key"_string, "my_value_with_\0_null"_string);
|
||||
EXPECT_EQ(get_item("my_key"_string), Optional<String> { "my_value_with_\0_null"_string });
|
||||
remove_item("my_key"_string);
|
||||
EXPECT_EQ(get_item("my_key"_string), Optional<String> {});
|
||||
}
|
||||
Loading…
Reference in a new issue