Repository: electron/electron
Pull request: fix: -Wunsafe-buffer-usage warning in HasWordCharacters()

#### Description of Change

Part 15 in a [series](https://github.com/electron/electron/pull/43477) to  fix `-Wunsafe-buffer-usage` warnings in Electron `shell/`. This one works around an unchecked-pointer-dereference warning generated inside icu's `U16_NEXT()` macro. It fixes it by replacing the `U16_NEXT()` call with a `base::ReadUnicodeCharacter()` instead -- which we should arguably be using anyway, since we should prefer base API over third-party API.

NB: `base::ReadUnicodeCharacter()` takes still uses pointer-and-length arguments that [spanification](https://groups.google.com/a/chromium.org/g/chromium-dev/c/iEy69ygz-rs) is trying to avoid, so :man_shrugging: we'll probably need a one-liner followup PR to this if/when upstream changes this to take a span arg.

Warnings fixed by this PR:

```
2024-10-04T05:37:07.1280320Z ../../electron/shell/renderer/api/electron_api_spell_check_client.cc:37:5: error: unsafe buffer access [-Werror,-Wunsafe-buffer-usage]
2024-10-04T05:37:07.1281110Z    37 |     U16_NEXT(data, index, length, code);
2024-10-04T05:37:07.1281650Z       |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2024-10-04T05:37:07.1282390Z ../../third_party/icu/source/common/unicode/utf16.h:310:9: note: expanded from macro 'U16_NEXT'
2024-10-04T05:37:07.1282900Z   310 |     (c)=(s)[(i)++]; \
2024-10-04T05:37:07.1283230Z       |         ^~~
2024-10-04T05:37:07.1283920Z ../../electron/shell/renderer/api/electron_api_spell_check_client.cc:37:5: note: See //docs/unsafe_buffers.md for help.
2024-10-04T05:37:07.1284850Z ../../third_party/icu/source/common/unicode/utf16.h:310:9: note: expanded from macro 'U16_NEXT'
2024-10-04T05:37:07.1285530Z   310 |     (c)=(s)[(i)++]; \
2024-10-04T05:37:07.1285810Z       |         ^
2024-10-04T05:37:07.1286700Z ../../electron/shell/renderer/api/electron_api_spell_check_client.cc:37:5: error: unsafe buffer access [-Werror,-Wunsafe-buffer-usage]
2024-10-04T05:37:07.1287610Z    37 |     U16_NEXT(data, index, length, code);
2024-10-04T05:37:07.1287980Z       |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2024-10-04T05:37:07.1288750Z ../../third_party/icu/source/common/unicode/utf16.h:313:47: note: expanded from macro 'U16_NEXT'
2024-10-04T05:37:07.1289460Z   313 |         if((i)!=(length) && U16_IS_TRAIL(__c2=(s)[(i)])) { \
2024-10-04T05:37:07.1290010Z       |                             ~~~~~~~~~~~~~~~~~~^~~~~~~~~
2024-10-04T05:37:07.1290870Z ../../third_party/icu/source/common/unicode/utf16.h:67:28: note: expanded from macro 'U16_IS_TRAIL'
2024-10-04T05:37:07.1291550Z    67 | #define U16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00)
2024-10-04T05:37:07.1292030Z       |                            ^
2024-10-04T05:37:07.1292750Z ../../electron/shell/renderer/api/electron_api_spell_check_client.cc:37:5: note: See //docs/unsafe_buffers.md for help.
2024-10-04T05:37:07.1293830Z ../../third_party/icu/source/common/unicode/utf16.h:313:47: note: expanded from macro 'U16_NEXT'
2024-10-04T05:37:07.1294450Z   313 |         if((i)!=(length) && U16_IS_TRAIL(__c2=(s)[(i)])) { \
2024-10-04T05:37:07.1294970Z       |                                               ^
2024-10-04T05:37:07.1295400Z 2 errors generated.
```

#### Checklist

- [x] PR description included and stakeholders cc'd
- [x] `npm test` passes
- [x] [PR release notes](https://github.com/electron/clerk/blob/main/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/main/README.md#examples).

#### Release Notes

Notes: none.

Changed files:
filename: shell/renderer/api/electron_api_spell_check_client.cc
patch: @@ -15,6 +15,7 @@
 #include "base/containers/contains.h"
 #include "base/logging.h"
 #include "base/numerics/safe_conversions.h"
+#include "base/strings/utf_string_conversion_utils.h"
 #include "base/task/single_thread_task_runner.h"
 #include "components/spellcheck/renderer/spellcheck_worditerator.h"
 #include "shell/common/gin_helper/dictionary.h"
@@ -29,12 +30,9 @@ namespace electron::api {
 
 namespace {
 
-bool HasWordCharacters(const std::u16string& text, int index) {
-  const char16_t* data = text.data();
-  int length = text.length();
-  while (index < length) {
-    uint32_t code = 0;
-    U16_NEXT(data, index, length, code);
+bool HasWordCharacters(const std::u16string& text, size_t index) {
+  base_icu::UChar32 code;
+  while (base::ReadUnicodeCharacter(text.c_str(), text.size(), &index, &code)) {
     UErrorCode error = U_ZERO_ERROR;
     if (uscript_getScript(code, &error) != USCRIPT_COMMON)
       return true;