Default all G-sets to ASCII unless ISO-2022 is requested (#11658)

## Summary of the Pull Request

There is a non-zero subset of applications that randomly output _Locking Shift_ escape sequences which will invoke a character set from G2 or G3 into the left half of the code table. If those G-sets are mapped to Latin1, that can result in the terminal producing output that appears to be broken. This PR now defaults all G-sets to ASCII, to prevent an unintentional _Locking Shift_ from having any effect.

## PR Checklist
* [x] Closes #10408
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number where discussion took place: #10408

## Detailed Description of the Pull Request / Additional comments

Most other modern terminals also default to ASCII in all G-sets, so this shouldn't break any modern applications. Legacy 8-bit applications may still expect the G2 and G3 sets mapped to Latin1, but they would also need to have the ISO-2022 encoding enabled, so we can keep them happy by setting G2 and G3 correctly when the ISO-2022 encoding is requested.

## Validation Steps Performed

I've manually confirmed that `echo -e "\en"` and `echo -e "\eo"` no longer have any visible effect on the output (at least without first invoking another character set into G2 or G3). I've also confirmed that they do still work as expected (i.e. selecting Latin1) after enabling the ISO-2022 encoding.
This commit is contained in:
James Holderness 2021-11-03 00:48:05 +00:00 committed by GitHub
parent 3667678df1
commit 27e042b784
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 15 additions and 3 deletions

View File

@ -10,10 +10,16 @@ using namespace Microsoft::Console::VirtualTerminal;
TerminalOutput::TerminalOutput() noexcept
{
// By default we set all of the G-sets to ASCII, so if someone accidentally
// triggers a locking shift, they won't end up with Latin1 in the GL table,
// making their system unreadable. If ISO-2022 encoding is selected, though,
// we'll reset the G2 and G3 tables to Latin1, so that 8-bit apps will get a
// more meaningful character mapping by default. This is triggered by a DOCS
// sequence, which will call the EnableGrTranslation method below.
_gsetTranslationTables.at(0) = Ascii;
_gsetTranslationTables.at(1) = Ascii;
_gsetTranslationTables.at(2) = Latin1;
_gsetTranslationTables.at(3) = Latin1;
_gsetTranslationTables.at(2) = Ascii;
_gsetTranslationTables.at(3) = Ascii;
}
bool TerminalOutput::Designate94Charset(size_t gsetNumber, const VTID charset)
@ -91,7 +97,13 @@ bool TerminalOutput::NeedToTranslate() const noexcept
void TerminalOutput::EnableGrTranslation(boolean enabled)
{
_grTranslationEnabled = enabled;
// We need to reapply the right locking shift to (de)activate the translation table.
// The default table for G2 and G3 is Latin1 when GR translation is enabled,
// and ASCII when disabled. The reason for this is explained in the constructor.
const auto defaultTranslationTable = enabled ? std::wstring_view{ Latin1 } : std::wstring_view{ Ascii };
_gsetTranslationTables.at(2) = defaultTranslationTable;
_gsetTranslationTables.at(3) = defaultTranslationTable;
// We need to reapply the locking shifts in case the underlying G-sets have changed.
LockingShift(_glSetNumber);
LockingShiftRight(_grSetNumber);
}