Open Bug 1797860 Opened 2 years ago Updated 2 months ago

Assertion failure: IsLink() (EndOffset is called on not hyper link!), at Accessible.cpp:149

Categories

(Core :: Disability Access APIs, defect)

Unspecified
macOS
defect

Tracking

()

People

(Reporter: mcomella, Unassigned)

Details

Steps to reproduce

  • On mac... (CTW is enabled but I'm not sure if it matters)
  • Start Nightly
  • Select all of the text in the url bar (e.g. click and cmd+A)
  • Turn on Voiceover (for me, cmd+F5)

Expected

No crash

Actual

Crash sometimes. It's an assertion failure in Accessible::EndOffset:

MOZ_ASSERT(IsLink(), "EndOffset is called on not hyper link!");

Here's the backtrace from lldb:

* thread #1, name = 'MainThread', queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    frame #0: 0x0000000155964916 XUL`mozilla::a11y::Accessible::EndOffset(this=0x00000001194e6500) at Accessible.cpp:149:3
    frame #1: 0x00000001558ac30a XUL`mozilla::a11y::GeckoTextMarker::operator<(mozilla::a11y::GeckoTextMarker const&) const(this=0x00007ff7bfefa0c8, aPoint=0x00007ff7bfefa058) at GeckoTextMarker.mm:169:33
  * frame #2: 0x00000001558b1532 XUL`mozilla::a11y::GeckoTextMarkerRange::Crop(this=0x00007ff7bfefa0b8, aContainer=0x00000001225fc420) at GeckoTextMarker.mm:570:12
    frame #3: 0x00000001558db9a8 XUL`-[mozTextAccessible selection](self=0x00000001d405dbc0, _cmd="selection") at mozTextAccessible.mm:357:42
    frame #4: 0x00000001558d9db2 XUL`-[mozTextAccessible moxSelectedTextRange](self=0x00000001d405dbc0, _cmd="moxSelectedTextRange") at mozTextAccessible.mm:153:36
    frame #5: 0x00000001558b408b XUL`-[MOXAccessibleBase accessibilityAttributeValue:](self=0x00000001d405dbc0, _cmd="accessibilityAttributeValue:", attribute="AXSelectedTextRange") at MOXAccessibleBase.mm:140:15
    frame #6: 0x00007ff807e752bc AppKit`NSAccessibilityGetObjectForAttributeUsingLegacyAPI + 337
    frame #7: 0x00007ff8083e466b AppKit`___NSAccessibilityEntryPointValueForAttribute_block_invoke.818 + 2600
    frame #8: 0x00007ff8083dfcdc AppKit`NSAccessibilityPerformEntryPointObject + 16
    frame #9: 0x00007ff8080aef1f AppKit`_NSAccessibilityEntryPointValueForAttribute + 168
    frame #10: 0x00007ff8081d563e AppKit`-[NSObject(NSAccessibilityInternal) _accessibilityValueForAttribute:clientError:] + 354
    frame #11: 0x00007ff8081daa76 AppKit`CopyAppKitUIElementAttributeValueNoCatch + 98
    frame #12: 0x00007ff8081d7bc9 AppKit`CopyAttributeValue + 125
    frame #13: 0x00007ff80ae36815 HIServices`_AXXMIGCopyAttributeValue + 633
    frame #14: 0x00007ff80ae59015 HIServices`_XCopyAttributeValue + 441
    frame #15: 0x00007ff80ae17729 HIServices`mshMIGPerform + 182
    frame #16: 0x00007ff8053a0954 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
    frame #17: 0x00007ff8053a0834 CoreFoundation`__CFRunLoopDoSource1 + 619
    frame #18: 0x00007ff80539ee9b CoreFoundation`__CFRunLoopRun + 2415
    frame #19: 0x00007ff80539de6c CoreFoundation`CFRunLoopRunSpecific + 562
    frame #20: 0x00007ff80e04c5e6 HIToolbox`RunCurrentEventLoopInMode + 292
    frame #21: 0x00007ff80e04c34a HIToolbox`ReceiveNextEventCommon + 594
    frame #22: 0x00007ff80e04c0e5 HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter + 70
    frame #23: 0x00007ff807dd7fad AppKit`_DPSNextEvent + 927
    frame #24: 0x00007ff807dd666a AppKit`-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1394
    frame #25: 0x0000000151977c95 XUL`-[GeckoNSApplication nextEventMatchingMask:untilDate:inMode:dequeue:](self=0x0000000100b66940, _cmd="nextEventMatchingMask:untilDate:inMode:dequeue:", mask=18446744073709551615, expiration=4001-01-01 00:00:00 UTC, mode="kCFRunLoopDefaultMode", flag=YES) at nsAppShell.mm:175:24
    frame #26: 0x00007ff807dc8d19 AppKit`-[NSApplication run] + 586
    frame #27: 0x000000015197a0ae XUL`nsAppShell::Run(this=0x000000010d8fd3a0) at nsAppShell.mm:801:5
    frame #28: 0x0000000156351965 XUL`nsAppStartup::Run(this=0x000000010ed256a0) at nsAppStartup.cpp:295:30
    frame #29: 0x00000001565a02ca XUL`XREMain::XRE_mainRun(this=0x00007ff7bfefeb88) at nsAppRunner.cpp:5723:22
    frame #30: 0x00000001565a1480 XUL`XREMain::XRE_main(this=0x00007ff7bfefeb88, argc=5, argv=0x00007ff7bfeff2c8, aConfig=0x00007ff7bfefecf8) at nsAppRunner.cpp:5916:8
    frame #31: 0x00000001565a1a69 XUL`XRE_main(argc=5, argv=0x00007ff7bfeff2c8, aConfig=0x00007ff7bfefecf8) at nsAppRunner.cpp:5972:21
    frame #32: 0x00000001565c0ba7 XUL`mozilla::BootstrapImpl::XRE_main(this=0x0000000100b03110, argc=5, argv=0x00007ff7bfeff2c8, aConfig=0x00007ff7bfefecf8) at Bootstrap.cpp:45:12
    frame #33: 0x0000000100001146 firefox`do_main(argc=5, argv=0x00007ff7bfeff2c8, envp=0x00007ff7bfeff2f8) at nsBrowserApp.cpp:226:22
    frame #34: 0x0000000100000a18 firefox`main(argc=5, argv=0x00007ff7bfeff2c8, envp=0x00007ff7bfeff2f8) at nsBrowserApp.cpp:428:16
    frame #35: 0x000000010004052e dyld`start + 462

Analysis & proposed solution

As I understand it, macOS' accessibility services is querying AXSelectedTextRange on a mozTextAccessible. Before returning the currently selected text to accessibility services, the [mozTextAccessible selection] method tries to return only the portion that is inside of the accessible by calling GeckoTextMarkerRange::Crop. Crop calls into GeckoTextMarker::operator< to check the relative positions of the selection and the accessible's text. However, this calls Accessible::EndOffset on the mozTextAccessible's gecko Accessible, which is an HTMLTextFieldAccessible. When EndOffset is called, it throws the assertion because HTMLTextFieldAccessible is not a link.

The StartOffset & EndOffset methods seem unrelated to links: as far as I can tell, if all of the parent's children concatenated their text together, these methods return the offset of this node's first character and last character + 1 respectively inside that concatenated string.

I suspect the solution to this bug is to remove the assertion, or change it to a more appropriate type like IsText(). However, I'm not familiar enough with the code to know if it's safe or expected. The StartOffset method's comment indicates its supposed to work on the "embedded object", backing up this solution though EndOffset contradicts this by specifically mentioning "link".

For extra context, I printed expressions in lldb (from GeckoTextMarker::operator<) to identify the mozTextAccessible's gecko Accessible and its parents:

(lldb) e mContainer
(mozilla::a11y::HTMLTextFieldAccessible *) $47 = 0x00000001194e6500
(lldb) e mContainer->Parent()
(mozilla::a11y::AccessibleWrap *) $48 = 0x00000001225fc420
(lldb) e mContainer->Parent()->Parent()
(mozilla::a11y::XULToolbarAccessible *) $49 = 0x00000001225fbb60
(lldb) e mContainer->Parent()->Parent()->Parent()
(mozilla::a11y::RootAccessibleWrap *) $50 = 0x00000001d1d6ee00
(lldb) e mContainer->Parent()->Parent()->Parent()->Parent()
(mozilla::a11y::ApplicationAccessible *) $51 = 0x000000010dcc30e0

This is on a recent mozilla-central: d1982cee06ca

Severity: -- → S3
Priority: -- → P1
Priority: P1 → --
Component: Disability Access → Disability Access APIs
Product: Firefox → Core
You need to log in before you can comment on or make changes to this bug.