Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audit FAIL_FASTs across the code #14298

Open
DHowett opened this issue Oct 27, 2022 · 3 comments
Open

Audit FAIL_FASTs across the code #14298

DHowett opened this issue Oct 27, 2022 · 3 comments
Labels
Area-CodeHealth Issues related to code cleanliness, linting, rules, warnings, errors, static analysis, etc. Needs-Tag-Fix Doesn't match tag requirements Product-Conhost For issues in the Console codebase Severity-Crash Crashes are real bad news.

Comments

@DHowett
Copy link
Member

DHowett commented Oct 27, 2022

Back in 2018 we switched every NTASSERT/ASSERT/NT_ASSERT in these components to a FAIL_FAST, unequivocally, because if we cared enough to check it, we should care enough to die for it.
I think that’s good and valuable, and it has its place.

Now that these components are shared with Terminal (who seeks to host multiple copies of each of them in parallel), and now that a11y has taken a bigger bet on them performing sanely and safely,
I’m wondering if we should scale back a little bit on the take down the entire process if something lifts off into space stance.

We’re seeing a good number of crashes due to accessibility that I think should just be “oh, the API returned an error code, NVDA can recover”. We once saw reports that resizing the window when an unexpected DBCS half lands in the buffer (#4907) caused a crash.

They’re programming errors, for sure, but our users probably want things to be more reliable.

Should, or could, we surface those as exceptions and let the caller recover wherever possible?
Should we just internally recover?

Let's find out.


Generated as of 2022-10-27 ab04067

How did I generate this?
rg -n FAIL_FAST_IF\`( --no-heading | % {
	$p=$_ -split ":";
	$pa=$p[0] -replace "\\","/";
	$ln=$p[1];
	[pscustomobject]@{File=$pa;Line=$ln}
} | group File | sort -Descending Count | % {
	"## $($_.Name)`n";
	$_.Group | % {
		"https://github.com/microsoft/terminal/blob/$(git rev-parse HEAD)/src/$($_.File)#L$($_.Line)"
	};
	"`n"
}

host/screenInfo.cpp

FAIL_FAST_IF(!(gci.IsConsoleLocked()));

FAIL_FAST_IF(coordFontSize.X == 0);
FAIL_FAST_IF(coordFontSize.Y == 0);

FAIL_FAST_IF(coordFont.X == 0);
FAIL_FAST_IF(coordFont.Y == 0);

FAIL_FAST_IF(coordFontSize.X == 0);
FAIL_FAST_IF(coordFontSize.Y == 0);

FAIL_FAST_IF(coordFontSize.X == 0);
FAIL_FAST_IF(coordFontSize.Y == 0);

FAIL_FAST_IF(coordFont.X == 0);
FAIL_FAST_IF(coordFont.Y == 0);

FAIL_FAST_IF(!(sEndX < coordScreenBufferSize.X));

FAIL_FAST_IF(!(_viewport.Top() >= 0));
// TODO MSFT: 17663344 - Audit call sites for this precondition. Extremely tiny offscreen windows.
//FAIL_FAST_IF(!(_viewport.IsValid()));

FAIL_FAST_IF(!(DeltaY <= 0));

host/cmdline.cpp

FAIL_FAST_IF(!(cookedReadData.BufferStartPtr() == cookedReadData.BufferCurrentPtr()));

FAIL_FAST_IF(!(cookedReadData.BufferStartPtr() == cookedReadData.BufferCurrentPtr()));

FAIL_FAST_IF(!(cookedReadData.BufferStartPtr() == cookedReadData.BufferCurrentPtr()));

FAIL_FAST_IF(!(cookedReadData.BufferStartPtr() == cookedReadData.BufferCurrentPtr()));

FAIL_FAST_IF(!(LastWord > cookedReadData.BufferStartPtr()));

FAIL_FAST_IF(!(LastWord > cookedReadData.BufferStartPtr()));

FAIL_FAST_IF(!(LastWord > cookedReadData.BufferStartPtr()));

FAIL_FAST_IF(!(LastWord >= cookedReadData.BufferStartPtr()));

