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();