From 0544c781728a665806b069cb8202acd4f6981a0a Mon Sep 17 00:00:00 2001 From: Kevin Frei Date: Thu, 14 Dec 2023 11:10:51 -0800 Subject: [PATCH] Fix a crash from character type confusion interaction with libedit (#75388) If you type `settings show ` LLDB might crash, depending on the version of libedit you're compiled with, and whether you're compiled with `-DLLDB_EDITLINE_USE_WCHAR=0` (and depending on how the optimizer lays out the stack...) The issue has to do with trying to figure out whether the libedit `getchar` callback is supposed to read a wide or 8 bit character. In order to maintain backward compatibility, there's really no 'clean' way to do it. We just have to make sure that we're invoking el_[w]getc with a buffer that is as wide as the getchar callback (registered by the `SetGetCharacterFunction` function further down in `Editline.cpp`. So, it's 'fixed' with a comment, and a wider version of the 'reply' variable. Co-authored-by: Kevin Frei --- lldb/include/lldb/Host/Editline.h | 2 ++ lldb/source/Host/common/Editline.cpp | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lldb/include/lldb/Host/Editline.h b/lldb/include/lldb/Host/Editline.h index c598244150788d..9049b106f02a34 100644 --- a/lldb/include/lldb/Host/Editline.h +++ b/lldb/include/lldb/Host/Editline.h @@ -75,6 +75,8 @@ using EditLineCharType = char; // to wchar_t. It is not possible to detect differentiate between the two // versions exactly, but this is a pretty good approximation and allows us to // build against almost any editline version out there. +// It does, however, require extra care when invoking el_getc, as the type +// of the input is a single char buffer, but the callback will write a wchar_t. #if LLDB_EDITLINE_USE_WCHAR || defined(EL_CLIENTDATA) || LLDB_HAVE_EL_RFUNC_T using EditLineGetCharType = wchar_t; #else diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp index 82e17ec753ab23..ce707e530d008b 100644 --- a/lldb/source/Host/common/Editline.cpp +++ b/lldb/source/Host/common/Editline.cpp @@ -978,8 +978,14 @@ void Editline::DisplayCompletions( break; fprintf(editline.m_output_file, "More (Y/n/a): "); - char reply = 'n'; - int got_char = el_getc(editline.m_editline, &reply); + // The type for the output and the type for the parameter are different, + // to allow interoperability with older versions of libedit. The container + // for the reply must be as wide as what our implementation is using, + // but libedit may use a narrower type depending on the build + // configuration. + EditLineGetCharType reply = L'n'; + int got_char = el_wgetc(editline.m_editline, + reinterpret_cast(&reply)); // Check for a ^C or other interruption. if (editline.m_editor_status == EditorStatus::Interrupted) { editline.m_editor_status = EditorStatus::Editing;