Repository: electron/electron (language: cpp)

Issue:
[Bug]: Electron crashes if Narrator is open and <img> without alt= is shown
### Preflight Checklist

- [X] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) for this project.
- [X] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
- [X] I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a bug report that matches the one I want to file, without success.

### Electron Version

18.0.3 (also 18.0.0-beta.1, 19.0.0-alpha.1, 20.0.0-nightly.20220411)

### What operating system are you using?

Windows

### Operating System Version

Windows 11 Pro version 21H2 build 22000.593

### What arch are you using?

x64

### Last Known Working Electron version

17.4.0 (also 18.0.0-alpha.5)

### Expected Behavior

1. Press <kbd>⊞ Win</kbd>+<kbd>Ctrl</kbd>+<kbd>Enter</kbd> to start Windows Narrator.
2. Start [this fiddle](https://gist.github.com/4d0c8b4e45baa84cc152ef7a545dcd98), which just displays `<img src="https://…/icon.png" />`.
3. Electron should not crash.

### Actual Behavior

3. Electron crashes on start.

### Testcase Gist URL

https://gist.github.com/4d0c8b4e45baa84cc152ef7a545dcd98

### Additional Information

I believe this is the crash that was supposed to be fixed by

- #33614

but although that was backported in 18.0.2 (#33616), the crash is evidently not fixed.

Cc @MarshallOfSound.


Discussion / hints:
Here’s the full stack trace, implicating the [`ElectronContentClient::GetLocalizedString(IDS_AX_UNLABELED_IMAGE_ROLE_DESCRIPTION)` call](https://github.com/chromium/chromium/blob/100.0.4896.75/content/browser/accessibility/browser_accessibility.cc#L1950-L1951) in `BrowserAccessibility::GetLocalizedRoleDescriptionForUnlabeledImage`.

```
electron.exe!ui::ResourceBundle::GetLocalizedStringImpl(int resource_id) Line 1162
	at C:\projects\src\ui\base\resource\resource_bundle.cc(1162)
electron.exe!ui::ResourceBundle::GetLocalizedString(int resource_id) Line 771
	at C:\projects\src\ui\base\resource\resource_bundle.cc(771)
electron.exe!l10n_util::GetStringUTF16(int message_id) Line 776
	at C:\projects\src\ui\base\l10n\l10n_util.cc(776)
electron.exe!electron::ElectronContentClient::GetLocalizedString(int message_id) Line 165
	at C:\projects\src\electron\shell\app\electron_content_client.cc(165)
electron.exe!content::BrowserAccessibility::GetLocalizedRoleDescriptionForUnlabeledImage() Line 1952
	at C:\projects\src\content\browser\accessibility\browser_accessibility.cc(1952)
electron.exe!ui::AXPlatformNodeBase::GetRoleDescriptionFromImageAnnotationStatusOrFromAttribute() Line 884
	at C:\projects\src\ui\accessibility\platform\ax_platform_node_base.cc(884)
electron.exe!ui::AXPlatformNodeBase::ComputeAttributes(std::__1::vector<std::__1::basic_string<wchar_t,std::__1::char_traits<wchar_t>,std::__1::allocator<wchar_t>>,std::__1::allocator<std::__1::basic_string<wchar_t,std::__1::char_traits<wchar_t>,std::__1::allocator<wchar_t>>>> * attributes) Line 1177
	at C:\projects\src\ui\accessibility\platform\ax_platform_node_base.cc(1177)
electron.exe!ui::AXPlatformNodeWin::ComputeIA2Attributes() Line 6832
	at C:\projects\src\ui\accessibility\platform\ax_platform_node_win.cc(6832)
electron.exe!content::BrowserAccessibilityComWin::UpdateStep1ComputeWinAttributes() Line 1467
	at C:\projects\src\content\browser\accessibility\browser_accessibility_com_win.cc(1467)
electron.exe!content::BrowserAccessibilityManagerWin::OnAtomicUpdateFinished(ui::AXTree * tree, bool root_changed, const std::__1::vector<ui::AXTreeObserver::Change,std::__1::allocator<ui::AXTreeObserver::Change>> & changes) Line 739
	at C:\projects\src\content\browser\accessibility\browser_accessibility_manager_win.cc(739)
electron.exe!ui::AXTree::Unserialize(const ui::AXTreeUpdate & update) Line 1320
	at C:\projects\src\ui\accessibility\ax_tree.cc(1320)
electron.exe!content::BrowserAccessibilityManager::Unserialize(const ui::AXTreeUpdate & tree_update) Line 225
	at C:\projects\src\content\browser\accessibility\browser_accessibility_manager.cc(225)
electron.exe!content::BrowserAccessibilityManager::OnAccessibilityEvents(const content::AXEventNotificationDetails & details) Line 460
	at C:\projects\src\content\browser\accessibility\browser_accessibility_manager.cc(460)
[Inline Frame] electron.exe!content::RenderFrameHostImpl::SendAccessibilityEventsToManager(const content::AXEventNotificationDetails & details) Line 5863
	at C:\projects\src\content\browser\renderer_host\render_frame_host_impl.cc(5863)
electron.exe!content::RenderFrameHostImpl::HandleAXEvents(const ui::AXTreeID & tree_id, mojo::StructPtr<content::mojom::AXUpdatesAndEvents> updates_and_events, int reset_token) Line 7316
	at C:\projects\src\content\browser\renderer_host\render_frame_host_impl.cc(7316)
[Inline Frame] electron.exe!base::internal::FunctorTraits<void (content::RenderFrameHostImpl::*)(const ui::AXTreeID &, mojo::StructPtr<content::mojom::AXUpdatesAndEvents>, int),void>::Invoke(void(content::RenderFrameHostImpl::*)(const ui::AXTreeID &, mojo::StructPtr<content::mojom::AXUpdatesAndEvents>, int) method, base::WeakPtr<content::RenderFrameHostImpl> && receiver_ptr, ui::AXTreeID && args, mojo::StructPtr<content::mojom::AXUpdatesAndEvents> && args, int && args) Line 542
	at C:\projects\src\base\bind_internal.h(542)
[Inline Frame] electron.exe!base::internal::InvokeHelper<1,void>::MakeItSo(void(content::RenderFrameHostImpl::*)(const ui::AXTreeID &, mojo::StructPtr<content::mojom::AXUpdatesAndEvents>, int) && functor, base::WeakPtr<content::RenderFrameHostImpl> && weak_ptr, ui::AXTreeID && args, mojo::StructPtr<content::mojom::AXUpdatesAndEvents> && args, int && args) Line 726
	at C:\projects\src\base\bind_internal.h(726)
[Inline Frame] electron.exe!base::internal::Invoker<base::internal::BindState<void (content::RenderFrameHostImpl::*)(const ui::AXTreeID &, mojo::StructPtr<content::mojom::AXUpdatesAndEvents>, int),base::WeakPtr<content::RenderFrameHostImpl>,ui::AXTreeID,mojo::StructPtr<content::mojom::AXUpdatesAndEvents>,int>,void ()>::RunImpl(void(content::RenderFrameHostImpl::*)(const ui::AXTreeID &, mojo::StructPtr<content::mojom::AXUpdatesAndEvents>, int) && functor, std::__1::tuple<base::WeakPtr<content::RenderFrameHostImpl>,ui::AXTreeID,mojo::StructPtr<content::mojom::AXUpdatesAndEvents>,int> && bound, std::__1::integer_sequence<unsigned long long,0,1,2,3>) Line 779
	at C:\projects\src\base\bind_internal.h(779)
electron.exe!base::internal::Invoker<base::internal::BindState<void (content::RenderFrameHostImpl::*)(const ui::AXTreeID &, mojo::StructPtr<content::mojom::AXUpdatesAndEvents>, int),base::WeakPtr<content::RenderFrameHostImpl>,ui::AXTreeID,mojo::StructPtr<content::mojom::AXUpdatesAndEvents>,int>,void ()>::RunOnce(base::internal::BindStateBase * base) Line 752
	at C:\projects\src\base\bind_internal.h(752)
[Inline Frame] electron.exe!base::OnceCallback<void ()>::Run() Line 142
	at C:\projects\src\base\callback.h(142)
electron.exe!base::`anonymous namespace'::PostTaskAndReplyRelay::RunTaskAndPostReply(base::`anonymous namespace'::PostTaskAndReplyRelay relay) Line 100
	at C:\projects\src\base\threading\post_task_and_reply_impl.cc(100)
[Inline Frame] electron.exe!base::internal::FunctorTraits<void (*)(base::(anonymous namespace)::PostTaskAndReplyRelay),void>::Invoke(void(*)(base::`anonymous namespace'::PostTaskAndReplyRelay) && function, base::`anonymous namespace'::PostTaskAndReplyRelay && args) Line 437
	at C:\projects\src\base\bind_internal.h(437)
[Inline Frame] electron.exe!base::internal::InvokeHelper<0,void>::MakeItSo(void(*)(base::`anonymous namespace'::PostTaskAndReplyRelay) && functor, base::`anonymous namespace'::PostTaskAndReplyRelay && args) Line 706
	at C:\projects\src\base\bind_internal.h(706)
[Inline Frame] electron.exe!base::internal::Invoker<base::internal::BindState<void (*)(base::(anonymous namespace)::PostTaskAndReplyRelay),base::(anonymous namespace)::PostTaskAndReplyRelay>,void ()>::RunImpl(void(*)(base::`anonymous namespace'::PostTaskAndReplyRelay) && functor, std::__1::tuple<base::(anonymous namespace)::PostTaskAndReplyRelay> && bound, std::__1::integer_sequence<unsigned long long,0>) Line 779
	at C:\projects\src\base\bind_internal.h(779)
electron.exe!base::internal::Invoker<base::internal::BindState<void (*)(base::(anonymous namespace)::PostTaskAndReplyRelay),base::(anonymous namespace)::PostTaskAndReplyRelay>,void ()>::RunOnce(base::internal::BindStateBase * base) Line 748
	at C:\projects\src\base\bind_internal.h(748)
[Inline Frame] electron.exe!base::OnceCallback<void ()>::Run() Line 142
	at C:\projects\src\base\callback.h(142)
electron.exe!base::TaskAnnotator::RunTaskImpl(base::PendingTask & pending_task) Line 135
	at C:\projects\src\base\task\common\task_annotator.cc(135)
[Inline Frame] electron.exe!base::TaskAnnotator::RunTask(perfetto::StaticString event_name, base::PendingTask & pending_task, base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl::<lambda_0> && args) Line 74
	at C:\projects\src\base\task\common\task_annotator.h(74)
[Inline Frame] electron.exe!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl(base::sequence_manager::LazyNow * continuation_lazy_now) Line 385
	at C:\projects\src\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc(385)
electron.exe!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork() Line 290
	at C:\projects\src\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc(290)
electron.exe!base::MessagePumpForUI::DoRunLoop() Line 221
	at C:\projects\src\base\message_loop\message_pump_win.cc(221)
electron.exe!base::MessagePumpWin::Run(base::MessagePump::Delegate * delegate) Line 79
	at C:\projects\src\base\message_loop\message_pump_win.cc(79)
electron.exe!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(bool application_tasks_allowed, base::TimeDelta timeout) Line 500
	at C:\projects\src\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc(500)
electron.exe!base::RunLoop::Run(const base::Location & location) Line 143
	at C:\projects\src\base\run_loop.cc(143)
electron.exe!content::BrowserMainLoop::RunMainMessageLoop() Line 1058
	at C:\projects\src\content\browser\browser_main_loop.cc(1058)
electron.exe!content::BrowserMainRunnerImpl::Run() Line 156
	at C:\projects\src\content\browser\browser_main_runner_impl.cc(156)
electron.exe!content::BrowserMain(content::MainFunctionParams parameters) Line 30
	at C:\projects\src\content\browser\browser_main.cc(30)
electron.exe!content::RunBrowserProcessMain(content::MainFunctionParams main_function_params, content::ContentMainDelegate * delegate) Line 639
	at C:\projects\src\content\app\content_main_runner_impl.cc(639)
electron.exe!content::ContentMainRunnerImpl::RunBrowser(content::MainFunctionParams main_params, bool start_minimal_browser) Line 1172
	at C:\projects\src\content\app\content_main_runner_impl.cc(1172)
electron.exe!content::ContentMainRunnerImpl::Run() Line 1043
	at C:\projects\src\content\app\content_main_runner_impl.cc(1043)
electron.exe!content::RunContentProcess(content::ContentMainParams params, content::ContentMainRunner * content_main_runner) Line 405
	at C:\projects\src\content\app\content_main.cc(405)
electron.exe!content::ContentMain(content::ContentMainParams params) Line 433
	at C:\projects\src\content\app\content_main.cc(433)
electron.exe!wWinMain(HINSTANCE__ * instance, HINSTANCE__ *, wchar_t * cmd, int) Line 238
	at C:\projects\src\electron\shell\app\electron_main_win.cc(238)
[External Code]
```
We are also seeing this crash for our app in production :(. Would it be possible to prioritize fixing this issue @MarshallOfSound? Unfortunately we can't go back to previous version of Electron, since data in IndexedDB would be deleted when fallback to older version. Thank you for your help!
Now that nightly is building again I can confirm that this still crashes 20.0.0-nightly.20220411 (so it’s not just a backport problem).
@ mentioning random maintainers honestly isn't the right way to engage.  We're aware of this issue.
@MarshallOfSound sorry about that - I don't really know how to get attention to this issue since I'm aware that there're a lot of tickets for the Electron team to look at, and this issue is causing a lot of problem with our users. Thanks for your reply and look forward to the fix :)
I looked into this on macOS, apparently both branches in `ResourceBundle::GetLocalizedStringImpl` that check the locale resources pak and secondary locale resources pak both fail, bringing us to the branch that tries to read it from the main data pak (where the string should not be), which also fails and causes the `CHECK` to go off. Therefore the string isn't being found in the locale paks where it should be.

I also confirmed in the generated `.pak.info` plaintext files (100%, 200%, the main one, and also the `en` locale) that the `IDS_AX_UNLABELED_IMAGE_ROLE_DESCRIPTION` does in fact not show up

Fix patch:
diff --git a/electron_paks.gni b/electron_paks.gni
index 2b089fa53b940..73d181d3f018d 100644
--- a/electron_paks.gni
+++ b/electron_paks.gni
@@ -184,6 +184,7 @@ template("electron_paks") {
       "${root_gen_dir}/components/strings/components_strings_",
       "${root_gen_dir}/device/bluetooth/strings/bluetooth_strings_",
       "${root_gen_dir}/services/strings/services_strings_",
+      "${root_gen_dir}/third_party/blink/public/strings/blink_accessibility_strings_",
       "${root_gen_dir}/third_party/blink/public/strings/blink_strings_",
       "${root_gen_dir}/ui/strings/app_locale_settings_",
       "${root_gen_dir}/ui/strings/ax_strings_",
@@ -198,6 +199,7 @@ template("electron_paks") {
       "//device/bluetooth/strings",
       "//services/strings",
       "//third_party/blink/public/strings",
+      "//third_party/blink/public/strings:accessibility_strings",
       "//ui/strings:app_locale_settings",
       "//ui/strings:ax_strings",
       "//ui/strings:ui_strings",


Test patch: