Bug 1861751 Part 4: Add tests of invalid buffers in various usages. r=webgpu-reviewer...
[gecko.git] / storage / SQLCollations.cpp
blob3cbeafe5d0be7d7e69f1e5a8e9fc159da8b0647c
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/ArrayUtils.h"
8 #include "mozilla/intl/Collator.h"
10 #include "SQLCollations.h"
12 using mozilla::intl::Collator;
14 namespace mozilla {
15 namespace storage {
17 ////////////////////////////////////////////////////////////////////////////////
18 //// Local Helper Functions
20 namespace {
22 /**
23 * Helper function for the UTF-8 locale collations.
25 * @param aService
26 * The Service that owns the collator used by this collation.
27 * @param aLen1
28 * The number of bytes in aStr1.
29 * @param aStr1
30 * The string to be compared against aStr2 as provided by SQLite. It
31 * must be a non-null-terminated char* buffer.
32 * @param aLen2
33 * The number of bytes in aStr2.
34 * @param aStr2
35 * The string to be compared against aStr1 as provided by SQLite. It
36 * must be a non-null-terminated char* buffer.
37 * @param aSensitivity
38 * The sorting sensitivity.
39 * @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative number.
40 * If aStr1 > aStr2, returns a positive number. If aStr1 == aStr2,
41 * returns 0.
43 int localeCollationHelper8(void* aService, int aLen1, const void* aStr1,
44 int aLen2, const void* aStr2,
45 Collator::Sensitivity aSensitivity) {
46 NS_ConvertUTF8toUTF16 str1(static_cast<const char*>(aStr1), aLen1);
47 NS_ConvertUTF8toUTF16 str2(static_cast<const char*>(aStr2), aLen2);
48 Service* serv = static_cast<Service*>(aService);
49 return serv->localeCompareStrings(str1, str2, aSensitivity);
52 /**
53 * Helper function for the UTF-16 locale collations.
55 * @param aService
56 * The Service that owns the collator used by this collation.
57 * @param aLen1
58 * The number of bytes (not characters) in aStr1.
59 * @param aStr1
60 * The string to be compared against aStr2 as provided by SQLite. It
61 * must be a non-null-terminated char16_t* buffer.
62 * @param aLen2
63 * The number of bytes (not characters) in aStr2.
64 * @param aStr2
65 * The string to be compared against aStr1 as provided by SQLite. It
66 * must be a non-null-terminated char16_t* buffer.
67 * @param aSensitivity
68 * The sorting sensitivity.
69 * @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative number.
70 * If aStr1 > aStr2, returns a positive number. If aStr1 == aStr2,
71 * returns 0.
73 int localeCollationHelper16(void* aService, int aLen1, const void* aStr1,
74 int aLen2, const void* aStr2,
75 Collator::Sensitivity aSensitivity) {
76 const char16_t* buf1 = static_cast<const char16_t*>(aStr1);
77 const char16_t* buf2 = static_cast<const char16_t*>(aStr2);
79 // The second argument to the nsDependentSubstring constructor is exclusive:
80 // It points to the char16_t immediately following the last one in the target
81 // substring. Since aLen1 and aLen2 are in bytes, divide by sizeof(char16_t)
82 // so that the pointer arithmetic is correct.
83 nsDependentSubstring str1(buf1, buf1 + (aLen1 / sizeof(char16_t)));
84 nsDependentSubstring str2(buf2, buf2 + (aLen2 / sizeof(char16_t)));
85 Service* serv = static_cast<Service*>(aService);
86 return serv->localeCompareStrings(str1, str2, aSensitivity);
89 // This struct is used only by registerCollations below, but ISO C++98 forbids
90 // instantiating a template dependent on a locally-defined type. Boo-urns!
91 struct Collations {
92 const char* zName;
93 int enc;
94 int (*xCompare)(void*, int, const void*, int, const void*);
97 } // namespace
99 ////////////////////////////////////////////////////////////////////////////////
100 //// Exposed Functions
102 int registerCollations(sqlite3* aDB, Service* aService) {
103 Collations collations[] = {
104 {"locale", SQLITE_UTF8, localeCollation8},
105 {"locale_case_sensitive", SQLITE_UTF8, localeCollationCaseSensitive8},
106 {"locale_accent_sensitive", SQLITE_UTF8, localeCollationAccentSensitive8},
107 {"locale_case_accent_sensitive", SQLITE_UTF8,
108 localeCollationCaseAccentSensitive8},
109 {"locale", SQLITE_UTF16, localeCollation16},
110 {"locale_case_sensitive", SQLITE_UTF16, localeCollationCaseSensitive16},
111 {"locale_accent_sensitive", SQLITE_UTF16,
112 localeCollationAccentSensitive16},
113 {"locale_case_accent_sensitive", SQLITE_UTF16,
114 localeCollationCaseAccentSensitive16},
117 int rv = SQLITE_OK;
118 for (size_t i = 0; SQLITE_OK == rv && i < ArrayLength(collations); ++i) {
119 struct Collations* p = &collations[i];
120 rv = ::sqlite3_create_collation(aDB, p->zName, p->enc, aService,
121 p->xCompare);
124 return rv;
127 ////////////////////////////////////////////////////////////////////////////////
128 //// SQL Collations
130 int localeCollation8(void* aService, int aLen1, const void* aStr1, int aLen2,
131 const void* aStr2) {
132 return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
133 Collator::Sensitivity::Base);
136 int localeCollationCaseSensitive8(void* aService, int aLen1, const void* aStr1,
137 int aLen2, const void* aStr2) {
138 return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
139 Collator::Sensitivity::Case);
142 int localeCollationAccentSensitive8(void* aService, int aLen1,
143 const void* aStr1, int aLen2,
144 const void* aStr2) {
145 return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
146 Collator::Sensitivity::Accent);
149 int localeCollationCaseAccentSensitive8(void* aService, int aLen1,
150 const void* aStr1, int aLen2,
151 const void* aStr2) {
152 return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
153 Collator::Sensitivity::Variant);
156 int localeCollation16(void* aService, int aLen1, const void* aStr1, int aLen2,
157 const void* aStr2) {
158 return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
159 Collator::Sensitivity::Base);
162 int localeCollationCaseSensitive16(void* aService, int aLen1, const void* aStr1,
163 int aLen2, const void* aStr2) {
164 return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
165 Collator::Sensitivity::Case);
168 int localeCollationAccentSensitive16(void* aService, int aLen1,
169 const void* aStr1, int aLen2,
170 const void* aStr2) {
171 return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
172 Collator::Sensitivity::Accent);
175 int localeCollationCaseAccentSensitive16(void* aService, int aLen1,
176 const void* aStr1, int aLen2,
177 const void* aStr2) {
178 return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
179 Collator::Sensitivity::Variant);
182 } // namespace storage
183 } // namespace mozilla