0

C++11 std::array rewrite for memory safety [4/19]

Split from:
https://chromium-review.googlesource.com/c/chromium/src/+/6004959/21

Generated patch
---------------
- Tool: ./tool/clang/spanify/rewrite-multiple-platform.sh
- Platform: Linux.
- Filter: This includes 2400/4222 patches. I included the std::array
      ones and excluded build errors.

Google announcement:
--------------------
https://groups.google.com/a/google.com/g/chrome-memory-safety/c/RMiO4gaVLQA/m/Yz-3NCObAgAJ

Benchmarks:
----------
See design doc and
https://chromium-review.googlesource.com/c/chromium/src/+/6004959/21

Description
-----------
The consensus during the memory safety summit was to begin rewriting
relevant C-style arrays to C++11 std::array. It can be done immediately,
offers better developer ergonomics, and fix large chunks of the
-Wunsafe-buffer-usage errors in Chrome.

To clarify, this effort is complementary to the longer plan work with
enabling -fsanitize=array-bounds, and we plan to leverage both,
especially for protecting 3p code.

[Attached] is a document detailing the rationale, benefits, and
considerations for potential compile-time and performance impacts.

[Attached]:https://docs.google.com/document/d/1z5aBDg26lHmNDjXRCysElWKx7E4PAJXqykI_k7ondJI/edit?tab=t.0#heading=h.cqgo7wvp0kzt

NO_IFTTT=No need to update base/debug/stack_trace.h

Bug: 378069401
Change-Id: I838a8c44e82ed27dc75e771acec31d84992860af
R: dcheng@chromium.org
AX-Relnotes: n/a.
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6038951
Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org>
Auto-Submit: Arthur Sonzogni <arthursonzogni@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Alexei Svitkine <asvitkine@chromium.org>
Owners-Override: Daniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1394163}
This commit is contained in:
Arthur Sonzogni
2024-12-10 09:58:59 +00:00
committed by Chromium LUCI CQ
parent deef7d51df
commit b7c1fd51e1
20 changed files with 224 additions and 185 deletions

