aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorZufu Liu <unknown>2021-11-22 08:46:14 +1100
committerZufu Liu <unknown>2021-11-22 08:46:14 +1100
commit8904b645419b8deb202046bbc785440d0d006404 (patch)
tree13a8e979ec427f00bff80f8f002ce18fcdbfe4f6
parent598b0b021ca5a585ab256a7e5a1bdafd87931136 (diff)
downloadscintilla-mirror-8904b645419b8deb202046bbc785440d0d006404.tar.gz
Bug [#2295] Fix potential memory leak with Korean language input.
-rw-r--r--doc/ScintillaHistory.html4
-rw-r--r--win32/HanjaDic.cxx122
-rw-r--r--win32/HanjaDic.h2
-rw-r--r--win32/ScintillaWin.cxx6
4 files changed, 73 insertions, 61 deletions
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html
index ca0fbfff1..190820625 100644
--- a/doc/ScintillaHistory.html
+++ b/doc/ScintillaHistory.html
@@ -593,6 +593,10 @@
or SC_ORDER_PERFORMSORT and the list is empty.
<a href="https://sourceforge.net/p/scintilla/bugs/2294/">Bug #2294</a>.
</li>
+ <li>
+ On Win32 prevent potential memory leaks for Korean language input.
+ <a href="https://sourceforge.net/p/scintilla/bugs/2295/">Bug #2295</a>.
+ </li>
</ul>
<h3>
<a href="https://www.scintilla.org/scintilla514.zip">Release 5.1.4</a>
diff --git a/win32/HanjaDic.cxx b/win32/HanjaDic.cxx
index a218b1f18..04df43845 100644
--- a/win32/HanjaDic.cxx
+++ b/win32/HanjaDic.cxx
@@ -8,23 +8,42 @@
#include <string>
#include <string_view>
+#include <memory>
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#include <ole2.h>
-#include "UniConversion.h"
#include "HanjaDic.h"
-namespace Scintilla::Internal {
+namespace Scintilla::Internal::HanjaDict {
+
+struct UnknownReleaser {
+ // Called by unique_ptr to destroy/free the resource
+ template <class T>
+ void operator()(T *pUnknown) noexcept {
+ // same as ReleaseUnknown() in PlatWin.h
+ try {
+ pUnknown->Release();
+ } catch (...) {
+ // IUnknown::Release must not throw, ignore if it does.
+ }
+ }
+};
+
+struct BSTRDeleter {
+ void operator()(BSTR bstr) const noexcept {
+ SysFreeString(bstr);
+ }
+};
-namespace HanjaDict {
+using UniqueBSTR = std::unique_ptr<OLECHAR[], BSTRDeleter>;
interface IRadical;
interface IHanja;
interface IStrokes;
-typedef enum { HANJA_UNKNOWN = 0, HANJA_K0 = 1, HANJA_K1 = 2, HANJA_OTHER = 3 } HANJA_TYPE;
+enum HANJA_TYPE { HANJA_UNKNOWN = 0, HANJA_K0 = 1, HANJA_K1 = 2, HANJA_OTHER = 3 };
interface IHanjaDic : IUnknown {
STDMETHOD(OpenMainDic)();
@@ -60,82 +79,71 @@ extern "C" const GUID __declspec(selectany) IID_IHanjaDic =
{ 0xad75f3ac, 0x18cd, 0x48c6, { 0xa2, 0x7d, 0xf1, 0xe9, 0xa7, 0xdc, 0xe4, 0x32 } };
class HanjaDic {
-private:
- HRESULT hr;
- CLSID CLSID_HanjaDic;
-
-public:
- IHanjaDic *HJinterface;
+ std::unique_ptr<IHanjaDic, UnknownReleaser> HJinterface;
- HanjaDic() : HJinterface(nullptr) {
- hr = CLSIDFromProgID(OLESTR("mshjdic.hanjadic"), &CLSID_HanjaDic);
+ bool OpenHanjaDic(LPCOLESTR lpszProgID) noexcept {
+ CLSID CLSID_HanjaDic;
+ HRESULT hr = CLSIDFromProgID(lpszProgID, &CLSID_HanjaDic);
if (SUCCEEDED(hr)) {
+ IHanjaDic *instance = nullptr;
hr = CoCreateInstance(CLSID_HanjaDic, nullptr,
- CLSCTX_INPROC_SERVER, IID_IHanjaDic,
- (LPVOID *)& HJinterface);
+ CLSCTX_INPROC_SERVER, IID_IHanjaDic,
+ (LPVOID *)&instance);
if (SUCCEEDED(hr)) {
- hr = HJinterface->OpenMainDic();
+ HJinterface.reset(instance);
+ hr = instance->OpenMainDic();
+ return SUCCEEDED(hr);
}
}
+ return false;
}
- // Deleted so HanjaDic objects can not be copied.
- HanjaDic(const HanjaDic &) = delete;
- HanjaDic(HanjaDic &&) = delete;
- HanjaDic &operator=(const HanjaDic &) = delete;
- HanjaDic &operator=(HanjaDic &&) = delete;
+public:
+ bool Open() noexcept {
+ return OpenHanjaDic(OLESTR("imkrhjd.hanjadic"))
+ || OpenHanjaDic(OLESTR("mshjdic.hanjadic"));
+ }
- ~HanjaDic() {
- if (SUCCEEDED(hr)) {
- hr = HJinterface->CloseMainDic();
- try {
- // This can never fail but IUnknown::Release is not marked noexcept.
- HJinterface->Release();
- } catch (...) {
- // Ignore any exception
- }
- }
+ void Close() const noexcept {
+ HJinterface->CloseMainDic();
}
- bool HJdictAvailable() {
- return SUCCEEDED(hr);
+ bool IsHanja(wchar_t hanja) const noexcept {
+ HANJA_TYPE hanjaType = HANJA_UNKNOWN;
+ const HRESULT hr = HJinterface->GetHanjaType(hanja, &hanjaType);
+ return SUCCEEDED(hr) && hanjaType > HANJA_UNKNOWN;
}
- bool IsHanja(int hanja) {
- HANJA_TYPE hanjaType;
- hr = HJinterface->GetHanjaType(static_cast<unsigned short>(hanja), &hanjaType);
- if (SUCCEEDED(hr)) {
- return (hanjaType > 0);
- }
- return false;
+ bool HanjaToHangul(BSTR bstrHanja, UniqueBSTR &bstrHangul) const noexcept {
+ BSTR result = nullptr;
+ const HRESULT hr = HJinterface->HanjaToHangul(bstrHanja, &result);
+ bstrHangul.reset(result);
+ return SUCCEEDED(hr);
}
};
-int GetHangulOfHanja(wchar_t *inout) {
+bool GetHangulOfHanja(std::wstring &inout) noexcept {
// Convert every hanja to hangul.
- // Return the number of characters converted.
- int changed = 0;
+ // Return whether any character been converted.
+ // Hanja linked to different notes in Hangul have different codes,
+ // so current character based conversion is enough.
+ // great thanks for BLUEnLIVE.
+ bool changed = false;
HanjaDic dict;
- if (dict.HJdictAvailable()) {
- const size_t len = wcslen(inout);
- wchar_t conv[UTF8MaxBytes] = {0};
- BSTR bstrHangul = SysAllocString(conv);
- for (size_t i=0; i<len; i++) {
- if (dict.IsHanja(static_cast<int>(inout[i]))) { // Pass hanja only!
- conv[0] = inout[i];
- BSTR bstrHanja = SysAllocString(conv);
- const HRESULT hr = dict.HJinterface->HanjaToHangul(bstrHanja, &bstrHangul);
- if (SUCCEEDED(hr)) {
- inout[i] = static_cast<wchar_t>(bstrHangul[0]);
- changed += 1;
+ if (dict.Open()) {
+ for (wchar_t &character : inout) {
+ if (dict.IsHanja(character)) { // Pass hanja only!
+ const UniqueBSTR bstrHanja{SysAllocStringLen(&character, 1)};
+ UniqueBSTR bstrHangul;
+ if (dict.HanjaToHangul(bstrHanja.get(), bstrHangul)) {
+ changed = true;
+ character = bstrHangul[0];
}
- SysFreeString(bstrHanja);
}
}
- SysFreeString(bstrHangul);
+ dict.Close();
}
return changed;
}
}
-}
diff --git a/win32/HanjaDic.h b/win32/HanjaDic.h
index c23abc19a..5f7f2a2f5 100644
--- a/win32/HanjaDic.h
+++ b/win32/HanjaDic.h
@@ -13,7 +13,7 @@ namespace Scintilla::Internal {
namespace HanjaDict {
-int GetHangulOfHanja(wchar_t *inout);
+bool GetHangulOfHanja(std::wstring &inout) noexcept;
}
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
index 1035384e3..e89e93977 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -1055,10 +1055,10 @@ void ScintillaWin::SelectionToHangul() {
pdoc->GetCharRange(&documentStr[0], selStart, documentStrLen);
std::wstring uniStr = StringDecode(documentStr, CodePageOfDocument());
- const int converted = HanjaDict::GetHangulOfHanja(&uniStr[0]);
- documentStr = StringEncode(uniStr, CodePageOfDocument());
+ const bool converted = HanjaDict::GetHangulOfHanja(uniStr);
- if (converted > 0) {
+ if (converted) {
+ documentStr = StringEncode(uniStr, CodePageOfDocument());
pdoc->BeginUndoAction();
ClearSelection();
InsertPaste(&documentStr[0], documentStr.size());