sw/source/core/access/accpara.cxx               |    2 -
 winaccessibility/source/UAccCOM/MAccessible.cxx |   28 ++++++++++++++++++------
 2 files changed, 23 insertions(+), 7 deletions(-)

New commits:
commit 56cf4d70bf09b027df31d8f4fbcad4830a88d454
Author:     Michael Stahl <[email protected]>
AuthorDate: Thu Nov 27 20:34:38 2025 +0100
Commit:     Michael Stahl <[email protected]>
CommitDate: Tue Dec 2 17:41:45 2025 +0100

    tdf#167362 sw: fix footnote hang with JAWS
    
    When moving the cursor to a line with a footnote, JAWS tries to retrieve
    the text attributes, gets an E_FAIL, but never gives up trying again.
    
    The problem is that some entirely undocumented magic number is stuffed
    into an uno::Any as `long` but the "CharEscapement" property is actually
    `short` and thus reading the property in
    AccessibleTextAttributeHelper::ConvertUnoToIAccessible2TextAttributes()
    throws and this is caught by CAccTextBase::get_attributes() and E_FAIL
    is returned.
    
    >       vcllo.dll!o3tl::doAccess<short>(const com::sun::star::uno::Any & 
any) Line 284
            
vcllo.dll!AccessibleTextAttributeHelper::ConvertUnoToIAccessible2TextAttributes(const
 com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> & 
rUnoAttributes, IA2AttributeType eAttributeType) Line 271
            
vcllo.dll!AccessibleTextAttributeHelper::GetIAccessible2TextAttributes(com::sun::star::uno::Reference<com::sun::star::accessibility::XAccessibleText>
 xText, IA2AttributeType eAttributeType, long nOffset, long & rStartOffset, 
long & rEndOffset) Line 346
            UAccCOM.dll!CAccTextBase::get_attributes(long offset, long * 
startOffset, long * endOffset, wchar_t * * textAttributes) Line 145
            UAccCOM.dll!CAccText::get_attributes(long offset, long * 
startOffset, long * endOffset, wchar_t * * textAttributes) Line 54
            FSDomNodeSymphony.dll!00007ff93f0fea12()
                ^ JAWS
    
    Change-Id: I6c487f9d2db462b787034df3d5ba2f2822d14746
    (cherry picked from commit 776662481583935ca148930de1e91ea499c53b3a)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194736
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Stephan Bergmann <[email protected]>
    (cherry picked from commit fac7e501d77a009fcd0bb1796a3ce8cee0c5e1f7)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194869
    Tested-by: Michael Stahl <[email protected]>

