Skip to content

Commit

Permalink
feat: escape LF, tab in IPC message (#1169)
Browse files Browse the repository at this point in the history
escape LF to "\\n" to avoid crash cause by LF in context

---------

Co-authored-by: 居戎氏 <[email protected]>
  • Loading branch information
fxliang and lotem authored Apr 8, 2024
1 parent d96c227 commit e901024
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 22 deletions.
38 changes: 19 additions & 19 deletions RimeWithWeasel/RimeWithWeasel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,22 +475,18 @@ void RimeWithWeaselHandler::_GetCandidateInfo(CandidateInfo& cinfo,
cinfo.comments.resize(ctx.menu.num_candidates);
cinfo.labels.resize(ctx.menu.num_candidates);
for (int i = 0; i < ctx.menu.num_candidates; ++i) {
cinfo.candies[i].str = std::regex_replace(
string_to_wstring(ctx.menu.candidates[i].text, CP_UTF8),
std::wregex(L"\\r\\n|\\n|\\r"), L"\r");
cinfo.candies[i].str =
escape_string(string_to_wstring(ctx.menu.candidates[i].text, CP_UTF8));
if (ctx.menu.candidates[i].comment) {
cinfo.comments[i].str = std::regex_replace(
string_to_wstring(ctx.menu.candidates[i].comment, CP_UTF8),
std::wregex(L"\\r\\n|\\n|\\r"), L"\r");
cinfo.comments[i].str = escape_string(
string_to_wstring(ctx.menu.candidates[i].comment, CP_UTF8));
}
if (RIME_STRUCT_HAS_MEMBER(ctx, ctx.select_labels) && ctx.select_labels) {
cinfo.labels[i].str =
std::regex_replace(string_to_wstring(ctx.select_labels[i], CP_UTF8),
std::wregex(L"\\r\\n|\\n|\\r"), L"\r");
escape_string(string_to_wstring(ctx.select_labels[i], CP_UTF8));
} else if (ctx.menu.select_keys) {
cinfo.labels[i].str =
std::regex_replace(std::wstring(1, ctx.menu.select_keys[i]),
std::wregex(L"\\r\\n|\\n|\\r"), L"\r");
escape_string(std::wstring(1, ctx.menu.select_keys[i]));
} else {
cinfo.labels[i].str = std::to_wstring((i + 1) % 10);
}
Expand Down Expand Up @@ -782,7 +778,9 @@ bool RimeWithWeaselHandler::_Respond(WeaselSessionId ipc_id, EatLine eat) {
RIME_STRUCT(RimeCommit, commit);
if (RimeGetCommit(session_id, &commit)) {
actions.insert("commit");
messages.push_back(std::string("commit=") + commit.text + '\n');

std::string commit_text = escape_string<char>(commit.text);
messages.push_back(std::string("commit=") + commit_text + '\n');
RimeFreeCommit(&commit);
}

Expand Down Expand Up @@ -821,7 +819,8 @@ bool RimeWithWeaselHandler::_Respond(WeaselSessionId ipc_id, EatLine eat) {
case UIStyle::PREVIEW:
if (ctx.commit_text_preview != NULL) {
std::string first = ctx.commit_text_preview;
messages.push_back(std::string("ctx.preedit=") + first + '\n');
messages.push_back(std::string("ctx.preedit=") +
escape_string<char>(first) + '\n');
messages.push_back(
std::string("ctx.preedit.cursor=") +
std::to_string(utf8towcslen(first.c_str(), 0)) + ',' +
Expand All @@ -834,7 +833,8 @@ bool RimeWithWeaselHandler::_Respond(WeaselSessionId ipc_id, EatLine eat) {
// no preview, fall back to composition
case UIStyle::COMPOSITION:
messages.push_back(std::string("ctx.preedit=") +
ctx.composition.preedit + '\n');
escape_string<char>(ctx.composition.preedit) +
'\n');
if (ctx.composition.sel_start <= ctx.composition.sel_end) {
messages.push_back(
std::string("ctx.preedit.cursor=") +
Expand All @@ -852,8 +852,9 @@ bool RimeWithWeaselHandler::_Respond(WeaselSessionId ipc_id, EatLine eat) {
case UIStyle::PREVIEW_ALL:
CandidateInfo cinfo;
_GetCandidateInfo(cinfo, ctx);
std::string topush =
std::string("ctx.preedit=") + ctx.composition.preedit + " [";
std::string topush = std::string("ctx.preedit=") +
escape_string<char>(ctx.composition.preedit) +
" [";
for (auto i = 0; i < ctx.menu.num_candidates; i++) {
std::string label =
session_status.style.label_font_point > 0
Expand All @@ -872,12 +873,11 @@ bool RimeWithWeaselHandler::_Respond(WeaselSessionId ipc_id, EatLine eat) {
CP_UTF8);
std::string prefix =
(i != ctx.menu.highlighted_candidate_index) ? "" : mark_text;
topush += " " + prefix + label +
std::string(ctx.menu.candidates[i].text) + " " + comment;
topush += " " + prefix + escape_string(label) +
escape_string<char>(ctx.menu.candidates[i].text) + " " +
escape_string(comment);
}
messages.push_back(topush + " ]\n");
// messages.push_back(std::string("ctx.preedit=") +
// ctx.composition.preedit + '\n');
if (ctx.composition.sel_start <= ctx.composition.sel_end) {
messages.push_back(
std::string("ctx.preedit.cursor=") +
Expand Down
6 changes: 4 additions & 2 deletions WeaselIPC/Committer.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "Deserializer.h"
#include "Committer.h"
#include <WeaselUtility.h>

using namespace weasel;

Expand All @@ -16,6 +17,7 @@ void Committer::Store(Deserializer::KeyType const& key,
std::wstring const& value) {
if (!m_pTarget->p_commit)
return;
if (key.size() == 1)
*m_pTarget->p_commit = value;
if (key.size() == 1) {
*m_pTarget->p_commit = unescape_string(value);
}
}
9 changes: 8 additions & 1 deletion WeaselIPC/ContextUpdater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void ContextUpdater::_StoreText(Text& target,
std::wstring const& value) {
if (k.size() == 2) {
target.clear();
target.str = value;
target.str = unescape_string(value);
return;
}
if (k.size() == 3) {
Expand Down Expand Up @@ -78,6 +78,13 @@ void ContextUpdater::_StoreCand(Deserializer::KeyType k,
boost::archive::text_wiarchive ia(ss);

ia >> cinfo;

for (auto& cand : cinfo.candies)
cand.str = unescape_string(cand.str);
for (auto& lalel : cinfo.labels)
lalel.str = unescape_string(lalel.str);
for (auto& comment : cinfo.comments)
comment.str = unescape_string(comment.str);
}

// StatusUpdater
Expand Down
73 changes: 73 additions & 0 deletions include/WeaselUtility.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,78 @@ inline std::string wstring_to_string(const std::wstring& wstr,
return res;
}

template <typename CharT>
struct EscapeChar {
static const CharT escape;
static const CharT linefeed;
static const CharT tab;
static const CharT linefeed_escape;
static const CharT tab_escape;
};

template <>
const char EscapeChar<char>::escape = '\\';
template <>
const char EscapeChar<char>::linefeed = '\n';
template <>
const char EscapeChar<char>::tab = '\t';
template <>
const char EscapeChar<char>::linefeed_escape = 'n';
template <>
const char EscapeChar<char>::tab_escape = 't';

template <>
const wchar_t EscapeChar<wchar_t>::escape = L'\\';
template <>
const wchar_t EscapeChar<wchar_t>::linefeed = L'\n';
template <>
const wchar_t EscapeChar<wchar_t>::tab = L'\t';
template <>
const wchar_t EscapeChar<wchar_t>::linefeed_escape = L'n';
template <>
const wchar_t EscapeChar<wchar_t>::tab_escape = L't';

template <typename CharT>
inline std::basic_string<CharT> escape_string(
const std::basic_string<CharT> input) {
using Esc = EscapeChar<CharT>;
std::basic_stringstream<CharT> res;
for (auto p = input.begin(); p != input.end(); ++p) {
if (*p == Esc::escape) {
res << Esc::escape << Esc::escape;
} else if (*p == Esc::linefeed) {
res << Esc::escape << Esc::linefeed_escape;
} else if (*p == Esc::tab) {
res << Esc::escape << Esc::tab_escape;
} else {
res << *p;
}
}
return res.str();
}

template <typename CharT>
inline std::basic_string<CharT> unescape_string(
const std::basic_string<CharT>& input) {
using Esc = EscapeChar<CharT>;
std::basic_stringstream<CharT> res;
for (auto p = input.begin(); p != input.end(); ++p) {
if (*p == Esc::escape) {
if (++p == input.end()) {
break;
} else if (*p == Esc::linefeed_escape) {
res << Esc::linefeed;
} else if (*p == Esc::tab_escape) {
res << Esc::tab;
} else { // \a => a
res << *p;
}
} else {
res << *p;
}
}
return res.str();
}

// resource
std::string GetCustomResource(const char* name, const char* type);

0 comments on commit e901024

Please sign in to comment.