[vte/vte-0-60] icu: glue: Set error callback on the from-unicode conversion



commit c893450ae32b85870df3313021d9ce1fdfcbe49e
Author: Christian Persch <chpe src gnome org>
Date:   Sat Apr 25 12:28:14 2020 +0200

    icu: glue: Set error callback on the from-unicode conversion
    
    The from-unicode side of the converter is only used on user input
    (keyboard, IM, clipboard paste). When it receives input not representable
    in the target encoding, it inserts the substitution character of the
    target encoding, which in many cases is U+001A. However, when sent to a
    PTY, that is interpreted as Ctrl-Z.
    
    Instead, set the from-unicode converter to error out when encountering
    such unrepresentable input.
    
    Fixes: https://gitlab.gnome.org/GNOME/vte/issues/233
    (cherry picked from commit 344c2e77e9fdbc19f4c213c23b7bf91e93a9f7aa)

 src/icu-glue.cc | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)
---
diff --git a/src/icu-glue.cc b/src/icu-glue.cc
index d86f23c3..6350386f 100644
--- a/src/icu-glue.cc
+++ b/src/icu-glue.cc
@@ -111,10 +111,35 @@ make_icu_converter(char const* charset,
 {
         auto err = icu::ErrorCode{};
         auto converter = std::shared_ptr<UConverter>{ucnv_open(charset, err), &ucnv_close};
-        if (err.isFailure())
+        if (err.isFailure()) {
                 g_set_error(error, G_CONVERT_ERROR, G_CONVERT_ERROR_NO_CONVERSION,
                             "Failed to open converter for charset \"%s\": %s",
                             charset, err.errorName());
+                return {};
+        }
+
+        /* The unicode->target conversion is only used when converting
+         * user input (keyboard, clipboard) to be sent to the PTY, and
+         * we don't want the ucnv_fromUChars to substitute the SUB character
+         * for illegal input, since SUB is U+001A which is Ctrl-Z, which
+         * the default UCNV_FROM_U_CALLBACK_SUBSTITUTE callback does.
+         * Use UCNV_FROM_U_CALLBACK_STOP to stop conversion when encountering
+         * illegal input.
+         */
+        err.reset();
+        ucnv_setFromUCallBack(converter.get(),
+                              UCNV_FROM_U_CALLBACK_STOP,
+                              nullptr,
+                              nullptr,
+                              nullptr,
+                              err);
+        if (err.isFailure()) {
+                g_set_error(error, G_CONVERT_ERROR, G_CONVERT_ERROR_NO_CONVERSION,
+                            "Failed ucnv_setFromUCallBack for charset \"%s\": %s",
+                            charset, err.errorName());
+                return {};
+        }
+
         return converter;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]