FAIL_FAST_IF(!(NextWord < BufLast));

FAIL_FAST_IF(!(cookedReadData.BufferStartPtr() == cookedReadData.BufferCurrentPtr()));

host/_stream.cpp

FAIL_FAST_IF(!(coordCursor.Y == bufferSize.Y));

FAIL_FAST_IF(!(WI_IsFlagSet(screenInfo.OutputMode, ENABLE_PROCESSED_OUTPUT)));

FAIL_FAST_IF(!(WI_IsFlagSet(screenInfo.OutputMode, ENABLE_PROCESSED_OUTPUT)));

FAIL_FAST_IF(!(Tmp2 >= buffer.get()));

FAIL_FAST_IF(!(WI_IsFlagSet(screenInfo.OutputMode, ENABLE_PROCESSED_OUTPUT)));
FAIL_FAST_IF(!(WI_IsFlagSet(screenInfo.OutputMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING)));
// defined down in the WriteBuffer default case hiding on the other end of the state machine. See outputStream.cpp
// This is the only mode used by DoWriteConsole.
FAIL_FAST_IF(!(WI_IsFlagSet(dwFlags, WC_LIMIT_BACKSPACE)));

FAIL_FAST_IF(wFromComplemented.size() != 1);

host/inputBuffer.cpp

FAIL_FAST_IF(streamRead && readCount != 1);

FAIL_FAST_IF(!(unusedWaitStatus));
// write all previously existing records
size_t existingEventsWritten;
_WriteBuffer(existingStorage, existingEventsWritten, unusedWaitStatus);
FAIL_FAST_IF(!(!unusedWaitStatus));

FAIL_FAST_IF(!(inEvents.size() == 1));
FAIL_FAST_IF(_storage.empty());

FAIL_FAST_IF(!(inEvents.size() == 1));

FAIL_FAST_IF(_storage.empty());

propsheet/fontdlg.cpp

FAIL_FAST_IF(!(OEMCP != 0)); // must be initialized

FAIL_FAST_IF(!(i == LB_ERR || (ULONG)i < NumberOfFonts));

FAIL_FAST_IF(!(OEMCP != 0));

FAIL_FAST_IF(!(FontIndex < (int)NumberOfFonts));

FAIL_FAST_IF(!((ULONG)nFont < NumberOfFonts));

FAIL_FAST_IF(!((ULONG)FontIndex < NumberOfFonts));

host/utils.cpp

terminal/src/host/utils.cpp

Lines 176 to 179 in ab04067

FAIL_FAST_IF(!(coordFirst.X >= 0 && coordFirst.X < cRowWidth));
FAIL_FAST_IF(!(coordSecond.X >= 0 && coordSecond.X < cRowWidth));
FAIL_FAST_IF(!(coordFirst.Y >= 0 && coordFirst.Y < cRowHeight));
FAIL_FAST_IF(!(coordSecond.Y >= 0 && coordSecond.Y < cRowHeight));

terminal/src/host/utils.cpp

Lines 231 to 232 in ab04067

FAIL_FAST_IF(!(coordCorner.X == srRectangle.Left || coordCorner.X == srRectangle.Right));
FAIL_FAST_IF(!(coordCorner.Y == srRectangle.Top || coordCorner.Y == srRectangle.Bottom));

interactivity/win32/icon.cpp

FAIL_FAST_IF(!(&hIconRef == &_hIcon || &hIconRef == &_hSmIcon));
// expecting hDefaultIconRef to be pointing to either the regular or small default handles
FAIL_FAST_IF(!(&hDefaultIconRef == &_hDefaultIcon || &hDefaultIconRef == &_hDefaultSmIcon));

FAIL_FAST_IF(!(&hIconRef == &_hDefaultIcon || &hIconRef == &_hDefaultSmIcon));

FAIL_FAST_IF(!(&hIconRef == &_hIcon || &hIconRef == &_hSmIcon));

FAIL_FAST_IF(!(&hIconRef == &_hIcon || &hIconRef == &_hSmIcon));

host/readDataCooked.cpp

FAIL_FAST_IF(!gci.IsConsoleLocked());