@ -2,16 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "components/dom_distiller/core/distiller.h"
#include <stddef.h>
#include <algorithm>
#include <array>
#include <map>
#include <memory>
#include <string>
@ -55,9 +51,12 @@ const char kOtherURL[] = "http://b.com/";
const size_t kTotalGoodImages = 2;
const size_t kTotalImages = 3;
// Good images need to be in the front.
const char* kImageURLs[kTotalImages] = {
"http://a.com/img1.jpg", "http://a.com/img2.jpg", "./bad_url_should_fail"};
const char* kImageData[kTotalImages] = {"abcde", "12345", "VWXYZ"};
std::array<const char*, kTotalImages> kImageURLs = {
"http://a.com/img1.jpg",
"http://a.com/img2.jpg",
"./bad_url_should_fail",
};
std::array<const char*, kTotalImages> kImageData = {"abcde", "12345", "VWXYZ"};
const char kDebugLog[] = "Debug Log";
const std::string GetImageName(int page_num, int image_num) {

@ -2,15 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "components/domain_reliability/context.h"
#include <stddef.h>
#include <array>
#include <map>
#include <memory>
#include <string>
@ -1267,10 +1263,10 @@ TEST_F(DomainReliabilityContextTest,
InitContext(MakeTestConfig());
net::IsolationInfo isolation_infos[] = {
auto isolation_infos = std::to_array<net::IsolationInfo>({
net::IsolationInfo::CreateTransient(),
net::IsolationInfo::CreateTransient(),
};
});
// Add `DomainReliabilityContext::kMaxQueuedBeacons` beacons, using a
// different IsolationInfo for every other beacon.

@ -2,13 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "components/enterprise/browser/reporting/report_uploader.h"
#include <array>
#include <utility>
#include "base/test/metrics/histogram_tester.h"
@ -33,7 +29,8 @@ namespace em = enterprise_management;
namespace enterprise_reporting {
namespace {
constexpr const char* kBrowserVersionNames[] = {"name1", "name2"};
constexpr const auto kBrowserVersionNames =
std::to_array<const char*>({"name1", "name2"});
constexpr char kResponseMetricsName[] = "Enterprise.CloudReportingResponse";
// Returns a function that schedules a callback it is passed as second parameter

@ -2,15 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "components/favicon/core/fallback_url_util.h"
#include <stddef.h>
#include <array>
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@ -19,39 +16,40 @@ namespace favicon {
namespace {
TEST(FallbackURLUtilTest, GetFallbackIconText) {
struct {
struct TestCases {
const char* url_str;
const char* expected;
} test_cases[] = {
// Test vacuous or invalid cases.
{"", ""},
{"http:///", ""},
{"this is not an URL", ""},
{"!@#$%^&*()", ""},
// Test URLs with a domain in the registry.
{"http://www.google.com/", "G"},
{"ftp://GOogLE.com/", "G"},
{"https://www.google.com:8080/path?query#ref", "G"},
{"http://www.amazon.com", "A"},
{"http://zmzaon.co.uk/", "Z"},
{"http://w-3.137.org", "1"},
// Test URLs with a domain not in the registry.
{"http://localhost/", "L"},
{"chrome-search://most-visited/title.html", "M"},
// Test IP URLs.
{"http://192.168.0.1/", "IP"},
{"http://[2001:4860:4860::8888]/", "IP"},
#if BUILDFLAG(IS_IOS)
// Test Android app URLs.
{"android://abc@org.coursera.android//", "A"},
#endif
// Miscellaneous edge cases.
{"http://www..com/", "."},
{"http://ip.ip/", "I"},
// xn-- related cases: we're not supporint xn-- yet
{"http://xn--oogle-60a/", "X"},
{"http://xn-oogle-60a/", "X"},
};
auto test_cases = std::to_array<TestCases>({
// Test vacuous or invalid cases.
{"", ""},
{"http:///", ""},
{"this is not an URL", ""},
{"!@#$%^&*()", ""},
// Test URLs with a domain in the registry.
{"http://www.google.com/", "G"},
{"ftp://GOogLE.com/", "G"},
{"https://www.google.com:8080/path?query#ref", "G"},
{"http://www.amazon.com", "A"},
{"http://zmzaon.co.uk/", "Z"},
{"http://w-3.137.org", "1"},
// Test URLs with a domain not in the registry.
{"http://localhost/", "L"},
{"chrome-search://most-visited/title.html", "M"},
// Test IP URLs.
{"http://192.168.0.1/", "IP"},
{"http://[2001:4860:4860::8888]/", "IP"},
#if BUILDFLAG(IS_IOS)
// Test Android app URLs.
{"android://abc@org.coursera.android//", "A"},
#endif
// Miscellaneous edge cases.
{"http://www..com/", "."},
{"http://ip.ip/", "I"},
// xn-- related cases: we're not supporint xn-- yet
{"http://xn--oogle-60a/", "X"},
{"http://xn-oogle-60a/", "X"},
});
for (size_t i = 0; i < std::size(test_cases); ++i) {
std::u16string expected = base::ASCIIToUTF16(test_cases[i].expected);
GURL url(test_cases[i].url_str);

@ -2,15 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "components/feedback/redaction_tool/redaction_tool.h"
#include <gtest/gtest.h>
#include <array>
#include <set>
#include <string_view>
#include <utility>
@ -603,7 +599,7 @@ TEST_F(RedactionToolTest, RedactCustomPatterns) {
EXPECT_EQ("(URL: 1)", RedactCustomPatterns("http://example.com/foo?test=1"));
EXPECT_EQ("Foo (URL: 2) Bar",
RedactCustomPatterns("Foo http://192.168.0.1/foo?test=1#123 Bar"));
const char* kURLs[] = {
auto kURLs = std::to_array<const char*>({
"http://example.com/foo?test=1",
"http://userid:password@example.com:8080",
"http://userid:password@example.com:8080/",
@ -621,7 +617,7 @@ TEST_F(RedactionToolTest, RedactCustomPatterns) {
"https://aaaaaaaaaaaaaaaa.com",
"file:///var/log/messages",
"file:///usr/local/home/iby/web%20page%20test.html",
};
});
for (size_t i = 0; i < std::size(kURLs); ++i) {
SCOPED_TRACE(kURLs[i]);
std::string got = RedactCustomPatterns(kURLs[i]);

@ -2,15 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "components/flags_ui/flags_state.h"
#include <stddef.h>
#include <array>
#include <map>
#include <memory>
#include <set>
@ -123,7 +119,7 @@ const FeatureEntry::Choice kMultiChoices[] = {
// The entries that are set for these tests. The 3rd entry is not supported on
// the current platform, all others are.
static FeatureEntry kEntries[] = {
auto kEntries = std::to_array<FeatureEntry>({
{kFlags1, kDummyName, kDummyDescription,
0, // Ends up being mapped to the current platform.
SINGLE_VALUE_TYPE(kSwitch1)},
@ -169,7 +165,8 @@ static FeatureEntry kEntries[] = {
0, // Ends up being mapped to the current platform.
FEATURE_WITH_PARAMS_VALUE_TYPE(kTestFeature3,
kTestVariations3,
kTestTrial)}};
kTestTrial)},
});
class FlagsStateTest : public ::testing::Test,
public flags_ui::FlagsState::Delegate {
@ -495,13 +492,14 @@ TEST_F(FlagsStateTest, RemoveFlagSwitches) {
}
TEST_F(FlagsStateTest, RemoveFlagSwitches_Features) {
struct {
struct Cases {
int enabled_choice; // 0: default, 1: enabled, 2: disabled.
const char* existing_enable_features;
const char* existing_disable_features;
const char* expected_enable_features;
const char* expected_disable_features;
} cases[] = {
};
auto cases = std::to_array<Cases>({
// Default value: Should not affect existing flags.
{0, nullptr, nullptr, nullptr, nullptr},
{0, "A,B", "C", "A,B", "C"},
@ -511,7 +509,7 @@ TEST_F(FlagsStateTest, RemoveFlagSwitches_Features) {
// "Disable" option: should only affect disabled list.
{2, nullptr, nullptr, nullptr, "FeatureName1"},
{2, "A,B", "C", "A,B", "C,FeatureName1"},
};
});
for (size_t i = 0; i < std::size(cases); ++i) {
SCOPED_TRACE(base::StringPrintf(
@ -795,13 +793,14 @@ TEST_F(FlagsStateTest, FeatureValues) {
const FeatureEntry& entry = kEntries[6];
ASSERT_EQ(kFlags7, entry.internal_name);
struct {
struct Cases {
int enabled_choice;
const char* existing_enable_features;
const char* existing_disable_features;
const char* expected_enable_features;
const char* expected_disable_features;
} cases[] = {
};
auto cases = std::to_array<Cases>({
// Nothing selected.
{-1, nullptr, nullptr, "", ""},
// "Default" option selected, same as nothing selected.
@ -814,7 +813,7 @@ TEST_F(FlagsStateTest, FeatureValues) {
{1, "Foo,Bar", nullptr, "Foo,Bar,FeatureName1", ""},
// "Disable" option should get added to the existing list.
{2, nullptr, "Foo,Bar", "", "Foo,Bar,FeatureName1"},
};
});
for (size_t i = 0; i < std::size(cases); ++i) {
SCOPED_TRACE(base::StringPrintf(

@ -4,6 +4,7 @@
#include "components/heap_profiling/in_process/heap_profiler_controller.h"
#include <array>
#include <atomic>
#include <iomanip>
#include <memory>
@ -1322,14 +1323,14 @@ auto GetProfileMetadataFunc(std::string_view name) {
}
// End-to-end test with multiple child processes.
constexpr FeatureTestParams kMultipleChildConfigs[] = {
constexpr const auto kMultipleChildConfigs = std::to_array<FeatureTestParams>({
{
.gpu_snapshot_prob = 100,
.network_snapshot_prob = 100,
.renderer_snapshot_prob = 66,
.utility_snapshot_prob = 50,
},
};
});
using HeapProfilerControllerMultipleChildTest = HeapProfilerControllerTest;

@ -4,6 +4,8 @@
#include "components/history_embeddings/sql_database.h"
#include <array>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
@ -145,10 +147,10 @@ TEST_F(HistoryEmbeddingsSqlDatabaseTest, WriteCloseAndThenReadUrlData) {
GetEncryptorInstance());
// Write embeddings.
UrlData url_datas[] = {
auto url_datas = std::to_array<UrlData>({
UrlData(1, 1, base::Time::Now()),
UrlData(2, 2, base::Time::Now()),
};
});
url_datas[0].passages.add_passages("data 0 passage 0");
url_datas[0].embeddings.push_back(FakeEmbedding());
url_datas[1].passages.add_passages("data 1 passage 0");
@ -459,10 +461,10 @@ TEST_F(HistoryEmbeddingsSqlDatabaseTest, IterationSkipsAndReportsMismatches) {
GetEncryptorInstance());
// Write embeddings.
UrlData url_datas[] = {
auto url_datas = std::to_array<UrlData>({
UrlData(1, 1, base::Time::Now()),
UrlData(2, 2, base::Time::Now()),
};
});
url_datas[0].passages.add_passages("data 0 passage 0");
url_datas[0].embeddings.push_back(FakeEmbedding());
url_datas[1].passages.add_passages("data 1 passage 0");
@ -498,11 +500,11 @@ TEST_F(HistoryEmbeddingsSqlDatabaseTest, OldVisitsAreExpired) {
GetEncryptorInstance());
// Write embeddings; one for an old visit, one for a new visit.
UrlData url_datas[] = {
auto url_datas = std::to_array<UrlData>({
UrlData(/*url_id=*/1, /*visit_id=*/1,
base::Time::Now() - base::Days(100)),
UrlData(/*url_id=*/2, /*visit_id=*/2, base::Time::Now()),
};
});
url_datas[0].passages.add_passages("data 0 passage 0");
url_datas[0].embeddings.push_back(FakeEmbedding());
url_datas[1].passages.add_passages("data 1 passage 0");

@ -9,6 +9,7 @@
#include "components/metrics/field_trials_provider.h"
#include <array>
#include <string_view>
#include "base/metrics/field_trial.h"
@ -28,11 +29,13 @@ namespace {
constexpr const char* kSuffix = "UKM";
const ActiveGroup kFieldTrials[] = {{"Trial1", "Group1"},
{"Trial2", "Group2"},
{"Trial3", "Group3"}};
const ActiveGroup kSyntheticFieldTrials[] = {{"Synthetic1", "SyntheticGroup1"},
{"Synthetic2", "SyntheticGroup2"}};
const auto kFieldTrials = std::to_array<ActiveGroup>({
{"Trial1", "Group1"},
{"Trial2", "Group2"},
{"Trial3", "Group3"},
});
const auto kSyntheticFieldTrials = std::to_array<ActiveGroup>(
{{"Synthetic1", "SyntheticGroup1"}, {"Synthetic2", "SyntheticGroup2"}});
ActiveGroupId ToActiveGroupId(ActiveGroup active_group,
std::string suffix = "");

@ -2,15 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "components/net_log/net_export_file_writer.h"
#include <stdint.h>
#include <array>
#include <memory>
#include <optional>
@ -537,14 +533,17 @@ TEST_F(NetExportFileWriterTest, InitWithExistingLog) {
}
TEST_F(NetExportFileWriterTest, StartAndStopWithAllCaptureModes) {
const net::NetLogCaptureMode capture_modes[3] = {
const std::array<net::NetLogCaptureMode, 3> capture_modes = {
net::NetLogCaptureMode::kDefault,
net::NetLogCaptureMode::kIncludeSensitive,
net::NetLogCaptureMode::kEverything};
net::NetLogCaptureMode::kEverything,
};
const std::string capture_mode_strings[3] = {
kCaptureModeDefaultString, kCaptureModeIncludeSensitiveString,
kCaptureModeIncludeEverythingString};
const std::array<std::string, 3> capture_mode_strings = {
kCaptureModeDefaultString,
kCaptureModeIncludeSensitiveString,
kCaptureModeIncludeEverythingString,
};
ASSERT_TRUE(InitializeThenVerifyNewState(true, false));

@ -6,6 +6,7 @@
#include <stdint.h>
#include <array>
#include <memory>
#include "base/files/scoped_temp_dir.h"
@ -30,16 +31,17 @@ struct TestCaseItem {
const char16_t* title;
};
const TestCaseItem kTestCase1[] = {{"http://foo1.com/", u"Foo1"}};
const TestCaseItem kTestCase2[] = {
const auto kTestCase1 =
std::to_array<TestCaseItem>({{"http://foo1.com/", u"Foo1"}});
const auto kTestCase2 = std::to_array<TestCaseItem>({
{"http://foo1.com/", u"Foo1"},
{"http://foo2.com/", u"Foo2"},
};
const TestCaseItem kTestCase3[] = {
});
const auto kTestCase3 = std::to_array<TestCaseItem>({
{"http://foo1.com/", u"Foo1"},
{"http://foo2.com/", u"Foo2"},
{"http://foo3.com/", u"Foo3"},
};
});
const TestCaseItem kTestCaseMax[] = {
{"http://foo1.com/", u"Foo1"}, {"http://foo2.com/", u"Foo2"},
{"http://foo3.com/", u"Foo3"}, {"http://foo4.com/", u"Foo4"},

@ -9,6 +9,7 @@
#include "components/open_from_clipboard/clipboard_recent_content_generic.h"
#include <array>
#include <memory>
#include <string>
#include <utility>
@ -95,10 +96,11 @@ class ClipboardRecentContentGenericTest : public testing::Test {
};
TEST_F(ClipboardRecentContentGenericTest, RecognizesURLs) {
struct {
struct TestData {
std::string clipboard;
const bool expected_get_recent_url_value;
} test_data[] = {
};
auto test_data = std::to_array<TestData>({
{"www", false},
{"query string", false},
{"www.example.com", false},
@ -125,7 +127,7 @@ TEST_F(ClipboardRecentContentGenericTest, RecognizesURLs) {
{"http://點看/path", true},
{" http://點看/path ", true},
{" http://點看/path extra word", false},
};
});
ClipboardRecentContentGeneric recent_content;
base::Time now = base::Time::Now();

@ -2,13 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "components/page_content_annotations/core/page_content_annotations_service.h"
#include <array>
#include "base/strings/utf_string_conversions.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/gmock_move_support.h"
@ -356,7 +353,7 @@ TEST_F(PageContentAnnotationsServiceTest, OlderVisitsDropped) {
// First 2 visits are always processed, then the next 4 are queued and the
// most recent 2 are annotated.
constexpr base::Time kTestTime = base::Time() + base::Days(1000);
constexpr base::Time kTimestamps[6] = {
constexpr std::array<base::Time, 6> kTimestamps = {
// Queue not full, gets annotated.
kTestTime + base::Days(12),
kTestTime,

@ -2,13 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "components/reading_list/core/reading_list_sync_bridge.h"
#include <array>
#include <map>
#include <set>
#include <utility>
@ -558,10 +554,12 @@ TEST_F(ReadingListSyncBridgeTest, CompareEntriesForSync) {
entryA.set_update_time_us(99);
ExpectAB(entryA, entryB, true);
ExpectAB(entryB, entryA, false);
sync_pb::ReadingListSpecifics::ReadingListEntryStatus status_oder[3] = {
sync_pb::ReadingListSpecifics::UNSEEN,
sync_pb::ReadingListSpecifics::UNREAD,
sync_pb::ReadingListSpecifics::READ};
std::array<sync_pb::ReadingListSpecifics::ReadingListEntryStatus, 3>
status_oder = {
sync_pb::ReadingListSpecifics::UNSEEN,
sync_pb::ReadingListSpecifics::UNREAD,
sync_pb::ReadingListSpecifics::READ,
};
for (int index_a = 0; index_a < 3; index_a++) {
entryA.set_status(status_oder[index_a]);
for (int index_b = 0; index_b < 3; index_b++) {

@ -20,14 +20,15 @@
namespace reduce_accept_language {
TEST(InMemoryReduceAcceptLanguageServiceTests, ValidTests) {
const struct {
struct Tests {
std::vector<std::string> user_accept_language;
std::string persist_language;
} tests[] = {
};
const auto tests = std::to_array<Tests>({
{{}, "zh"},
{{"en-us"}, "zh"},
{{"en-us", "zh"}, "zh"},
};
});
for (size_t i = 0; i < std::size(tests); ++i) {
InMemoryReduceAcceptLanguageService in_memory_service(

@ -2,15 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "components/search_engines/template_url.h"
#include <stddef.h>
#include <array>
#include <string>
#include "base/base64.h"
@ -125,14 +121,16 @@ TEST_F(TemplateURLTest, URLRefTestSearchTerms) {
const char* url;
const std::u16string terms;
const std::string output;
} search_term_cases[] = {
};
auto search_term_cases = std::to_array<SearchTermsCase>({
{"http://foo{searchTerms}", u"sea rch/bar", "http://foosea%20rch/bar"},
{"http://foo{searchTerms}?boo=abc", u"sea rch/bar",
"http://foosea%20rch/bar?boo=abc"},
{"http://foo/?boo={searchTerms}", u"sea rch/bar",
"http://foo/?boo=sea+rch%2Fbar"},
{"http://en.wikipedia.org/{searchTerms}", u"wiki/?",
"http://en.wikipedia.org/wiki/%3F"}};
"http://en.wikipedia.org/wiki/%3F"},
});
for (size_t i = 0; i < std::size(search_term_cases); ++i) {
const SearchTermsCase& value = search_term_cases[i];
TemplateURLData data;
@ -550,10 +548,12 @@ TEST_F(TemplateURLTest, URLRefTestSearchTermsUsingTermsData) {
const char* url;
const std::u16string terms;
const char* output;
} search_term_cases[] = {{"{google:baseURL}{language}{searchTerms}",
std::u16string(), "http://example.com/e/en"},
{"{google:baseSuggestURL}{searchTerms}",
std::u16string(), "http://example.com/complete/"}};
};
auto search_term_cases = std::to_array<SearchTermsCase>(
{{"{google:baseURL}{language}{searchTerms}", std::u16string(),
"http://example.com/e/en"},
{"{google:baseSuggestURL}{searchTerms}", std::u16string(),
"http://example.com/complete/"}});
TestingSearchTermsData search_terms_data("http://example.com/e/");
TemplateURLData data;
@ -575,7 +575,8 @@ TEST_F(TemplateURLTest, URLRefTermToWide) {
struct ToWideCase {
const char* encoded_search_term;
const std::u16string expected_decoded_term;
} to_wide_cases[] = {
};
auto to_wide_cases = std::to_array<ToWideCase>({
{"hello+world", u"hello world"},
// Test some big-5 input.
{"%a7A%A6%6e+to+you", u"\x4f60\x597d to you"},
@ -589,7 +590,7 @@ TEST_F(TemplateURLTest, URLRefTermToWide) {
{"C%2B%2B", u"C++"},
// C%2B is escaped as C%252B, make sure we unescape it properly.
{"C%252B", u"C%2B"},
};
});
// Set one input encoding: big-5. This is so we can test fallback to UTF-8.
TemplateURLData data;
@ -1361,16 +1362,32 @@ TEST_F(TemplateURLTest, SearchTermKeyLocation) {
}
TEST_F(TemplateURLTest, GoogleBaseSuggestURL) {
static const struct {
struct Data {
const char* const base_url;
const char* const base_suggest_url;
} data[] = {
{ "http://google.com/", "http://google.com/complete/", },
{ "http://www.google.com/", "http://www.google.com/complete/", },
{ "http://www.google.co.uk/", "http://www.google.co.uk/complete/", },
{ "http://www.google.com.by/", "http://www.google.com.by/complete/", },
{ "http://google.com/intl/xx/", "http://google.com/complete/", },
};
static const auto data = std::to_array<Data>({
{
"http://google.com/",
"http://google.com/complete/",
},
{
"http://www.google.com/",
"http://www.google.com/complete/",
},
{
"http://www.google.co.uk/",
"http://www.google.co.uk/complete/",
},
{
"http://www.google.com.by/",
"http://www.google.com.by/complete/",
},
{
"http://google.com/intl/xx/",
"http://google.com/complete/",
},
});
for (size_t i = 0; i < std::size(data); ++i)
CheckSuggestBaseURL(data[i].base_url, data[i].base_suggest_url);
@ -2169,21 +2186,52 @@ TEST_F(TemplateURLTest, IsSearchURL) {
data.alternate_urls.push_back("http://bar/webhp#q={searchTerms}");
TemplateURL search_provider(data);
const struct {
struct UrlData {
const char* const url;
bool result;
} url_data[] = {
{ "http://bar/search?q=foo&oq=foo", true, },
{ "http://bar/?q=foo&oq=foo", true, },
{ "http://bar/#output=search&q=foo&oq=foo", true, },
{ "http://bar/webhp#q=foo&oq=foo", true, },
{ "http://bar/#q=foo&oq=foo", true, },
{ "http://bar/?ext=foo&q=foo#ref=bar", true, },
{ "http://bar/url?url=http://www.foo.com/&q=foo#ref=bar", false, },
{ "http://bar/", false, },
{ "http://foo/", false, },
{ "http://bar/newtab", false, },
};
const auto url_data = std::to_array<UrlData>({
{
"http://bar/search?q=foo&oq=foo",
true,
},
{
"http://bar/?q=foo&oq=foo",
true,
},
{
"http://bar/#output=search&q=foo&oq=foo",
true,
},
{
"http://bar/webhp#q=foo&oq=foo",
true,
},
{
"http://bar/#q=foo&oq=foo",
true,
},
{
"http://bar/?ext=foo&q=foo#ref=bar",
true,
},
{
"http://bar/url?url=http://www.foo.com/&q=foo#ref=bar",
false,
},
{
"http://bar/",
false,
},
{
"http://foo/",
false,
},
{
"http://bar/newtab",
false,
},
});
for (size_t i = 0; i < std::size(url_data); ++i) {
EXPECT_EQ(url_data[i].result,

@ -4,6 +4,7 @@
#include "components/send_tab_to_self/send_tab_to_self_entry.h"
#include <array>
#include <memory>
#include "base/strings/utf_string_conversions.h"
@ -109,7 +110,7 @@ TEST(SendTabToSelfEntry, IsExpired) {
// Tests that the send tab to self entry rejects strings that are not utf8.
TEST(SendTabToSelfEntry, InvalidStrings) {
const char16_t term[1] = {u'\uFDD1'};
const std::array<char16_t, 1> term = {u'\uFDD1'};
std::string invalid_utf8;
base::UTF16ToUTF8(&term[0], 1, &invalid_utf8);

@ -10,6 +10,7 @@
#include <stddef.h>
#include <stdint.h>
#include <array>
#include <map>
#include <string>
@ -47,13 +48,15 @@ TEST_F(DirectoryImplTest, Read) {
base::File::Error error;
// Make some files.
const struct {
struct FilesToCreate {
const char* name;
uint32_t open_flags;
} files_to_create[] = {
};
const auto files_to_create = std::to_array<FilesToCreate>({
{"my_file1", mojom::kFlagRead | mojom::kFlagWrite | mojom::kFlagCreate},
{"my_file2", mojom::kFlagWrite | mojom::kFlagCreate},
{"my_file3", mojom::kFlagAppend | mojom::kFlagCreate}};
{"my_file3", mojom::kFlagAppend | mojom::kFlagCreate},
});
for (size_t i = 0; i < std::size(files_to_create); i++) {
error = base::File::Error::FILE_ERROR_FAILED;
base::File tmp_base_file;

@ -2,13 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "components/session_proto_db/session_proto_db.h"
#include <array>
#include <map>
#include "base/functional/bind.h"
@ -341,7 +337,7 @@ TEST_F(SessionProtoDBTest, TestArbitraryProto) {
InitTestProtoDB();
test_content_db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
RunUntilIdle();
base::RunLoop run_loop[2];
std::array<base::RunLoop, 2> run_loop;
test_proto_db()->InsertContent(
kMockKeyA, kTestProto,
base::BindOnce(&SessionProtoDBTest::OperationEvaluation,
@ -366,7 +362,7 @@ TEST_F(SessionProtoDBTest, TestInit) {
TEST_F(SessionProtoDBTest, TestKeyInsertionSucceeded) {
InitPersistedStateDB();
base::RunLoop run_loop[2];
std::array<base::RunLoop, 2> run_loop;
persisted_state_db()->InsertContent(
kMockKeyA, kMockValueA,
base::BindOnce(&SessionProtoDBTest::OperationEvaluation,
@ -384,7 +380,7 @@ TEST_F(SessionProtoDBTest, TestKeyInsertionSucceeded) {
TEST_F(SessionProtoDBTest, TestKeyInsertionFailed) {
InitPersistedStateDB();
base::RunLoop run_loop[2];
std::array<base::RunLoop, 2> run_loop;
persisted_state_db()->InsertContent(
kMockKeyA, kMockValueA,
base::BindOnce(&SessionProtoDBTest::OperationEvaluation,
@ -402,7 +398,7 @@ TEST_F(SessionProtoDBTest, TestKeyInsertionFailed) {
TEST_F(SessionProtoDBTest, TestKeyInsertionPrefix) {
InitPersistedStateDB();
base::RunLoop run_loop[2];
std::array<base::RunLoop, 2> run_loop;
persisted_state_db()->InsertContent(
kMockKeyA, kMockValueA,
base::BindOnce(&SessionProtoDBTest::OperationEvaluation,
@ -420,7 +416,7 @@ TEST_F(SessionProtoDBTest, TestKeyInsertionPrefix) {
TEST_F(SessionProtoDBTest, TestLoadOneEntry) {
InitPersistedStateDB();
base::RunLoop run_loop[4];
std::array<base::RunLoop, 4> run_loop;
persisted_state_db()->InsertContent(
kMockKeyA, kMockValueA,
base::BindOnce(&SessionProtoDBTest::OperationEvaluation,
@ -451,7 +447,7 @@ TEST_F(SessionProtoDBTest, TestLoadOneEntry) {
TEST_F(SessionProtoDBTest, TestLoadAllEntries) {
InitPersistedStateDB();
base::RunLoop run_loop[3];
std::array<base::RunLoop, 3> run_loop;
persisted_state_db()->InsertContent(
kMockKeyA, kMockValueA,
base::BindOnce(&SessionProtoDBTest::OperationEvaluation,
@ -473,7 +469,7 @@ TEST_F(SessionProtoDBTest, TestLoadAllEntries) {
TEST_F(SessionProtoDBTest, TestDeleteWithPrefix) {
InitPersistedStateDB();
base::RunLoop run_loop[4];
std::array<base::RunLoop, 4> run_loop;
persisted_state_db()->InsertContent(
kMockKeyA, kMockValueA,
base::BindOnce(&SessionProtoDBTest::OperationEvaluation,
@ -506,7 +502,7 @@ TEST_F(SessionProtoDBTest, TestDeleteWithPrefix) {
TEST_F(SessionProtoDBTest, TestDeleteOneEntry) {
InitPersistedStateDB();
base::RunLoop run_loop[6];
std::array<base::RunLoop, 6> run_loop;
persisted_state_db()->InsertContent(
kMockKeyA, kMockValueA,
base::BindOnce(&SessionProtoDBTest::OperationEvaluation,
@ -552,7 +548,7 @@ TEST_F(SessionProtoDBTest, TestDeferredOperations) {
InitPersistedStateDBWithoutCallback();
RunUntilIdle();
EXPECT_EQ(true, InitStatusUnknown());
base::RunLoop run_loop[4];
std::array<base::RunLoop, 4> run_loop;
persisted_state_db()->InsertContent(
kMockKeyA, kMockValueA,
@ -595,7 +591,7 @@ TEST_F(SessionProtoDBTest, TestInitializationFailure) {
InitPersistedStateDBWithoutCallback();
RunUntilIdle();
EXPECT_EQ(true, InitStatusUnknown());
base::RunLoop run_loop[6];
std::array<base::RunLoop, 6> run_loop;
// Do some operations before database status is known
persisted_state_db()->InsertContent(
@ -649,7 +645,7 @@ TEST_F(SessionProtoDBTest, TestInitializationFailure) {
TEST_F(SessionProtoDBTest, TestUpdateEntries) {
InitPersistedStateDB();
base::RunLoop run_loop[6];
std::array<base::RunLoop, 6> run_loop;
persisted_state_db()->InsertContent(
kMockKeyA, kMockValueA,
base::BindOnce(&SessionProtoDBTest::OperationEvaluation,

@ -11,6 +11,7 @@
#include <stddef.h>
#include <array>
#include <limits>
#include <utility>
@ -202,7 +203,7 @@ TEST_F(CommandStorageBackendTest, SimpleReadWriteEncrypted) {
}
TEST_F(CommandStorageBackendTest, RandomDataEncrypted) {
struct TestData data[] = {
auto data = std::to_array<TestData>({
{1, "a"},
{2, "ab"},
{3, "abc"},
@ -216,7 +217,7 @@ TEST_F(CommandStorageBackendTest, RandomDataEncrypted) {
{11, "abcdefghijk"},
{12, "abcdefghijkl"},
{13, "abcdefghijklm"},
};
});
const std::vector<uint8_t> key = CommandStorageManager::CreateCryptoKey();
for (size_t i = 0; i < std::size(data); ++i) {
@ -240,10 +241,10 @@ TEST_F(CommandStorageBackendTest, RandomDataEncrypted) {
}
TEST_F(CommandStorageBackendTest, BigDataEncrypted) {
struct TestData data[] = {
auto data = std::to_array<TestData>({
{1, "a"},
{2, "ab"},
};
});
const std::vector<uint8_t> key = CommandStorageManager::CreateCryptoKey();
scoped_refptr<CommandStorageBackend> backend = CreateBackend();
@ -422,7 +423,7 @@ TEST_F(CommandStorageBackendTest, SimpleReadWriteWithRestoreType) {
}
TEST_F(CommandStorageBackendTest, RandomDataWithRestoreType) {
struct TestData data[] = {
auto data = std::to_array<TestData>({
{1, "a"},
{2, "ab"},
{3, "abc"},
@ -436,7 +437,7 @@ TEST_F(CommandStorageBackendTest, RandomDataWithRestoreType) {
{11, "abcdefghijk"},
{12, "abcdefghijkl"},
{13, "abcdefghijklm"},
};
});
for (size_t i = 0; i < std::size(data); ++i) {
scoped_refptr<CommandStorageBackend> backend =
@ -459,10 +460,10 @@ TEST_F(CommandStorageBackendTest, RandomDataWithRestoreType) {
}
TEST_F(CommandStorageBackendTest, BigDataWithRestoreType) {
struct TestData data[] = {
auto data = std::to_array<TestData>({
{1, "a"},
{2, "ab"},
};
});
scoped_refptr<CommandStorageBackend> backend = CreateBackendWithRestoreType();
std::vector<std::unique_ptr<SessionCommand>> commands;