vcl/osx/a11yfocustracker.cxx      |   30 +++++++++++++++++-------
 vcl/osx/a11yrolehelper.mm         |   26 ++++++++++++++-------
 vcl/osx/a11ywrapper.mm            |   47 ++++++++++++++++++++++++--------------
 vcl/osx/documentfocuslistener.cxx |   44 +++++++++++++++++++++++++----------
 4 files changed, 101 insertions(+), 46 deletions(-)

New commits:
commit b1dd43d64d41ebed8b8b92c9b32ea1e47dbdfa65
Author:     Patrick Luby <plub...@neooffice.org>
AuthorDate: Thu Jun 15 17:10:17 2023 -0400
Commit:     Patrick Luby <plub...@neooffice.org>
CommitDate: Tue Jun 20 20:00:56 2023 +0200

    tdf#146626 catch IndexOutOfBoundsException when fetching accessible children
    
    com::sun::star::accessibility::XAccessibleContext::getAccessibleChild()
    can throw an IndexOutOfBoundsException exception even when fetching with
    an index that is positive and less than the value returned by a call to
    the accessible context's getAccessibleChildCount() method so put every
    getAccessibleChild() call in a try/catch block.
    
    Note: this is actually expected behavior even though it is rare. For
    example, accessibility::AccessibleTextHelper_Impl::getAccessibleChild()
    uses the following code snippet to throw such an exception:
    
        if( 0 > i || i >= getAccessibleChildCount() ||
            GetTextForwarder().GetParagraphCount() <= i )
    
    In the case of tdf#146626, getAccessibleChildCount() returns 22 but
    getAccessibleChild(1) throws such an exception due to the last
    condition in the above code snippet.
    
    Change-Id: If974afb7b9178faa99b91dcd79eb5f169bbfe13e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153160
    Tested-by: Jenkins
    Reviewed-by: Patrick Luby <plub...@neooffice.org>
    (cherry picked from commit 060a6aa4396592ab89b7239bec07b5055c7cde1c)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153148

diff --git a/vcl/osx/a11yfocustracker.cxx b/vcl/osx/a11yfocustracker.cxx
index 8d830cdb62a1..2aaa8b0a8e25 100644
--- a/vcl/osx/a11yfocustracker.cxx
+++ b/vcl/osx/a11yfocustracker.cxx
@@ -30,8 +30,10 @@
 #include <com/sun/star/accessibility/XAccessibleSelection.hpp>
 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
 #include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
 
 using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::lang;
 using namespace ::com::sun::star::uno;
 
 AquaA11yFocusTracker& TheAquaA11yFocusTracker()
@@ -118,10 +120,16 @@ void 
AquaA11yFocusTracker::notify_toolbox_item_focus(ToolBox *pToolBox)
 
         if( xContext.is() )
         {
-            ToolBox::ImplToolItems::size_type nPos = pToolBox->GetItemPos( 
pToolBox->GetHighlightItemId() );
-            if( nPos != ToolBox::ITEM_NOTFOUND )
-                setFocusedObject( xContext->getAccessibleChild( nPos ) );
-                    //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+            try {
+                ToolBox::ImplToolItems::size_type nPos = pToolBox->GetItemPos( 
pToolBox->GetHighlightItemId() );
+                if( nPos != ToolBox::ITEM_NOTFOUND )
+                    setFocusedObject( xContext->getAccessibleChild( nPos ) );
+                        //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+            }
+            catch (const IndexOutOfBoundsException&)
+            {
+                SAL_WARN("vcl", "Accessible object has invalid index in 
parent");
+            }
         }
     }
 }
@@ -150,11 +158,17 @@ void 
AquaA11yFocusTracker::toolbox_open_floater(vcl::Window *pWindow)
             return;
         }
         if ( rxContext -> getAccessibleChildCount() > 0 ) {
-            Reference < XAccessible > rxAccessibleChild = rxContext -> 
getAccessibleChild( 0 );
-            if ( ! rxAccessibleChild.is() ) {
-                return;
+            try {
+                Reference < XAccessible > rxAccessibleChild = rxContext -> 
getAccessibleChild( 0 );
+                if ( ! rxAccessibleChild.is() ) {
+                    return;
+                }
+                setFocusedObject ( rxAccessibleChild );
+            }
+            catch (const IndexOutOfBoundsException&)
+            {
+                SAL_WARN("vcl", "No valid accessible objects in parent");
             }
-            setFocusedObject ( rxAccessibleChild );
         }
     }
 }
diff --git a/vcl/osx/a11yrolehelper.mm b/vcl/osx/a11yrolehelper.mm
index 5cb75c94a86f..e95036dbebd9 100644
--- a/vcl/osx/a11yrolehelper.mm
+++ b/vcl/osx/a11yrolehelper.mm
@@ -24,8 +24,12 @@
 
 #include <com/sun/star/accessibility/AccessibleRole.hpp>
 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+#include <sal/log.hxx>
 
 using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::lang;
 using namespace ::com::sun::star::uno;
 
 @implementation AquaA11yRoleHelper