FAIL_FAST_IF(_pInputReadHandleData->IsInputPending());
// this routine should be called by a thread owning the same lock on the same console as we're reading from.
FAIL_FAST_IF(_pInputReadHandleData->GetReadCount() == 0);

FAIL_FAST_IF(!(Tmp < (_backupLimit + _bytesRead)));

host/settings.cpp

FAIL_FAST_IF(!(_dwWindowSize.X > 0));
FAIL_FAST_IF(!(_dwWindowSize.Y > 0));
FAIL_FAST_IF(!(_dwScreenBufferSize.X > 0));
FAIL_FAST_IF(!(_dwScreenBufferSize.Y > 0));

host/history.cpp

FAIL_FAST_IF(WI_IsFlagClear(historyList.Flags, CLE_ALLOCATED));

FAIL_FAST_IF(commands > SHORT_MAX);

FAIL_FAST_IF(WI_IsFlagClear(Flags, CLE_ALLOCATED));

FAIL_FAST_IF(!(WI_IsFlagSet(Flags, CLE_ALLOCATED)));

host/srvinit.cpp

FAIL_FAST_IF(!(sizeof(Cac->AppName) == sizeof(Data.ApplicationName)));
FAIL_FAST_IF(!(sizeof(Cac->Title) == sizeof(Data.Title)));
FAIL_FAST_IF(!(sizeof(Cac->CurDir) == sizeof(Data.CurrentDirectory)));

host/misc.cpp

FAIL_FAST_IF(!(IsDBCSLeadByteConsole(*pch, &gci.OutputCPInfo) || cch == 1));

FAIL_FAST_IF(!(pwchSource != (LPWSTR)pchTarget));

FAIL_FAST_IF(!(cchTarget > 0));

interactivity/win32/window.cpp

FAIL_FAST_IF(!(s_atomWindowClass == 0));

