terminal/src
James Holderness 55151a4a04
Refactor VT parameter handling (#7799)
This PR introduces a pair of classes for managing VT parameters that
automatically handle range checking and default fallback values, so the
individual operations don't have to do that validation themselves. In
addition to simplifying the code, this fixes a few cases where we were
mishandling missing or extraneous parameters, and adds support for
parameter sequences on commands that couldn't previously handle them.
This PR also sets a limit on the number of parameters allowed, to help
thwart DoS memory consumption attacks.

## References

* The new parameter class also introduces the concept of an
  omitted/default parameter which is not necessarily zero, which is a
  prerequisite for addressing issue #4417.

## Detailed Description of the Pull Request / Additional comments

There are two new classes provide by this PR: a `VTParameter` class,
similar in function to a `std::optional<size_t>`, which holds an
individual parameter (which may be an omitted/default value); and a
`VTParameters` class, similar in function to `gsl:span<VTParameter>`,
which holds a sequence of those parameters.

Where `VTParameter` differs from `std::optional` is with the inclusion
of two cast operators. There is a `size_t` cast that interprets omitted
and zero values as 1 (the expected behaviour for most numeric
parameters). And there is a generic cast, for use with the enum
parameter types, which interprets omitted values as 0 (the expected
behaviour for most selective parameters).

The advantage of `VTParameters` class is that it has an `at` method that
can never fail - out of range values simply return the a default
`VTParameter` instance (this is standard behaviour in VT terminals). It
also has a `size` method that will always return a minimum count of 1,
since an empty parameter list is typically the equivalent of a single
"default" parameter, so this guarantees you'll get at least one value
when iterating over the list with `size()`.

For cases where we just need to call the same dispatch method for every
parameter, there is a helper `for_each` method, which repeatedly calls a
given predicate function with each value in the sequence. It also
collates the returned success values to determine the overall result of
the sequence. As with the `size` method, this will always make at least
one call, so it correctly handles empty sequences.

With those two classes in place, we could get rid of all the parameter
validation and default handling code in the `OutputStateMachineEngine`.
We now just use the `VTParameters::at` method to grab a parameter and
typically pass it straight to the appropriate dispatch method, letting
the cast operators automatically handle the assignment of default
values. Occasionally we might need a `value_or` call to specify a
non-standard default value, but those cases are fairly rare.

In some case the `OutputStateMachineEngine` was also checking whether
parameters values were in range, but for the most part this shouldn't
have been necessary, since that is something the dispatch classes would
already have been doing themselves (in the few cases that they weren't,
I've now updated them to do so).

I've also updated the `InputStateMachineEngine` in a similar way to the
`OutputStateMachineEngine`, getting rid of a few of the parameter
extraction methods, and simplifying other parts of the implementation.
It's not as clean a replacement as the output engine, but there are
still benefits in using the new classes.

## Validation Steps Performed

For the most part I haven't had to alter existing tests other than
accounting for changes to the API. There were a couple of tests I needed
to drop because they were checking for failure cases which shouldn't
have been failing (unexpected parameters should never be an error), or
testing output engine validation that is no longer handled at that
level.

I've added a few new tests to cover operations that take sequences of
selective parameters (`ED`, `EL`, `TBC`, `SM`, and `RM`). And I've
extended the cursor movement tests to make sure those operations can
handle extraneous parameters that weren't expected. I've also added a
test to verify that the state machine will correctly ignore parameters
beyond the maximum 32 parameter count limit.

I've also manual confirmed that the various test cases given in issues
#2101 are now working as expected.

Closes #2101
2020-10-15 16:12:52 +00:00
..
buffer Properly handle and test a11y movement at end of buffer (#7792) 2020-10-05 15:11:47 -07:00
cascadia Refactor VT parameter handling (#7799) 2020-10-15 16:12:52 +00:00
dep Move all wildcards into targets or expand them (#6406) 2020-06-08 14:01:47 -07:00
host Refactor VT parameter handling (#7799) 2020-10-15 16:12:52 +00:00
inc Add support for more OSC color formats (#7578) 2020-10-14 17:29:10 -07:00
interactivity Fix UIA ScrollIntoView at EndExclusive (#7868) 2020-10-09 20:27:13 +00:00
internal Merged PR 4271163: [Git2Git] Remove use of private theme APIs 2020-02-03 23:13:31 +00:00
propsheet Merged PR 5131018: [Git2Git] Migrate OS changes to console property sheet manifest 2020-09-03 21:38:04 +00:00
propslib Find icon from shortcut target if shortcut doesn't specify it (#6277) 2020-06-01 17:19:05 +00:00
renderer wpf: Add AutoFill to control whether the connection/buffer resizes (#7853) 2020-10-09 22:25:18 +00:00
server Replace basic_string_view<T> with span<const T> (#6921) 2020-07-15 16:40:42 +00:00
terminal Refactor VT parameter handling (#7799) 2020-10-15 16:12:52 +00:00
testlist inbox: Merge accumulated build fixes from RS_ONECORE_DEP_ACIOSS (#1002) 2019-05-24 12:28:30 -07:00
til Introduce TerminalSettingsModel project (#7667) 2020-10-06 09:56:59 -07:00
tools Render the SGR "underlined" attribute in the style of the font (#7148) 2020-08-03 12:49:25 +00:00
tsf Replace basic_string_view<T> with span<const T> (#6921) 2020-07-15 16:40:42 +00:00
types Add support for more OSC color formats (#7578) 2020-10-14 17:29:10 -07:00
winconpty Add support for win32-input-mode to conhost, ConPTY, Terminal (#6309) 2020-06-08 22:31:28 +00:00
common.build.post.props Disable parallel build (again) and keep TerminalApp PCHs (#7322) 2020-08-18 00:01:50 +00:00
common.build.pre.props Enable Control Flow Guard in the common build props (#5453) 2020-04-22 11:30:13 -07:00
common.build.tests.props Update TAEF to 10.57.200731005-develop (#7164) 2020-08-03 20:47:02 +00:00
ConsolePerf.regions.xml Tab to spaces (#578) 2019-05-13 18:06:36 -07:00
ConsolePerf.wprp Fix the WPR profile (#4007) 2019-12-17 17:14:15 -08:00
cppwinrt.build.post.props deps: upgrade CppWinRT to 2.0.200316.3, gsl to v2.1.0 (#4536) 2020-03-23 17:15:24 +00:00
cppwinrt.build.pre.props Move ICore/ControlSettings to TerminalControl project (#7167) 2020-08-07 14:46:52 +00:00
dirs build: move oss required to build conhost out of dep/ (#5451) 2020-04-21 14:43:09 -07:00
project.inc Merged PR 4963673: OS-side build fixes for 09471c375 (gsl-3.1.0 update) 2020-07-30 22:48:48 +00:00
project.unittest.inc Merged PR 4915530: Reflect OS Build fixes on top of 58f5d7c7 2020-07-13 23:00:53 +00:00
StaticAnalysis.ruleset Combined changes to make the build work again (see inside) (#2945) 2019-09-30 10:39:55 -07:00
unit.tests.x64.runsettings Initial release of the Windows Terminal source code 2019-05-02 15:29:04 -07:00
unit.tests.x86.runsettings Initial release of the Windows Terminal source code 2019-05-02 15:29:04 -07:00
wap-common.build.post.props Initial release of the Windows Terminal source code 2019-05-02 15:29:04 -07:00
wap-common.build.pre.props Initial release of the Windows Terminal source code 2019-05-02 15:29:04 -07:00