diff --git a/sw/source/core/access/accpara.cxx 
b/sw/source/core/access/accpara.cxx
index 67578811a996..f6252ac87ce4 100644
--- a/sw/source/core/access/accpara.cxx
+++ b/sw/source/core/access/accpara.cxx
@@ -2008,7 +2008,7 @@ void SwAccessibleParagraph::_correctValues( const 
sal_Int32 nIndex,
         {
             if ( GetPortionData().IsIndexInFootnode(nIndex) )
             {
-                rValue.Value <<= sal_Int32(101);
+                rValue.Value <<= sal_Int16(101);
             }
             continue;
         }
commit aa45dfe5e208efb41e1fdac7c72faf7242f5ac99
Author:     Michael Stahl <[email protected]>
AuthorDate: Thu Nov 27 16:52:12 2025 +0100
Commit:     Michael Stahl <[email protected]>
CommitDate: Tue Dec 2 17:41:42 2025 +0100

    tdf#168897 winaccessibility: fix JAWS crash with CAccTable
    
    stack:
    
            UAccCOM.dll!ATL::CComObjectRootBase::OuterAddRef() Line 2631
            UAccCOM.dll!ATL::CComContainedObject<CAccImage>::AddRef() Line 3719
            AccEventCache.dll!00007ffd2039be28()
            AccEventCache.dll!00007ffd20355677()
            AccEventCache.dll!00007ffd20346d41()
            AccEventCache.dll!00007ffd20347f9a()
            AccEventCache.dll!00007ffd20338ba2()
            AccEventCache.dll!00007ffd20380dd8()
            AccEventCache.dll!00007ffd2037fd7b()
            AccEventCache.dll!00007ffd2037f7ee()
            AccEventCache.dll!00007ffd2037d9e6()
            AccEventCache.dll!00007ffd2037d07f()
                    ^ JAWS
            GlobalHooksDispatcher.dll!00007ffd214daed4()
            GlobalHooksDispatcher.dll!00007ffd214d8d84()
            user32.dll!00007ffd492068ac()
            ntdll.dll!00007ffd4ae71424()
            win32u.dll!NtUserNotifyWinEvent()
            
winaccessibility.dll!AccObjectWinManager::NotifyAccEvent(com::sun::star::accessibility::XAccessible
 * pXAcc, UnoMSAAEvent eEvent) Line 182
                    ^ selfAccObj looks very dead here but that is a red herring!
            
winaccessibility.dll!AccContainerEventListener::FireStateFocusedChange(bool 
enable) Line 351
            
winaccessibility.dll!AccContainerEventListener::SetComponentState(__int64 
state, bool enable) Line 178
            
winaccessibility.dll!AccParagraphEventListener::SetComponentState(__int64 
state, bool enable) Line 123
            
winaccessibility.dll!AccContainerEventListener::HandleStateChangedEvent(com::sun::star::uno::Any
 oldValue, com::sun::star::uno::Any newValue) Line 106
            winaccessibility.dll!AccContainerEventListener::notifyEvent(const 
com::sun::star::accessibility::AccessibleEventObject & aEvent) Line 72
            winaccessibility.dll!AccParagraphEventListener::notifyEvent(const 
com::sun::star::accessibility::AccessibleEventObject & aEvent) Line 77
            comphelper.dll!comphelper::AccessibleEventNotifier::addEvent(const 
unsigned long _nClient, const 
com::sun::star::accessibility::AccessibleEventObject & _rEvent) Line 256
            
swlo.dll!SwAccessibleContext::FireAccessibleEvent(com::sun::star::accessibility::AccessibleEventObject
 & rEvent) Line 457
            swlo.dll!SwAccessibleContext::FireStateChangedEvent(__int64 nState, 
bool bNewState) Line 478
            swlo.dll!SwAccessibleParagraph::InvalidateFocus_() Line 397
            swlo.dll!SwAccessibleContext::InvalidateFocus() Line 1314
            swlo.dll!SwAccessibleMap::InvalidateFocus() Line 2695
            swlo.dll!SwViewShell::InvalidateAccessibleFocus() Line 2597
            swlo.dll!SwEditWin::GetFocus() Line 5569
            vcllo.dll!vcl::Window::CompatGetFocus() Line 3891
            vcllo.dll!vcl::Window::ImplGrabFocus(GetFocusFlags nFlags) Line 385
            vcllo.dll!vcl::Window::GrabFocus() Line 2983
            sfxlo.dll!SfxFrame::GrabFocusOnComponent_Impl() Line 650
    
    The problem is quite simply that CMAccessible::SmartQI() returns a
    pointer that is the result of querying the newly created COM aggregation
    for IID_IUnknown instead of the requested `iid` interface.
    
    Apparently the wrong result happens to work in many cases, but the
    CAccTable actually has 2 interfaces IAccessibleTable and
    IAccessibleTable2, and the COM aggravation for IAccessibleTable2 is the
    one that crashes; in this case the correct pointer is an offset of 8 to
    the start of CAccTable, while in the working cases there is no offset.
    
    So likely the bug was introduced by commits
    3b86569fcba210eb6570fabef7ff8abf6aff91f0 and
    d0e8e6e3cd51736583603e37f0ba2ff7bdf29f5c but only started to crash with
    839dbf9ecf9f8fbec7de983d1a2e16d7de6f868c.
    
    Change-Id: I7c7d295c8032b95fe7f64b8da4dd9bc3212563f9
    (cherry picked from commit 9502a9f76731afa0f5105e6d79b069222677f88d)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194727
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Stephan Bergmann <[email protected]>
    (cherry picked from commit 7dc79ac270e855f58d24b2dedebe06a209a4bc66)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194868
    Tested-by: Michael Stahl <[email protected]>

diff --git a/winaccessibility/source/UAccCOM/MAccessible.cxx 
b/winaccessibility/source/UAccCOM/MAccessible.cxx
index a6454f3c39f8..9d4271f41988 100644
--- a/winaccessibility/source/UAccCOM/MAccessible.cxx
+++ b/winaccessibility/source/UAccCOM/MAccessible.cxx
@@ -2340,15 +2340,31 @@ HRESULT WINAPI CMAccessible::SmartQI(void* /*pv*/, 
REFIID iid, void** ppvObject)
                 assert(hr == S_OK);
                 if(hr == S_OK)
                 {
+                    // does it matter which IID was used to query before it is
+                    // put into the map?  probably not, and currently
+                    // QueryInterface is called after lookup anyway...
                     m_containedObjects.emplace(*rEntry.piid, 
static_cast<IUnknown*>(*ppvObject));
+                    // very nonobvious: this QI only succeeds on an 
IID_IUnknown
+                    // pointer because that one points directly to the
+                    // CComAggObject whereas the other-IID ones point into
+                    // CAcc* objects and end up forward back here to SmartQI
+                    // which firstly doesn't know IID_IUNOXWrapper and secondly
+                    // it would be useless to return a new instance for it, it
+                    // *must* be the same CAcc* instance that was just created.
+                    // Also, it's not possible to get the CAccTable out of the
+                    // CComAggObject because it is private.
+                    // However for the aggregated objects this here is also the
+                    // *only* place where this interface is called; every other
+                    // call is on a non-aggregated object - so it's sufficient
+                    // if it works once right after construction.
                     IUNOXWrapper* wrapper = nullptr;
                     
static_cast<IUnknown*>(*ppvObject)->QueryInterface(IID_IUNOXWrapper, 
reinterpret_cast<void**>(&wrapper));
-                    if(wrapper)
-                    {
-                        wrapper->put_XInterface(
-                                reinterpret_cast<hyper>(m_xAccessible.get()));
-                        wrapper->Release();
-                    }
+                    assert(wrapper); // every map entry implements it currently
+                    wrapper->put_XInterface(
+                            reinterpret_cast<hyper>(m_xAccessible.get()));
+                    wrapper->Release();
+                    // ppvObject is IID_IUnknown - Query for requested target!
+                    static_cast<IUnknown*>(*ppvObject)->QueryInterface(iid, 
ppvObject);
                     return S_OK;
                 }
             }

Reply via email to