1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

term_bidi_line: fix failure to initialise wcTo.

The bidi algorithm is called on the array term->wcFrom, modifying it
in place. Then the Arabic-shaping algorithm - which can't work in
place because it needs to check the original value of array entries
it's already modified - is called, copying term->wcFrom to term->wcTo
as a side effect. Then the cleanup code expects the final version of
the line to be in wcTo. So if shaping is turned off, we still need to
copy wcFrom into wcTo, even if we don't modify it en route.

Previously, that copy was done under an if statement whose condition
boils down to 'if bidi is enabled but shaping is not'. So if that code
was ever reached with _both_ bidi and shaping turned off, then nothing
at all would copy wcFrom into wcTo, and wcTo would be filled with
nonsense.

Before trust sigils were introduced, that was OK, because the whole
function body was skipped if both bidi and shaping were turned off.
But now trust-sigil handling lives in there too, so we can get into
that code with the previously disallowed combination of flags. If
you're lucky, this means that the assert(opos == term->cols) near the
bottom of the function fails, on the basis that opos is the sum of
nonsense values from wcTo; if you're unlucky I suppose you might
manage to get _plausible_ nonsense through to the screen.

Now fixed, by changing that central if statement into a much more
obvious one: if we're running do_shape, then that can copy wcFrom into
wcTo, and if and only if we're _not_, then we must copy it another
way. (And while I'm here, I've turned that other way from a manual for
loop into memcpy.)
This commit is contained in:
Simon Tatham 2019-03-26 21:05:12 +00:00
parent 399603fd95
commit 117c7857d2

View File

@ -5130,13 +5130,13 @@ static termchar *term_bidi_line(Terminal *term, struct termline *ldata,
if(!term->bidi)
do_bidi(term->wcFrom, nbc);
/* this is saved iff done from inside the shaping */
if(!term->bidi && term->arabicshaping)
for(it=0; it<nbc; it++)
term->wcTo[it] = term->wcFrom[it];
if(!term->arabicshaping)
if(!term->arabicshaping) {
do_shape(term->wcFrom, term->wcTo, nbc);
} else {
/* If we're not calling do_shape, we must copy the
* data into wcTo anyway, unchanged */
memcpy(term->wcTo, term->wcFrom, nbc * sizeof(*term->wcTo));
}
if (term->ltemp_size < ldata->size) {
term->ltemp_size = ldata->size;