aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNeil Hodgson <nyamatongwe@gmail.com>2022-02-25 12:10:18 +1100
committerNeil Hodgson <nyamatongwe@gmail.com>2022-02-25 12:10:18 +1100
commit1e4d9bcc43664caf1531817423aa69575a6d0eef (patch)
tree165fba0a44b663d7c539fa5e771e9d0f1d90c833
parent0111b35556b04f7e46ac335874ba6e22b30ad1c4 (diff)
downloadscintilla-mirror-1e4d9bcc43664caf1531817423aa69575a6d0eef.tar.gz
Bug [#2309] Avoid crash for unexpected right-to-left text.
-rw-r--r--doc/ScintillaHistory.html12
-rwxr-xr-xgtk/PlatGTK.cxx52
2 files changed, 53 insertions, 11 deletions
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html
index 7491109a6..b117e90ba 100644
--- a/doc/ScintillaHistory.html
+++ b/doc/ScintillaHistory.html
@@ -573,6 +573,18 @@
</table>
<h2>Releases</h2>
<h3>
+ <a href="https://www.scintilla.org/scintilla522.zip">Release 5.2.2</a>
+ </h3>
+ <ul>
+ <li>
+ Released 24 February 2022.
+ </li>
+ <li>
+ Fix crash with unexpected right-to-left text on GTK.
+ <a href="https://sourceforge.net/p/scintilla/bugs/2309/">Bug #2309</a>.
+ </li>
+ </ul>
+ <h3>
<a href="https://www.scintilla.org/scintilla521.zip">Release 5.2.1</a>
</h3>
<ul>
diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx
index fcd0fb1f7..afccef2b6 100755
--- a/gtk/PlatGTK.cxx
+++ b/gtk/PlatGTK.cxx
@@ -822,6 +822,8 @@ void SurfaceImpl::DrawTextTransparent(PRectangle rc, const Font *font_, XYPOSITI
}
}
+namespace {
+
class ClusterIterator {
UniquePangoLayoutIter iter;
PangoRectangle pos {};
@@ -836,6 +838,7 @@ public:
lenPositions(static_cast<int>(text.length())) {
LayoutSetText(layout, text);
iter.reset(pango_layout_get_iter(layout));
+ curIndex = pango_layout_iter_get_index(iter.get());
pango_layout_iter_get_cluster_extents(iter.get(), nullptr, &pos);
}
@@ -848,12 +851,24 @@ public:
} else {
finished = true;
position = pango_units_to_double(pos.x + pos.width);
- curIndex = lenPositions;
+ curIndex = pango_layout_iter_get_index(iter.get());
}
distance = position - positionStart;
}
};
+// Something has gone wrong so set all the characters as equally spaced.
+void EquallySpaced(PangoLayout *layout, XYPOSITION *positions, size_t lenPositions) {
+ int widthLayout = 0;
+ pango_layout_get_size(layout, &widthLayout, nullptr);
+ const XYPOSITION widthTotal = pango_units_to_double(widthLayout);
+ for (size_t bytePos=0; bytePos<lenPositions; bytePos++) {
+ positions[bytePos] = widthTotal / lenPositions * (bytePos + 1);
+ }
+}
+
+}
+
void SurfaceImpl::MeasureWidths(const Font *font_, std::string_view text, XYPOSITION *positions) {
if (PFont(font_)->fd) {
UniquePangoContext contextMeasure = MeasuringContext();
@@ -863,8 +878,13 @@ void SurfaceImpl::MeasureWidths(const Font *font_, std::string_view text, XYPOSI
pango_layout_set_font_description(layoutMeasure.get(), PFont(font_)->fd.get());
if (et == EncodingType::utf8) {
// Simple and direct as UTF-8 is native Pango encoding
- int i = 0;
ClusterIterator iti(layoutMeasure.get(), text);
+ int i = iti.curIndex;
+ if (i != 0) {
+ // Unexpected start to iteration, could be bidirectional text
+ EquallySpaced(layoutMeasure.get(), positions, text.length());
+ return;
+ }
while (!iti.finished) {
iti.Next();
const int places = iti.curIndex - i;
@@ -889,8 +909,13 @@ void SurfaceImpl::MeasureWidths(const Font *font_, std::string_view text, XYPOSI
// character byte lengths.
Converter convMeasure("UCS-2", CharacterSetID(characterSet), false);
int i = 0;
- int clusterStart = 0;
ClusterIterator iti(layoutMeasure.get(), utfForm);
+ int clusterStart = iti.curIndex;
+ if (clusterStart != 0) {
+ // Unexpected start to iteration, could be bidirectional text
+ EquallySpaced(layoutMeasure.get(), positions, text.length());
+ return;
+ }
while (!iti.finished) {
iti.Next();
const int clusterEnd = iti.curIndex;
@@ -920,22 +945,22 @@ void SurfaceImpl::MeasureWidths(const Font *font_, std::string_view text, XYPOSI
utfForm = UTF8FromLatin1(text);
}
size_t i = 0;
- int clusterStart = 0;
// Each 8-bit input character may take 1 or 2 bytes in UTF-8
// and groups of up to 3 may be represented as ligatures.
ClusterIterator iti(layoutMeasure.get(), utfForm);
+ int clusterStart = iti.curIndex;
+ if (clusterStart != 0) {
+ // Unexpected start to iteration, could be bidirectional text
+ EquallySpaced(layoutMeasure.get(), positions, lenPositions);
+ return;
+ }
while (!iti.finished) {
iti.Next();
const int clusterEnd = iti.curIndex;
const int ligatureLength = g_utf8_strlen(utfForm.c_str() + clusterStart, clusterEnd - clusterStart);
if (rtlCheck && ((clusterEnd <= clusterStart) || (ligatureLength == 0) || (ligatureLength > 3))) {
// Something has gone wrong: exit quickly but pretend all the characters are equally spaced:
- int widthLayout = 0;
- pango_layout_get_size(layoutMeasure.get(), &widthLayout, nullptr);
- const XYPOSITION widthTotal = pango_units_to_double(widthLayout);
- for (size_t bytePos=0; bytePos<lenPositions; bytePos++) {
- positions[bytePos] = widthTotal / lenPositions * (bytePos + 1);
- }
+ EquallySpaced(layoutMeasure.get(), positions, lenPositions);
return;
}
PLATFORM_ASSERT(ligatureLength > 0 && ligatureLength <= 3);
@@ -1029,8 +1054,13 @@ void SurfaceImpl::MeasureWidthsUTF8(const Font *font_, std::string_view text, XY
pango_layout_set_font_description(layoutMeasure.get(), PFont(font_)->fd.get());
// Simple and direct as UTF-8 is native Pango encoding
- int i = 0;
ClusterIterator iti(layoutMeasure.get(), text);
+ int i = iti.curIndex;
+ if (i != 0) {
+ // Unexpected start to iteration, could be bidirectional text
+ EquallySpaced(layoutMeasure.get(), positions, text.length());
+ return;
+ }
while (!iti.finished) {
iti.Next();
const int places = iti.curIndex - i;