include/vcl/outdev.hxx                                      |    6 ++--
 sc/source/ui/view/output2.cxx                               |    2 -
 sw/qa/uitest/data/date_picker.docx                          |binary
 sw/qa/uitest/writer_tests5/DateFormFieldPropertiesDialog.py |   15 ++++++++++++
 toolkit/source/awt/vclxgraphics.cxx                         |    2 -
 vcl/inc/calendar.hxx                                        |    2 -
 vcl/source/control/calendar.cxx                             |    7 ++++-
 7 files changed, 26 insertions(+), 8 deletions(-)

New commits:
commit 2d7db6981e5087507c02bde6c0841c388cfaad0f
Author:     Hossein <hoss...@libreoffice.org>
AuthorDate: Sun Nov 13 00:57:22 2022 +0100
Commit:     خالد حسني <kha...@aliftype.com>
CommitDate: Mon Nov 14 12:08:08 2022 +0100

    tdf#152012 Fix assert fail on opening date picker
    
    This patch fixes tdf#152012 which caused an assertion failure on opening
    date picker field in a DOCX file
    
    The assertion was:
    
    include/o3tl/span.hxx:83: constexpr o3tl::span<T>::value_type& o3tl::
    span<T>::operator[](o3tl::span<T>::size_type) const [with T = const
    int; o3tl::span<T>::reference = const int&; o3tl::span<T>::size_type
    = long unsigned int]: Assertion `pos < size()' failed.
    
    And the backtrace was:
    
    1  __pthread_kill_implementation           pthread_kill.c:44
    2  __pthread_kill_internal                 pthread_kill.c:78
    3  __GI___pthread_kill                     pthread_kill.c:89
    4  __GI_raise                              raise.c:26
    5  __GI_abort                              abort.c:79
    6  __assert_fail_base                      assert.c:92
    7  __GI___assert_fail                      assert.c:101
    8  o3tl::span<int const>::operator[]       span.hxx:83
    9  OutputDevice::ImplLayout                text.cxx:1396
    10 OutputDevice::DrawTextArray             text.cxx:948
    11 Calendar::ImplDraw                      calendar.cxx:71
    12 Calendar::Paint                         calendar.cxx:1133
    
    The problem was caused by an out of bound access to a vector of integers
    which was created for rendering calendar header consisting of the first
    letters of 7 days of week, when you clicked on the down arrow on the
    date field.
    
    The function OutputDevice::DrawTextArray() takes an 'rStr' string to
    draw, and 'pDXAry' array for the exact position of the the individual
    characters. It also takes 'nIndex' as the first index, and 'nLen' as the
    length of the array. 'nLen' has the default value of -1. In this case,
    the length is calculated from the size of the string passed to the
    function. This works well if the one who uses the function makes sure
    that the size of the array and the length of string are equal.
    
    Previously, for the 7 days of the week, a 7 letter string "smtwtfs"
    (depending on the week start day this can be different, but length is
    always 7) was sent to this method without providing the length, thus
    the string length: 7 was used. In this case, positions of the letters
    were calculated and used from other array named mnDayOfWeekAry[7].
    mnDayOfWeekAry[k+1] was used as the position of letter k (k=0..5).
    In this case, there was 7 letters for 7 days, and only 6 positions
    provided by the array. This caused assertion failure in span.hxx:83
    when trying to accesss mnDayOfWeekAry[7] via o3tl::span<T>::operator[].
    
    Value of mnDayOfWeekAry[0] was used in other calculations, therefore to
    fix this problem, mnDayOfWeekAry was extended from 7 to 8, and the last
    position was set to the end of drawing rectangle.
    
    The other thing that is done in this patch to avoid this problem in the
    future is removing the default value from the function prototype, so
    that the use should always be done by providing the length of array and
    starting index. After removing these defaults, it became necessary to
    provide empty arrays for 'pKashidaAry' which provides the kashida
    positions, if needed.
    
    With this fix in place, the assertion failure no longer happens.
    
    A UI test is added to make sure the crash will not happen again. The
    test can be run by invoking:
    
     cd sw && make -srj1 UITest_writer_tests5 \
      
UITEST_TEST_NAME="DateFormFieldPropertiesDialog.dateFormFieldDialog.test_date_picker_drop_down"
 \
      SAL_USE_VCLPLUGIN=gen
    
    Change-Id: I347afb358fbc4956524f7f0a0abc3a221bf42992
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142642
    Tested-by: Jenkins
    Reviewed-by: خالد حسني <kha...@aliftype.com>

diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index b1b47d60c1a0..14c1675e7eed 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -1038,9 +1038,9 @@ public:
 
     void                        DrawTextArray( const Point& rStartPt, const 
OUString& rStr,
                                                o3tl::span<const sal_Int32> 
pDXAry,
-                                               o3tl::span<const sal_Bool> 
pKashidaAry={},
-                                               sal_Int32 nIndex = 0,
-                                               sal_Int32 nLen = -1,
+                                               o3tl::span<const sal_Bool> 
pKashidaAry,
+                                               sal_Int32 nIndex,
+                                               sal_Int32 nLen,
                                                SalLayoutFlags flags = 
SalLayoutFlags::NONE,
                                                const SalLayoutGlyphs* 
pLayoutCache = nullptr);
     tools::Long                        GetTextArray( const OUString& rStr, 
std::vector<sal_Int32>* pDXAry,
diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx
index 07f9f750ffe0..28d448fc69b9 100644
--- a/sc/source/ui/view/output2.cxx
+++ b/sc/source/ui/view/output2.cxx
@@ -2111,7 +2111,7 @@ tools::Rectangle ScOutputData::LayoutStrings(bool 
bPixelToLogic, bool bPaint, co
                                 }
 
                                 if (bPaint)
-                                    mpDev->DrawTextArray(aDrawTextPos, aShort, 
aDX);
+                                    mpDev->DrawTextArray(aDrawTextPos, aShort, 
aDX, {}, 0, nLen);
                             }
                             else
                             {
diff --git a/sw/qa/uitest/data/date_picker.docx 
b/sw/qa/uitest/data/date_picker.docx
new file mode 100644
index 000000000000..3100c8db6920
Binary files /dev/null and b/sw/qa/uitest/data/date_picker.docx differ
diff --git a/sw/qa/uitest/writer_tests5/DateFormFieldPropertiesDialog.py 
b/sw/qa/uitest/writer_tests5/DateFormFieldPropertiesDialog.py
index 7eaa7b255247..eb43912782bc 100644
--- a/sw/qa/uitest/writer_tests5/DateFormFieldPropertiesDialog.py
+++ b/sw/qa/uitest/writer_tests5/DateFormFieldPropertiesDialog.py
@@ -8,6 +8,7 @@
 #
 from uitest.framework import UITestCase
 from uitest.uihelper.common import get_state_as_dict, get_url_for_data_file
+from libreoffice.uno.propertyvalue import mkPropertyValues
 
 class dateFormFieldDialog(UITestCase):
 
@@ -125,4 +126,18 @@ class dateFormFieldDialog(UITestCase):
             # a placeholder text is not changed by format change
             self.assertEqual(writer_doc.getText().getString(), "Jul 17, 2019")
 
+    def test_date_picker_drop_down(self):
+        with self.ui_test.load_file(get_url_for_data_file("date_picker.docx")) 
as writer_doc:
+            xWriterDoc = self.xUITest.getTopFocusWindow()
+            xWriterEdit = xWriterDoc.getChild("writer_edit")
+
+            xWriterEdit.executeAction("TYPE", mkPropertyValues({"KEYCODE": 
"RIGHT"}))
+            xWriterEdit.executeAction("TYPE", mkPropertyValues({"KEYCODE": 
"RIGHT"}))
+
+            # open the dialog (cursor is at the field)
+            xWriterEdit.executeAction("TYPE", mkPropertyValues({"KEYCODE": 
"ALT+DOWN"}))
+            xWriterEdit.executeAction("TYPE", mkPropertyValues({"KEYCODE": 
"ESC"}))
+            xWriterEdit.executeAction("TYPE", mkPropertyValues({"KEYCODE": 
"UP"}))
+            self.assertEqual(writer_doc.getText().getString(), "\nClick to 
choose a date")
+
 # vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/toolkit/source/awt/vclxgraphics.cxx 
b/toolkit/source/awt/vclxgraphics.cxx
index a8409a5cf7da..673c44eb09f2 100644
--- a/toolkit/source/awt/vclxgraphics.cxx
+++ b/toolkit/source/awt/vclxgraphics.cxx
@@ -468,7 +468,7 @@ void VCLXGraphics::drawTextArray( sal_Int32 x, sal_Int32 y, 
const OUString& rTex
         {
             aDXA[i] = rLongs[i];
         }
-        mpOutputDevice->DrawTextArray( Point( x, y ), rText, aDXA );
+        mpOutputDevice->DrawTextArray( Point( x, y ), rText, aDXA , {}, 0, 
rText.getLength());
     }
 }
 
diff --git a/vcl/inc/calendar.hxx b/vcl/inc/calendar.hxx
index 500b97f47cd1..a40f1ffdf323 100644
--- a/vcl/inc/calendar.hxx
+++ b/vcl/inc/calendar.hxx
@@ -126,7 +126,7 @@ class Calendar final : public Control
     tools::Rectangle       maPrevRect;
     tools::Rectangle       maNextRect;
     OUString        maDayOfWeekText;
-    sal_Int32       mnDayOfWeekAry[7];
+    sal_Int32       mnDayOfWeekAry[8];
     Date            maOldFormatFirstDate;
     Date            maOldFormatLastDate;
     Date            maFirstDate;
diff --git a/vcl/source/control/calendar.cxx b/vcl/source/control/calendar.cxx
index 0227db0c3e79..3995aa142bae 100644
--- a/vcl/source/control/calendar.cxx
+++ b/vcl/source/control/calendar.cxx
@@ -260,6 +260,9 @@ void Calendar::ImplFormat()
             nDay %= 7;
         }
 
+        // header position for the last day of week
+        mnDayOfWeekAry[7] = mnMonthWidth;
+
         mbCalc = false;
     }
 
@@ -705,9 +708,9 @@ void Calendar::ImplDraw(vcl::RenderContext& rRenderContext)
             Point aStartPos(nDayX, nDeltaY);
             rRenderContext.DrawLine(aStartPos, Point(nDayX + (7 * mnDayWidth), 
nDeltaY));
             std::vector<sal_Int32> aTmp;
-            for (int k=0; k<6; ++k)
+            for (int k=0; k<7; ++k)
                 aTmp.push_back(mnDayOfWeekAry[k+1]);
-            rRenderContext.DrawTextArray(Point(nDayX + mnDayOfWeekAry[0], 
nDayY), maDayOfWeekText, aTmp);
+            rRenderContext.DrawTextArray(Point(nDayX + mnDayOfWeekAry[0], 
nDayY), maDayOfWeekText, aTmp, {}, 0, aTmp.size());
 
             // display days
             sal_uInt16 nDaysInMonth = aDate.GetDaysInMonth();

Reply via email to