FAIL_FAST_IF(!((fInKeyboardMarkMode && !fInMouseSelectMode && !fInScrollMode) ||

FAIL_FAST_IF(!(rectSizeTemp.top == 0 && rectSizeTemp.left == 0));

host/readDataDirect.cpp

FAIL_FAST_IF(_pInputReadHandleData->GetReadCount() == 0);

FAIL_FAST_IF(!gci.IsConsoleLocked());

FAIL_FAST_IF(!(readEvents.empty()));

server/ProcessList.cpp

FAIL_FAST_IF(!(ServiceLocator::LocateGlobals().getConsoleInformation().IsConsoleLocked()));

FAIL_FAST_IF(!(ServiceLocator::LocateGlobals().getConsoleInformation().IsConsoleLocked()));

FAIL_FAST_IF(!(_processes.cend() != std::find(_processes.cbegin(), _processes.cend(), pProcessData)));

host/selectionInput.cpp

FAIL_FAST_IF(!IsInSelectingState());

FAIL_FAST_IF(!fMoveSucceeded); // we should never fail to move forward after having moved backward

FAIL_FAST_IF(!bufferSize.IsInBounds(coordSelPoint));

tsf/TfEditSession.cpp

FAIL_FAST_IF(!(cr >= 0));

FAIL_FAST_IF(!((cchCompleted > 0) && (cchCompleted < cch)));

FAIL_FAST_IF(!(lTextLength > 0));

server/ObjectHandle.cpp

FAIL_FAST_IF(!(_IsInput()));

FAIL_FAST_IF(pReadHandleData->GetReadCount() > 0);

FAIL_FAST_IF(!(_IsOutput()));

host/CommandListPopup.cpp

FAIL_FAST_IF(_currentCommand < 0);

FAIL_FAST_IF(!(Tmp < (cookedReadData.BufferStartPtr() + cookedReadData.BytesRead())));

interactivity/win32/windowio.cpp

FAIL_FAST_IF(!(gci.IsConsoleLocked()));

FAIL_FAST_IF(!(ProcessData != nullptr && ProcessData->fRootProcess));

host/conimeinfo.cpp

FAIL_FAST_IF(size <= 0); // It's a programming error to have <= 0 cells to insert.

FAIL_FAST_IF(text.size() != attributes.size());

host/input.cpp

FAIL_FAST_IF(EventsWritten != 1);

FAIL_FAST_IF(!(!((CtrlFlags & (CONSOLE_CTRL_CLOSE_FLAG | CONSOLE_CTRL_BREAK_FLAG | CONSOLE_CTRL_C_FLAG)) && (CtrlFlags & (CONSOLE_CTRL_LOGOFF_FLAG | CONSOLE_CTRL_SHUTDOWN_FLAG)))));

host/consoleInformation.cpp

FAIL_FAST_IF(rc == 0);

FAIL_FAST_IF(rc == ULONG_MAX);

host/readDataRaw.cpp

FAIL_FAST_IF(_pInputReadHandleData->GetReadCount() == 0);
FAIL_FAST_IF(!Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation().IsConsoleLocked());

tsf/TfDispAttr.cpp

FAIL_FAST_IF(!(var.vt == VT_UNKNOWN));

FAIL_FAST_IF(!(tfPropVal.varValue.vt == VT_I4)); // expecting GUIDATOMs

host/inputReadHandleData.cpp

FAIL_FAST_IF(prevCount == 0); // we just underflowed, that's a programming error.

host/directio.cpp

FAIL_FAST_IF(!(readEvents.empty()));

FAIL_FAST_IF(!(readEvents.empty()));

host/ConsoleArguments.cpp

FAIL_FAST_IF(!(CLIENT_COMMANDLINE_ARG == start->c_str()));

FAIL_FAST_IF(!args.empty());

propsheet/registry.cpp

FAIL_FAST_IF(!(OEMCP != 0));

FAIL_FAST_IF(!(OEMCP != 0));

server/WaitBlock.cpp

FAIL_FAST_IF(!(WI_IsFlagClear(TerminationReason, WaitTerminationReason::ThreadDying)));

host/writeData.cpp

FAIL_FAST_IF(!(Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation().IsConsoleLocked()));

propsheet/misc.cpp

FAIL_FAST_IF(!(ShouldAllowAllMonoTTFonts()));

interactivity/base/ServiceLocator.cpp

FAIL_FAST_IF(nullptr != s_oneCoreTeardownFunction);

host/stream.cpp

FAIL_FAST_IF(Wait);

host/dbcs.cpp

FAIL_FAST_IF(iDst != buffer.size());

server/IoSorter.cpp

FAIL_FAST_IF(!(!ReplyPending));

types/sgrStack.cpp

FAIL_FAST_IF(validParts.test(SgrSaveRestoreStackOptions::All));

@ghost ghost added Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting Needs-Tag-Fix Doesn't match tag requirements labels Oct 27, 2022
@DHowett DHowett added Severity-Crash Crashes are real bad news. Area-CodeHealth Issues related to code cleanliness, linting, rules, warnings, errors, static analysis, etc. labels Oct 27, 2022
@carlos-zamora
Copy link
Member

now that a11y has taken a bigger bet on them

For the record, all of the a11y-related crashes were removed in #13250, I believe.

@carlos-zamora carlos-zamora added Product-Conhost For issues in the Console codebase and removed Needs-Tag-Fix Doesn't match tag requirements labels Oct 27, 2022
@DHowett
Copy link
Member Author

DHowett commented Nov 2, 2022

_stream.cpp:618 was removed in 86928bb.

@zadjii-msft zadjii-msft removed the Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting label Nov 7, 2022
@ghost ghost added the Needs-Tag-Fix Doesn't match tag requirements label Nov 7, 2022
@lhecker
Copy link
Member

lhecker commented Mar 14, 2023

Removed

FAIL_FAST_IF(!_isInputPending); // we shouldn't have multiline input without a pending input.
in anticipation for #14991.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-CodeHealth Issues related to code cleanliness, linting, rules, warnings, errors, static analysis, etc. Needs-Tag-Fix Doesn't match tag requirements Product-Conhost For issues in the Console codebase Severity-Crash Crashes are real bad news.
Projects
None yet
Development

No branches or pull requests

4 participants