@@ -153,17 +157,23 @@ using namespace ::com::sun::star::uno;
             }
         }
     } else if ( accessibleContext -> getAccessibleRole() == 
AccessibleRole::COMBO_BOX ) {
-        Reference < XAccessible > rxAccessible = accessibleContext -> 
getAccessibleChild(0);
-        if ( rxAccessible.is() ) {
-            Reference < XAccessibleContext > rxAccessibleContext = 
rxAccessible -> getAccessibleContext();
-            if ( rxAccessibleContext.is() && rxAccessibleContext -> 
getAccessibleRole() == AccessibleRole::TEXT ) {
-                sal_Int64 nStateSet = rxAccessibleContext -> 
getAccessibleStateSet();
-                if ( !(nStateSet & AccessibleStateType::EDITABLE ) ) {
-                    [ nativeRole release ];
-                    nativeRole = NSAccessibilityPopUpButtonRole;
+        try {
+            Reference < XAccessible > rxAccessible = accessibleContext -> 
getAccessibleChild(0);
+            if ( rxAccessible.is() ) {
+                Reference < XAccessibleContext > rxAccessibleContext = 
rxAccessible -> getAccessibleContext();
+                if ( rxAccessibleContext.is() && rxAccessibleContext -> 
getAccessibleRole() == AccessibleRole::TEXT ) {
+                    sal_Int64 nStateSet = rxAccessibleContext -> 
getAccessibleStateSet();
+                    if ( !(nStateSet & AccessibleStateType::EDITABLE ) ) {
+                        [ nativeRole release ];
+                        nativeRole = NSAccessibilityPopUpButtonRole;
+                    }
                 }
             }
         }
+        catch (const IndexOutOfBoundsException&)
+        {
+            SAL_WARN("vcl", "No valid accessible objects in parent");
+        }
     }
     return nativeRole;
 }
diff --git a/vcl/osx/a11ywrapper.mm b/vcl/osx/a11ywrapper.mm
index 06967df5aa3e..0ca256a7552f 100644
--- a/vcl/osx/a11ywrapper.mm
+++ b/vcl/osx/a11ywrapper.mm
@@ -45,6 +45,7 @@
 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
 #include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
 
 #include <sal/log.hxx>
 #include <osl/diagnose.h>
@@ -339,19 +340,25 @@ static std::ostream &operator<<(std::ostream &s, NSObject 
*obj) {
             NSMutableArray * children = [ [ NSMutableArray alloc ] init ];
             Reference< XAccessibleContext > xContext( [ self accessibleContext 
] );
 
-            sal_Int64 cnt = xContext -> getAccessibleChildCount();
-            for ( sal_Int64 i = 0; i < cnt; i++ ) {
-                Reference< XAccessible > xChild( xContext -> 
getAccessibleChild( i ) );
-                if( xChild.is() ) {
-                    Reference< XAccessibleContext > xChildContext( xChild -> 
getAccessibleContext() );
-                    // the menubar is already accessible (including Apple- and 
Application-Menu) through NSApplication => omit it here
-                    if ( xChildContext.is() && AccessibleRole::MENU_BAR != 
xChildContext -> getAccessibleRole() ) {
-                        id wrapper = [ AquaA11yFactory 
wrapperForAccessibleContext: xChildContext ];
-                        [ children addObject: wrapper ];
-                        [ wrapper release ];
+            try {
+                sal_Int64 cnt = xContext -> getAccessibleChildCount();
+                for ( sal_Int64 i = 0; i < cnt; i++ ) {
+                    Reference< XAccessible > xChild( xContext -> 
getAccessibleChild( i ) );
+                    if( xChild.is() ) {
+                        Reference< XAccessibleContext > xChildContext( xChild 
-> getAccessibleContext() );
+                        // the menubar is already accessible (including Apple- 
and Application-Menu) through NSApplication => omit it here
+                        if ( xChildContext.is() && AccessibleRole::MENU_BAR != 
xChildContext -> getAccessibleRole() ) {
+                            id wrapper = [ AquaA11yFactory 
wrapperForAccessibleContext: xChildContext ];
+                            [ children addObject: wrapper ];
+                            [ wrapper release ];
+                        }
                     }
                 }
             }
+            catch (const IndexOutOfBoundsException&)
+            {
+                SAL_WARN("vcl", "Accessible object has invalid index in 
parent");
+            }
 
             // if not already acting as RadioGroup now is the time to replace 
RadioButtons with RadioGroups and remove RadioButtons
             if ( ! mActsAsRadioGroup ) {
@@ -1063,16 +1070,22 @@ static Reference < XAccessibleContext > hitTestRunner ( 
css::awt::Point point,
             }
 
             if( bSafeToIterate ) {
-                for ( sal_Int64 i = 0; i < rxAccessibleContext -> 
getAccessibleChildCount(); i++ ) {
-                    Reference < XAccessible > rxAccessibleChild = 
rxAccessibleContext -> getAccessibleChild ( i );
-                    if ( rxAccessibleChild.is() && rxAccessibleChild -> 
getAccessibleContext().is() && rxAccessibleChild -> getAccessibleContext() -> 
getAccessibleRole() != AccessibleRole::LIST ) {
-                        Reference < XAccessibleContext > myHitChild = 
hitTestRunner ( point, rxAccessibleChild -> getAccessibleContext() );
-                        if ( myHitChild.is() ) {
-                            hitChild = myHitChild;
-                            break;
+                try {
+                    for ( sal_Int64 i = 0; i < rxAccessibleContext -> 
getAccessibleChildCount(); i++ ) {
+                        Reference < XAccessible > rxAccessibleChild = 
rxAccessibleContext -> getAccessibleChild ( i );
+                        if ( rxAccessibleChild.is() && rxAccessibleChild -> 
getAccessibleContext().is() && rxAccessibleChild -> getAccessibleContext() -> 
getAccessibleRole() != AccessibleRole::LIST ) {
+                            Reference < XAccessibleContext > myHitChild = 
hitTestRunner ( point, rxAccessibleChild -> getAccessibleContext() );
+                            if ( myHitChild.is() ) {
+                                hitChild = myHitChild;
+                                break;
+                            }
                         }
                     }
                 }
+                catch (const IndexOutOfBoundsException&)
+                {
+                    SAL_WARN("vcl", "Accessible object has invalid index in 
parent");
+                }
             }
         }
     } catch ( RuntimeException ) {
diff --git a/vcl/osx/documentfocuslistener.cxx 
b/vcl/osx/documentfocuslistener.cxx
index 5f39e7cbfdc0..44a3506f860d 100644
--- a/vcl/osx/documentfocuslistener.cxx
+++ b/vcl/osx/documentfocuslistener.cxx
@@ -106,7 +106,13 @@ Reference< XAccessible > 
DocumentFocusListener::getAccessible(const EventObject&
             Reference< XAccessibleContext > xParentContext( 
xParent->getAccessibleContext() );
             if( xParentContext.is() )
             {
-                return xParentContext->getAccessibleChild( 
xContext->getAccessibleIndexInParent() );
+                try {
+                    return xParentContext->getAccessibleChild( 
xContext->getAccessibleIndexInParent() );
+                }
+                catch (const IndexOutOfBoundsException&)
+                {
+                    SAL_WARN("vcl", "Accessible object has invalid index in 
parent");
+                }
             }
         }
     }
@@ -153,13 +159,19 @@ void DocumentFocusListener::attachRecursive(
 
         if( ! (nStateSet & AccessibleStateType::MANAGES_DESCENDANTS) )
         {
-            sal_Int64 n, nmax = xContext->getAccessibleChildCount();
-            for( n = 0; n < nmax; n++ )
+            try {
+                sal_Int64 n, nmax = xContext->getAccessibleChildCount();
+                for( n = 0; n < nmax; n++ )
+                {
+                    Reference< XAccessible > xChild( 
xContext->getAccessibleChild( n ) );
+
+                    if( xChild.is() )
+                        attachRecursive(xChild);
+                }
+            }
+            catch (const IndexOutOfBoundsException&)
             {
-                Reference< XAccessible > xChild( xContext->getAccessibleChild( 
n ) );
-
-                if( xChild.is() )
-                    attachRecursive(xChild);
+                SAL_WARN("vcl", "Accessible object index does not exist in 
parent");
             }
         }
     }
@@ -197,13 +209,19 @@ void DocumentFocusListener::detachRecursive(
 
         if( ! (nStateSet & AccessibleStateType::MANAGES_DESCENDANTS) )
         {
-            sal_Int64 n, nmax = xContext->getAccessibleChildCount();
-            for( n = 0; n < nmax; n++ )
+            try {
+                sal_Int64 n, nmax = xContext->getAccessibleChildCount();
+                for( n = 0; n < nmax; n++ )
+                {
+                    Reference< XAccessible > xChild( 
xContext->getAccessibleChild( n ) );
+
+                    if( xChild.is() )
+                        detachRecursive(xChild);
+                }
+            }
+            catch (const IndexOutOfBoundsException&)
             {
-                Reference< XAccessible > xChild( xContext->getAccessibleChild( 
n ) );
-
-                if( xChild.is() )
-                    detachRecursive(xChild);
+                SAL_WARN("vcl", "Accessible object index does not exist in 
parent");
             }
         }
     }

Reply via email to