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

Fix a ReadConsoleOutputCharacter regression #16898

Merged
merged 4 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 3 additions & 39 deletions .github/actions/spelling/expect/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ backgrounding
backported
backstory
barbaz
Batang
Bazz
BBDM
bbwe
Expand Down Expand Up @@ -180,7 +179,6 @@ changelists
chaof
charinfo
CHARSETINFO
chcbpat
chh
chshdng
CHT
Expand All @@ -198,7 +196,6 @@ cloudconsole
cloudvault
CLSCTX
clsids
CLUSTERMAP
cmatrix
cmder
CMDEXT
Expand All @@ -214,15 +211,13 @@ codepages
codepath
coinit
colorizing
COLORMATRIX
COLORREFs
colorschemes
colorspec
colortable
colortbl
colortest
colortool
COLR
combaseapi
comctl
commandline
Expand Down Expand Up @@ -367,11 +362,9 @@ DBGFONTS
DBGOUTPUT
dbh
dblclk
DBlob
DColor
DCOLORVALUE
dcommon
dcompile
dcompiler
DComposition
dde
Expand Down Expand Up @@ -479,7 +472,6 @@ depersist
deprioritized
deserializers
desktopwindowxamlsource
DESTINATIONNAME
devicecode
Dext
DFactory
Expand Down Expand Up @@ -539,7 +531,6 @@ DWORDs
dwrite
dxgi
dxgidwm
dxguid
dxinterop
dxsm
dxttbmp
Expand Down Expand Up @@ -607,7 +598,7 @@ FEEF
fesb
FFAF
FFDE
FFrom
FFFDb
fgbg
FGCOLOR
FGHIJ
Expand Down Expand Up @@ -719,7 +710,6 @@ GETWAITTOKILLTIMEOUT
GETWHEELSCROLLCHARACTERS
GETWHEELSCROLLCHARS
GETWHEELSCROLLLINES
GFEh
Gfun
gfx
GGI
Expand Down Expand Up @@ -867,7 +857,6 @@ INLINEPREFIX
inproc
Inputkeyinfo
INPUTPROCESSORPROFILE
inputrc
Inputreadhandledata
INSERTMODE
INTERACTIVITYBASE
Expand Down Expand Up @@ -908,10 +897,6 @@ KAttrs
kawa
Kazu
kazum
kcub
kcud
kcuf
kcuu
kernelbase
kernelbasestaging
KEYBDINPUT
Expand All @@ -923,7 +908,6 @@ Keymapping
keyscan
keystate
keyups
khome
KILLACTIVE
KILLFOCUS
kinda
Expand Down Expand Up @@ -1061,7 +1045,6 @@ MBUTTON
MBUTTONDBLCLK
MBUTTONDOWN
MBUTTONUP
Mbxy
mdmerge
MDs
MEASUREITEM
Expand All @@ -1086,7 +1069,6 @@ minkernel
MINMAXINFO
minwin
minwindef
Mip
MMBB
mmcc
MMCPL
Expand Down Expand Up @@ -1123,8 +1105,8 @@ msix
msrc
MSVCRTD
MTSM
munges
Munged
munges
murmurhash
muxes
myapplet
Expand Down Expand Up @@ -1221,7 +1203,6 @@ ntdll
ntifs
ntlpcapi
ntm
nto
ntrtl
ntstatus
NTSYSCALLAPI
Expand Down Expand Up @@ -1297,7 +1278,6 @@ parentable
parms
PATCOPY
pathcch
Pathto
PATTERNID
pcat
pcb
Expand Down Expand Up @@ -1456,7 +1436,6 @@ pwsz
pythonw
Qaabbcc
QUERYOPEN
QUESTIONMARK
quickedit
QUZ
QWER
Expand Down Expand Up @@ -1489,8 +1468,6 @@ READCONSOLE
READCONSOLEOUTPUT
READCONSOLEOUTPUTSTRING
READMODE
reallocs
reamapping
rectread
redef
redefinable
Expand Down Expand Up @@ -1518,7 +1495,6 @@ repositorypath
Requiresx
rerasterize
rescap
Resequence
RESETCONTENT
resheader
resmimetype
Expand Down Expand Up @@ -1551,7 +1527,6 @@ RRRGGGBB
rsas
rtcore
RTEXT
RTFTo
RTLREADING
Rtn
ruleset
Expand Down Expand Up @@ -1699,7 +1674,6 @@ srcsrv
SRCSRVTRG
srctool
srect
srv
srvinit
srvpipe
ssa
Expand Down Expand Up @@ -1731,7 +1705,6 @@ SUA
subcompartment
subkeys
SUBLANG
subresource
subsystemconsole
subsystemwindows
swapchain
Expand Down Expand Up @@ -1835,7 +1808,6 @@ tosign
touchpad
Tpp
Tpqrst
tracelog
tracelogging
traceviewpp
trackbar
Expand All @@ -1846,7 +1818,6 @@ Trd
TREX
triaged
triaging
TRIANGLESTRIP
Tribool
TRIMZEROHEADINGS
trx
Expand Down Expand Up @@ -1888,8 +1859,8 @@ UINTs
ul
ulcch
uld
uldb
uldash
uldb
ulwave
Unadvise
unattend
Expand All @@ -1900,7 +1871,6 @@ unhosted
UNICODETEXT
UNICRT
Unintense
Uniscribe
unittesting
unittests
unk
Expand All @@ -1912,7 +1882,6 @@ untextured
UPDATEDISPLAY
UPDOWN
UPKEY
UPSS
upss
uregex
URegular
Expand Down Expand Up @@ -1996,7 +1965,6 @@ VTRGBTo
vtseq
vtterm
vttest
waitable
WANSUNG
WANTARROWS
WANTTAB
Expand Down Expand Up @@ -2121,7 +2089,6 @@ wrkstr
wrl
wrp
WRunoff
WScript
wsl
WSLENV
wstr
Expand Down Expand Up @@ -2156,13 +2123,11 @@ XBUTTONDOWN
XBUTTONUP
XCast
XCENTER
XColors
xcopy
XCount
xdy
XEncoding
xes
xff
XFG
XFile
XFORM
Expand All @@ -2171,7 +2136,6 @@ xinchaof
xinxinchaof
XManifest
XMath
XMFLOAT
xorg
XResource
xsi
Expand Down
17 changes: 17 additions & 0 deletions src/host/ft_host/CJK_DbcsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ class DbcsTests
BEGIN_TEST_METHOD(TestInvalidTrailer)
TEST_METHOD_PROPERTY(L"IsolationLevel", L"Method")
END_TEST_METHOD()

