diff --git a/src/terminal/parser/stateMachine.cpp b/src/terminal/parser/stateMachine.cpp index 432d287ce0..79ed50a03f 100644 --- a/src/terminal/parser/stateMachine.cpp +++ b/src/terminal/parser/stateMachine.cpp @@ -450,12 +450,16 @@ void StateMachine::_ActionParam(const wchar_t wch) // multiply existing values by 10 to make space in the 1s digit *_pusActiveParam *= 10; - // mark that we've now stored another digit. - _iParamAccumulatePos++; - // store the digit in the 1s place. *_pusActiveParam += usDigit; + // if the total is zero, it must be a leading zero digit, so we don't count it. + if (*_pusActiveParam != 0) + { + // otherwise mark that we've now stored another digit. + _iParamAccumulatePos++; + } + if (*_pusActiveParam > SHORT_MAX) { *_pusActiveParam = SHORT_MAX; @@ -530,12 +534,16 @@ void StateMachine::_ActionOscParam(const wchar_t wch) // multiply existing values by 10 to make space in the 1s digit _sOscParam *= 10; - // mark that we've now stored another digit. - _iParamAccumulatePos++; - // store the digit in the 1s place. _sOscParam += usDigit; + // if the total is zero, it must be a leading zero digit, so we don't count it. + if (_sOscParam != 0) + { + // otherwise mark that we've now stored another digit. + _iParamAccumulatePos++; + } + if (_sOscParam > SHORT_MAX) { _sOscParam = SHORT_MAX; diff --git a/src/terminal/parser/ut_parser/OutputEngineTest.cpp b/src/terminal/parser/ut_parser/OutputEngineTest.cpp index 15e423fff6..84fed5c355 100644 --- a/src/terminal/parser/ut_parser/OutputEngineTest.cpp +++ b/src/terminal/parser/ut_parser/OutputEngineTest.cpp @@ -273,6 +273,30 @@ class Microsoft::Console::VirtualTerminal::OutputEngineTest final VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::Ground); } + TEST_METHOD(TestLeadingZeroCsiParam) + { + StateMachine mach(new OutputStateMachineEngine(new DummyDispatch)); + + VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::Ground); + mach.ProcessCharacter(AsciiChars::ESC); + VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::Escape); + mach.ProcessCharacter(L'['); + VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::CsiEntry); + for (int i = 0; i < 50; i++) // Any number of leading zeros should be supported + { + mach.ProcessCharacter(L'0'); + VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::CsiParam); + } + for (int i = 0; i < 5; i++) // We're only expecting to be able to keep 5 digits max + { + mach.ProcessCharacter((wchar_t)(L'1' + i)); + VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::CsiParam); + } + VERIFY_ARE_EQUAL(*mach._pusActiveParam, 12345); + mach.ProcessCharacter(L'J'); + VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::Ground); + } + TEST_METHOD(TestCsiIgnore) { StateMachine mach(new OutputStateMachineEngine(new DummyDispatch)); @@ -429,6 +453,35 @@ class Microsoft::Console::VirtualTerminal::OutputEngineTest final mach.ProcessCharacter(AsciiChars::BEL); VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::Ground); } + + TEST_METHOD(TestLeadingZeroOscParam) + { + StateMachine mach(new OutputStateMachineEngine(new DummyDispatch)); + + VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::Ground); + mach.ProcessCharacter(AsciiChars::ESC); + VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::Escape); + mach.ProcessCharacter(L']'); + VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::OscParam); + for (int i = 0; i < 50; i++) // Any number of leading zeros should be supported + { + mach.ProcessCharacter(L'0'); + VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::OscParam); + } + for (int i = 0; i < 5; i++) // We're only expecting to be able to keep 5 digits max + { + mach.ProcessCharacter((wchar_t)(L'1' + i)); + VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::OscParam); + } + VERIFY_ARE_EQUAL(mach._sOscParam, 12345); + mach.ProcessCharacter(L';'); + VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::OscString); + mach.ProcessCharacter(L's'); + VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::OscString); + mach.ProcessCharacter(AsciiChars::BEL); + VERIFY_ARE_EQUAL(mach._state, StateMachine::VTStates::Ground); + } + TEST_METHOD(TestLongOscParam) { StateMachine mach(new OutputStateMachineEngine(new DummyDispatch));