TEST_METHOD(TestNarrowSurrogate);
};

bool DbcsTests::DbcsTestSetup()
Expand Down Expand Up @@ -2183,3 +2185,18 @@ void DbcsTests::TestInvalidTrailer()

DbcsWriteRead::Verify(expected, output);
}

// The various console APIs that read back from the buffer are generally incompatible with UTF16 and surrogate pairs.
// ReadConsoleOutputCharacterW in particular has a nLength parameter which is a column count but also the buffer size.
// This makes it impossible to reliably return arbitrarily long graphemes per-cell in the output buffer.
// The test ensures that we replace them with U+FFFD which makes the behavior more consistent for the caller.
void DbcsTests::TestNarrowSurrogate()
{
const auto out = GetStdHandle(STD_OUTPUT_HANDLE);
wchar_t buf[3];
DWORD read;

VERIFY_WIN32_BOOL_SUCCEEDED(WriteConsoleOutputCharacterW(out, L"a\U00010000b", 4, {}, &read));
VERIFY_WIN32_BOOL_SUCCEEDED(ReadConsoleOutputCharacterW(out, &buf[0], ARRAYSIZE(buf), {}, &read));
VERIFY_ARE_EQUAL(std::wstring_view(L"a\U0000FFFDb"), std::wstring_view(&buf[0], read));
Fixed Show fixed Hide fixed
}
7 changes: 6 additions & 1 deletion src/host/output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,12 @@ std::wstring ReadOutputStringW(const SCREEN_INFORMATION& screenInfo,
// Otherwise, add anything that isn't a trailing cell. (Trailings are duplicate copies of the leading.)
if (it->DbcsAttr() != DbcsAttribute::Trailing)
{
retVal += it->Chars();
auto chars = it->Chars();
if (chars.size() > 1)
{
chars = { &UNICODE_REPLACEMENT, 1 };
}
retVal += chars;
}
}

Expand Down
Loading