Blob Blame History Raw
From b3b90f0e467ade81165d67638ca7c2541963a879 Mon Sep 17 00:00:00 2001
From: fujiwarat <takao.fujiwara1@gmail.com>
Date: Sat, 20 Mar 2021 20:28:42 +0900
Subject: [PATCH] src/tests: Change default session gnome-session to mutter

gnome-shell 40 now shows the overview mode by login and
gnome-desktop-testing-runner cannot get the focus.
Now the default session is changed to mutter from gnome-session.
The default may be changed to twm if mutter also will be changed
not to accept the application focus in the future.

Disable Tour dialog which prevent test application from getting the
input focus.

Don't output FAIL if the actual failure is 0 for Fedora CI.

BUG=https://discourse.gnome.org/t/focus-on-autostart-application-by-login/5863
---
 src/tests/ibus-desktop-testing-runner.in | 31 +++++++++++++++++++-----
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/src/tests/ibus-desktop-testing-runner.in b/src/tests/ibus-desktop-testing-runner.in
index 4232c549..23e3411e 100755
--- a/src/tests/ibus-desktop-testing-runner.in
+++ b/src/tests/ibus-desktop-testing-runner.in
@@ -4,7 +4,7 @@
 #
 # ibus - The Input Bus
 #
-# Copyright (c) 2018-2020 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2018-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
 # Copyright (c) 2018 Red Hat, Inc.
 #
 # This program is free software; you can redistribute it and/or modify
@@ -36,7 +36,7 @@
 
 
 PROGNAME=`basename $0`
-VERSION=0.1
+VERSION=0.2
 DISPLAY=:99.0
 BUILDDIR="."
 SRCDIR="."
@@ -44,7 +44,7 @@ TEST_LOG="test-suite.log"
 TEST_LOG_STDOUT=0
 RESULT_LOG=""
 HAVE_GRAPHICS=1
-DESKTOP_COMMAND="dbus-launch --exit-with-session gnome-session"
+DESKTOP_COMMAND="dbus-launch --exit-with-session mutter"
 PID_XORG=0
 PID_GNOME_SESSION=0
 TESTING_RUNNER="default"
@@ -80,7 +80,9 @@ usage()
 "-b, --builddir=BUILDDIR          Set the BUILDDIR\n"                          \
 "-s, --srcdir=SOURCEDIR           Set the SOURCEDIR\n"                         \
 "-c, --no-graphics                Use Xvfb instead of Xorg\n"                  \
-"-d, --desktop=DESKTOP            Run DESTKTOP. The default is gnome-session\n" \
+"-d, --desktop=DESKTOP            Run DESTKTOP. The default is mutter.\n"      \
+"                                 Suffix '-with-dbus' can run DESKTOP with dbus session." \
+"                                 E.g. --desktop=gnome-session-with-dbus"      \
 "-t, --tests=\"TESTS...\"           Run TESTS programs which is separated by space\n" \
 "-r, --runner=RUNNER              Run TESTS programs with a test RUNNER.\n"    \
 "                                 RUNNDER = gnome or default.\n"               \
@@ -115,6 +117,12 @@ parse_args()
         * )                  usage; exit 1;;
         esac
     done
+    DL='$'
+    HAS_DBUS_SUFFIX=`echo "$DESKTOP_COMMAND" | grep "\-with\-dbus$DL"`
+    if [ x"$HAS_DBUS_SUFFIX" != x ] ; then
+        DESKTOP_COMMAND=`echo "$DESKTOP_COMMAND" | sed -e 's/-with-dbus$//'`
+        DESKTOP_COMMAND="dbus-launch --exit-with-session $DESKTOP_COMMAND"
+    fi
 }
 
 init_desktop()
@@ -221,6 +229,12 @@ run_desktop()
     if [ x"$HAS_GNOME" = x ] ; then
         ibus-daemon --daemonize --verbose
         sleep 3
+    else
+        # Disable Tour dialog to get focus
+        V=`gsettings get org.gnome.shell welcome-dialog-last-shown-version`
+        if [ x"$V" = x ] ; then
+            gsettings set org.gnome.shell welcome-dialog-last-shown-version '100'
+        fi
     fi
 }
 
@@ -360,8 +374,13 @@ EOF_RUNNER
         ;;
     esac
     echo ""
-    print_log -e "${GREEN}PASS${NC}: $pass"
-    print_log -e "${RED}FAIL${NC}: $fail"
+    # Fedora CI assumes the test is failed even if $fail is 0.
+    if [ $pass -ne 0 ] ; then
+        print_log -e "${GREEN}PASS${NC}: $pass"
+    fi
+    if [ $fail -ne 0 ] ; then
+        print_log -e "${RED}FAIL${NC}: $fail"
+    fi
     echo ""
     if [ $TEST_LOG_STDOUT -eq 1 ] ; then
         cat $TEST_LOG
-- 
2.28.0

From d105a3941aad53b0c7470a1e9c1033987b029fb8 Mon Sep 17 00:00:00 2001
From: fujiwarat <takao.fujiwara1@gmail.com>
Date: Wed, 12 May 2021 18:54:30 +0900
Subject: [PATCH] client/gtk2: Implement
 ibus_im_context_set_surrounding_with_selection()

Selection bounds need to be re-calculated when pre-edit text is
inserted and the selection position is changed.
GTK4 has a new API GtkIMContext.set_surrounding_with_selection()
to fix this issue and now IBus GTK module inherits the API.

BUG=https://github.com/ibus/ibus/issues/2013
---
 client/gtk2/ibusimcontext.c | 53 ++++++++++++++++++++++++++++++-------
 1 file changed, 44 insertions(+), 9 deletions(-)

diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c
index e153081d..61194816 100644
--- a/client/gtk2/ibusimcontext.c
+++ b/client/gtk2/ibusimcontext.c
@@ -2,8 +2,8 @@
 /* vim:set et sts=4: */
 /* ibus - The Input Bus
  * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2015-2020 Takao Fujiwara <takao.fujiwara1@gmail.com>
- * Copyright (C) 2008-2020 Red Hat, Inc.
+ * Copyright (C) 2015-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2008-2021 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -165,11 +165,19 @@ static void     ibus_im_context_set_cursor_location
 static void     ibus_im_context_set_use_preedit
                                             (GtkIMContext           *context,
                                              gboolean               use_preedit);
+#if !GTK_CHECK_VERSION (4, 1, 2)
 static void     ibus_im_context_set_surrounding
                                             (GtkIMContext  *slave,
                                              const gchar   *text,
-                                             gint           len,
-                                             gint           cursor_index);
+                                             int            len,
+                                             int            cursor_index);
+#endif
+static void     ibus_im_context_set_surrounding_with_selection
+                                            (GtkIMContext  *slave,
+                                             const gchar   *text,
+                                             int            len,
+                                             int            cursor_index,
+                                             int            anchor_index);
 
 /* static methods*/
 static void     _ibus_context_update_preedit_text_cb
@@ -724,7 +732,12 @@ ibus_im_context_class_init (IBusIMContextClass *class)
 #endif
     im_context_class->set_cursor_location = ibus_im_context_set_cursor_location;
     im_context_class->set_use_preedit = ibus_im_context_set_use_preedit;
+#if GTK_CHECK_VERSION (4, 1, 2)
+    im_context_class->set_surrounding_with_selection
+            = ibus_im_context_set_surrounding_with_selection;
+#else
     im_context_class->set_surrounding = ibus_im_context_set_surrounding;
+#endif
     gobject_class->notify = ibus_im_context_notify;
     gobject_class->finalize = ibus_im_context_finalize;
 
@@ -1624,8 +1637,22 @@ get_selection_anchor_point (IBusIMContext *ibusimcontext,
 static void
 ibus_im_context_set_surrounding (GtkIMContext  *context,
                                  const gchar   *text,
-                                 gint           len,
-                                 gint           cursor_index)
+                                 int            len,
+                                 int            cursor_index)
+{
+    ibus_im_context_set_surrounding_with_selection (context,
+                                                    text,
+                                                    len,
+                                                    cursor_index,
+                                                    cursor_index);
+}
+
+static void
+ibus_im_context_set_surrounding_with_selection (GtkIMContext  *context,
+                                                const gchar   *text,
+                                                int            len,
+                                                int            cursor_index,
+                                                int            anchor_index)
 {
     g_return_if_fail (context != NULL);
     g_return_if_fail (IBUS_IS_IM_CONTEXT (context));
@@ -1647,18 +1674,26 @@ ibus_im_context_set_surrounding (GtkIMContext  *context,
         ibustext = ibus_text_new_from_string (p);
         g_free (p);
 
-        guint anchor_pos = get_selection_anchor_point (ibusimcontext,
-                                                       cursor_pos,
-                                                       utf8_len);
+        gint anchor_pos = get_selection_anchor_point (ibusimcontext,
+                                                      cursor_pos,
+                                                      utf8_len);
         ibus_input_context_set_surrounding_text (ibusimcontext->ibuscontext,
                                                  ibustext,
                                                  cursor_pos,
                                                  anchor_pos);
     }
+#if GTK_CHECK_VERSION (4, 1, 2)
+    gtk_im_context_set_surrounding_with_selection (ibusimcontext->slave,
+                                                   text,
+                                                   len,
+                                                   cursor_index,
+                                                   anchor_index);
+#else
     gtk_im_context_set_surrounding (ibusimcontext->slave,
                                     text,
                                     len,
                                     cursor_index);
+#endif
 }
 
 static void
-- 
2.28.0

From c3c224770a9db120713f86ce836cacbfcb178484 Mon Sep 17 00:00:00 2001
From: fujiwarat <takao.fujiwara1@gmail.com>
Date: Wed, 26 May 2021 17:46:42 +0900
Subject: [PATCH] Fix code reviews

---
 bus/ibusimpl.c                |  23 ++++--
 bus/server.c                  |  10 +--
 client/gtk2/ibusimcontext.c   |   8 ++
 client/wayland/main.c         |   9 ++-
 client/x11/main.c             |  22 +++--
 conf/dconf/main.c             |   7 +-
 portal/portal.c               |   7 +-
 setup/ibus-setup.in           |   2 +-
 src/emoji-parser.c            |  46 ++++++-----
 src/ibusaccelgroup.c          |   2 +-
 src/ibusbus.c                 |  10 ++-
 src/ibuscomposetable.c        |  91 ++++++++++++++++++---
 src/ibusemoji.c               |   8 +-
 src/ibusenginesimple.c        |  21 +++--
 src/ibushotkey.c              |   4 +-
 src/ibusregistry.c            |   9 ++-
 src/ibusshare.c               |  36 +++++----
 src/ibustext.c                |   5 +-
 src/ibusunicode.c             |  17 +++-
 src/tests/ibus-compose.c      |   6 +-
 src/tests/ibus-keypress.c     |   3 +-
 src/unicode-parser.c          |  52 ++++++------
 util/IMdkit/FrameMgr.c        |  34 +++++++-
 util/IMdkit/i18nIc.c          |  41 ++++++++--
 util/IMdkit/i18nMethod.c      |  24 +++++-
 util/IMdkit/i18nOffsetCache.c |   2 +-
 util/IMdkit/i18nPtHdr.c       | 148 ++++++++++++++++++++++++++++------
 util/IMdkit/i18nUtil.c        |  20 +++++
 util/IMdkit/i18nX.c           |  29 ++++---
 29 files changed, 524 insertions(+), 172 deletions(-)

diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c
index e432e849..49a138fe 100644
--- a/bus/ibusimpl.c
+++ b/bus/ibusimpl.c
@@ -2,8 +2,8 @@
 /* vim:set et sts=4: */
 /* ibus - The Input Bus
  * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2011-2020 Takao Fujiwara <takao.fujiwara1@gmail.com>
- * Copyright (C) 2008-2020 Red Hat, Inc.
+ * Copyright (C) 2011-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2008-2021 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -624,7 +624,6 @@ bus_ibus_impl_destroy (BusIBusImpl *ibus)
 
     g_list_foreach (ibus->components, (GFunc) bus_component_stop, NULL);
 
-    pid = 0;
     timeout = 0;
     flag = FALSE;
     while (1) {
@@ -1190,6 +1189,7 @@ _ibus_get_current_input_context (BusIBusImpl     *ibus,
                                  GDBusConnection *connection,
                                  GError         **error)
 {
+    GVariant *retval = NULL;
     if (error) {
         *error = NULL;
     }
@@ -1204,8 +1204,14 @@ _ibus_get_current_input_context (BusIBusImpl     *ibus,
         const gchar *path = ibus_service_get_object_path (
                 (IBusService *) ibus->focused_context);
         /* the format-string 'o' is for a D-Bus object path. */
-        return g_variant_new_object_path (path);
+        retval = g_variant_new_object_path (path);
+        if (!retval) {
+            g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+                         "Could not get object path from %s",
+                         path ? path : "(null)");
+        }
     }
+    return retval;
 }
 
 static void
@@ -1572,6 +1578,7 @@ _ibus_get_global_engine (BusIBusImpl     *ibus,
                          GError         **error)
 {
     IBusEngineDesc *desc = NULL;
+    GVariant *retval = NULL;
 
     if (error) {
         *error = NULL;
@@ -1592,7 +1599,13 @@ _ibus_get_global_engine (BusIBusImpl     *ibus,
         GVariant *variant = ibus_serializable_serialize (
                 (IBusSerializable *) desc);
         // Set type "v" for introspection_xml.
-        return g_variant_new_variant (variant);
+        retval = g_variant_new_variant (variant);
+        if (!retval) {
+            g_set_error (error,
+                         G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+                         "Failed to serialize engine desc.");
+        }
+        return retval;
     } while (0);
 
     g_set_error (error,
diff --git a/bus/server.c b/bus/server.c
index 6c9e2c02..e8d0ce2b 100644
--- a/bus/server.c
+++ b/bus/server.c
@@ -2,8 +2,8 @@
 /* vim:set et sts=4: */
 /* bus - The Input Bus
  * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2011-2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
- * Copyright (C) 2008-2019 Red Hat, Inc.
+ * Copyright (C) 2011-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2008-2021 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -22,12 +22,11 @@
  */
 #include "server.h"
 
-#include <errno.h>
 #include <glib/gstdio.h>
 #include <gio/gio.h>
-#include <stdlib.h>
-#include <fcntl.h>
 #include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "dbusimpl.h"
@@ -282,6 +281,7 @@ bus_server_init (void)
          * `chmod` runs for the last directory only not to change the modes
          * of the parent directories. E.g. "/tmp/ibus".
          */
+        errno = 0;
         if (g_mkdir_with_parents (unix_dir, 0700) != 0) {
             g_error ("mkdir is failed in: %s: %s",
                      unix_dir, g_strerror (errno));
diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c
index 61194816..e7ce5363 100644
--- a/client/gtk2/ibusimcontext.c
+++ b/client/gtk2/ibusimcontext.c
@@ -385,7 +385,9 @@ _process_key_event_done (GObject      *object,
 
     ProcessKeyEventData *data = (ProcessKeyEventData *)user_data;
     GdkEvent *event = data->event;
+#if GTK_CHECK_VERSION (3, 98, 4)
     IBusIMContext *ibusimcontext = data->ibusimcontext;
+#endif
     GError *error = NULL;
 
     g_slice_free (ProcessKeyEventData, data);
@@ -1634,6 +1636,7 @@ get_selection_anchor_point (IBusIMContext *ibusimcontext,
     return anchor;
 }
 
+#if !GTK_CHECK_VERSION (4, 1, 2)
 static void
 ibus_im_context_set_surrounding (GtkIMContext  *context,
                                  const gchar   *text,
@@ -1646,6 +1649,7 @@ ibus_im_context_set_surrounding (GtkIMContext  *context,
                                                     cursor_index,
                                                     cursor_index);
 }
+#endif
 
 static void
 ibus_im_context_set_surrounding_with_selection (GtkIMContext  *context,
@@ -1851,7 +1855,11 @@ _create_gdk_event (IBusIMContext *ibusimcontext,
         if (event->state & GDK_CONTROL_MASK) {
             if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
             else if (c == '2') {
+#if GLIB_CHECK_VERSION (2, 68, 0)
+                event->string = g_memdup2 ("\0\0", 2);
+#else
                 event->string = g_memdup ("\0\0", 2);
+#endif
                 event->length = 1;
                 buf[0] = '\0';
                 goto out;
diff --git a/client/wayland/main.c b/client/wayland/main.c
index d86bab9e..1f99c804 100644
--- a/client/wayland/main.c
+++ b/client/wayland/main.c
@@ -1,7 +1,7 @@
 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 /* vim:set et sts=4: */
 /* ibus - The Input Bus
- * Copyright (C) 2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2019-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
  * Copyright (C) 2013 Intel Corporation
  * Copyright (C) 2013-2019 Red Hat, Inc.
  *
@@ -339,16 +339,19 @@ input_method_keyboard_keymap (void               *data,
 {
     IBusWaylandIM *wlim = data;
     GMappedFile *map;
-    GError *error;
+    GError *error = NULL;
 
     if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
         close(fd);
         return;
     }
 
-    error = NULL;
     map = g_mapped_file_new_from_fd (fd, FALSE, &error);
     if (map == NULL) {
+        if (error) {
+            g_warning ("Failed to map file fd %s", error->message);
+            g_error_free (error);
+        }
         close (fd);
         return;
     }
diff --git a/client/x11/main.c b/client/x11/main.c
index c9ee174d..ffd776fd 100644
--- a/client/x11/main.c
+++ b/client/x11/main.c
@@ -2,7 +2,7 @@
 /* vim:set et sts=4: */
 /* ibus
  * Copyright (C) 2007-2015 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2015-2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2015-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
  * Copyright (C) 2007-2015 Red Hat, Inc.
  *
  * main.c:
@@ -229,12 +229,13 @@ _xim_preedit_callback_draw (XIMS xims, X11IC *x11ic, const gchar *preedit_string
         }
     }
 
-    for (i = 0; i < len; i++) {
+    for (i = 0; feedback && i < len; i++) {
         if (feedback[i] == 0) {
             feedback[i] = XIMUnderline;
         }
     }
-    feedback[len] = 0;
+    if (feedback)
+        feedback[len] = 0;
 
     pcb.major_code = XIM_PREEDIT_DRAW;
     pcb.connect_id = x11ic->connect_id;
@@ -736,9 +737,20 @@ xim_get_ic_values (XIMS xims, IMChangeICStruct *call_data)
 
     for (i = 0; i < (int) call_data->ic_attr_num; ++i, ++ic_attr) {
         if (g_strcmp0 (XNFilterEvents, ic_attr->name) == 0) {
+            /* ic_attr->value will be freed in server side and ignore
+             * leak of malloc with -Wanalyzer-malloc-leak flags in gcc 11.0.1
+             */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
             ic_attr->value = (void *) malloc (sizeof (CARD32));
-            *(CARD32 *) ic_attr->value = KeyPressMask | KeyReleaseMask;
-            ic_attr->value_length = sizeof (CARD32);
+            if (ic_attr->value) {
+                *(CARD32 *) ic_attr->value = KeyPressMask | KeyReleaseMask;
+                ic_attr->value_length = sizeof (CARD32);
+            } else {
+                g_warning ("Failed to malloc");
+                ic_attr->value_length = 0;
+            }
+#pragma GCC diagnostic pop
         }
     }
 
diff --git a/conf/dconf/main.c b/conf/dconf/main.c
index e6878424..0d78b97d 100644
--- a/conf/dconf/main.c
+++ b/conf/dconf/main.c
@@ -2,7 +2,8 @@
 /* vim:set et sts=4: */
 /* ibus - The Input Bus
  * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2008-2010 Red Hat, Inc.
+ * Copyright (C) 2012-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2008-2021 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -70,7 +71,9 @@ main (gint argc, gchar **argv)
     GOptionContext *context;
 
     setlocale (LC_ALL, "");
-    g_setenv ("DCONF_PROFILE", "ibus", FALSE);
+    errno = 0;
+    if (!g_setenv ("DCONF_PROFILE", "ibus", FALSE))
+        g_warning ("Failed setenv %s", errno ? strerror (errno) : "(null)");
 
     context = g_option_context_new ("- ibus dconf component");
 
diff --git a/portal/portal.c b/portal/portal.c
index e78bc92f..213e2ba6 100644
--- a/portal/portal.c
+++ b/portal/portal.c
@@ -1,7 +1,7 @@
 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 /* vim:set et sts=4: */
 /* ibus - The Input Bus
- * Copyright (C) 2017-2019 Red Hat, Inc.
+ * Copyright (C) 2017-2021 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -508,7 +508,6 @@ create_input_context_done (IBusBus               *bus,
     if (portal_context == NULL) {
         g_dbus_method_invocation_return_gerror (invocation, error);
         g_error_free (error);
-        g_object_unref (portal_context);
         return;
     }
 
@@ -656,8 +655,10 @@ main (gint argc, gchar **argv)
         exit (-1);
     }
 
+     errno = 0;
     /* Avoid even loading gvfs to avoid accidental confusion */
-    g_setenv ("GIO_USE_VFS", "local", TRUE);
+    if (!g_setenv ("GIO_USE_VFS", "local", TRUE))
+        g_warning ("Failed setenv %s", errno ? strerror (errno) : "(null)");
 
     ibus_init ();
 
diff --git a/setup/ibus-setup.in b/setup/ibus-setup.in
index 4a6830af..474ce8a8 100644
--- a/setup/ibus-setup.in
+++ b/setup/ibus-setup.in
@@ -27,5 +27,5 @@ export IBUS_PREFIX=@prefix@
 export IBUS_DATAROOTDIR=@datarootdir@
 export IBUS_LOCALEDIR=@localedir@
 export IBUS_LIBEXECDIR=${libexecdir}
-exec ${PYTHON:-@PYTHON@} @prefix@/share/ibus/setup/main.py $@
+exec ${PYTHON:-@PYTHON@} @prefix@/share/ibus/setup/main.py "$@"
 
diff --git a/src/emoji-parser.c b/src/emoji-parser.c
index b117b1b4..36d36e05 100644
--- a/src/emoji-parser.c
+++ b/src/emoji-parser.c
@@ -1,7 +1,7 @@
 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 /* vim:set et sts=4: */
 /* ibus - The Input Bus
- * Copyright (C) 2016-2020 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2016-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
  * Copyright (C) 2016 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
@@ -291,11 +291,9 @@ emoji_data_new_object (EmojiData *data)
                                  "annotations",
                                  data->annotations,
                                  "description",
-                                 data->description ? data->description
-                                         : g_strdup (""),
+                                 data->description ? data->description : "",
                                  "category",
-                                 data->category ? data->category
-                                         : g_strdup (""),
+                                 data->category ? data->category : "",
                                  NULL);
     data->list = g_slist_append (data->list, emoji);
 }
@@ -608,7 +606,7 @@ unicode_emoji_test_parse_line (const gchar *line,
         return FALSE;
     }
     unicode_emoji_test_parse_description (segments[1], data);
-    g_strfreev (segments);
+    g_clear_pointer (&segments, g_strfreev);
     if (data->annotations == NULL) {
         if (data->subcategory) {
             int i;
@@ -631,7 +629,7 @@ unicode_emoji_test_parse_line (const gchar *line,
                 data->annotations = g_slist_append (data->annotations,
                                                     g_strdup (segments[i]));
             }
-            g_strfreev (segments);
+            g_clear_pointer (&segments, g_strfreev);
         } else {
             g_warning ("No subcategory line\n");
             goto failed_to_parse_unicode_emoji_test_line;
@@ -672,7 +670,7 @@ unicode_emoji_test_parse_file (const gchar *filename,
                    filename, error ? error->message : "");
         goto failed_to_parse_unicode_emoji_test;
     }
-    head = end = content;
+    end = content;
     while (*end == '\n' && end - content < length) {
         end++;
         n++;
@@ -1100,10 +1098,12 @@ static void
 category_list_dump (const gchar *category,
                     GString     *buff)
 {
+    gchar *line;
     g_return_if_fail (buff != NULL);
 
-    const gchar *line = g_strdup_printf ("    N_(\"%s\"),\n", category);
+    line = g_strdup_printf ("    N_(\"%s\"),\n", category);
     g_string_append (buff, line);
+    g_free (line);
 }
 
 static void
@@ -1113,7 +1113,7 @@ category_file_save (const gchar *filename,
     gchar *content = NULL;
     gsize length = 0;
     GError *error = NULL;
-    gchar *p;
+    gchar *p, *substr;
     GString *buff = NULL;
     int i;
     GSList *list_categories = NULL;
@@ -1139,24 +1139,28 @@ category_file_save (const gchar *filename,
             break;
     }
     if (p != NULL) {
-        g_string_append (buff, g_strndup (content, p - content));
+        substr = g_strndup (content, p - content);
+        g_string_append (buff, substr);
+        g_free (substr);
         g_string_append_c (buff, '\n');
     }
     g_clear_pointer (&content, g_free);
 
-    g_string_append (buff, g_strdup ("\n"));
-    g_string_append (buff, g_strdup_printf ("/* This file is generated by %s. */", __FILE__));
-    g_string_append (buff, g_strdup ("\n"));
-    g_string_append (buff, g_strdup ("include <glib/gi18n.h>\n"));
-    g_string_append (buff, g_strdup ("\n"));
-    g_string_append (buff, g_strdup ("#ifndef __IBUS_EMOJI_GEN_H_\n"));
-    g_string_append (buff, g_strdup ("#define __IBUS_EMOJI_GEN_H_\n"));
-    g_string_append (buff, g_strdup ("const static char *unicode_emoji_categories[] = {\n"));
+    g_string_append (buff, "\n");
+    substr = g_strdup_printf ("/* This file is generated by %s. */", __FILE__);
+    g_string_append (buff, substr);
+    g_free (substr);
+    g_string_append (buff, "\n");
+    g_string_append (buff, "include <glib/gi18n.h>\n");
+    g_string_append (buff, "\n");
+    g_string_append (buff, "#ifndef __IBUS_EMOJI_GEN_H_\n");
+    g_string_append (buff, "#define __IBUS_EMOJI_GEN_H_\n");
+    g_string_append (buff, "const static char *unicode_emoji_categories[] = {\n");
     list_categories = g_slist_sort (list_categories, (GCompareFunc)g_strcmp0);
     g_slist_foreach (list_categories, (GFunc)category_list_dump, buff);
     g_slist_free (list_categories);
-    g_string_append (buff, g_strdup ("};\n"));
-    g_string_append (buff, g_strdup ("#endif\n"));
+    g_string_append (buff, "};\n");
+    g_string_append (buff, "#endif\n");
 
     if (!g_file_set_contents (filename, buff->str, -1, &error)) {
         g_warning ("Failed to save emoji category file %s: %s", filename, error->message);
diff --git a/src/ibusaccelgroup.c b/src/ibusaccelgroup.c
index 8a81597e..ef2d3976 100644
--- a/src/ibusaccelgroup.c
+++ b/src/ibusaccelgroup.c
@@ -468,7 +468,7 @@ ibus_accelerator_name (guint            accelerator_key,
     if (accelerator_mods & IBUS_SUPER_MASK)
         l += sizeof (text_super) - 1;
 
-    accelerator = g_new (gchar, l + 1);
+    g_return_val_if_fail ((accelerator = g_new (gchar, l + 1)), NULL);
 
     accelerator_mods = saved_mods;
     l = 0;
diff --git a/src/ibusbus.c b/src/ibusbus.c
index b7ffbb47..e9b0bcbb 100644
--- a/src/ibusbus.c
+++ b/src/ibusbus.c
@@ -2,7 +2,7 @@
 /* vim:set et sts=4: */
 /* ibus - The Input Bus
  * Copyright (C) 2008-2015 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2015-2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2015-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
  * Copyright (C) 2008-2016 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
@@ -555,12 +555,18 @@ ibus_bus_init (IBusBus *bus)
 
     path = g_path_get_dirname (ibus_get_socket_path ());
 
-    g_mkdir_with_parents (path, 0700);
+    errno = 0;
+    if (g_mkdir_with_parents (path, 0700)) {
+        g_warning ("Failed to mkdir %s: %s", path, g_strerror (errno));
+        g_free (path);
+        return;
+    }
 
     if (stat (path, &buf) == 0) {
         if (buf.st_uid != getuid ()) {
             g_warning ("The owner of %s is not %s!",
                        path, ibus_get_user_name ());
+            g_free (path);
             return;
         }
         if (buf.st_mode != (S_IFDIR | S_IRWXU)) {
diff --git a/src/ibuscomposetable.c b/src/ibuscomposetable.c
index ef20469c..685ac717 100644
--- a/src/ibuscomposetable.c
+++ b/src/ibuscomposetable.c
@@ -1,7 +1,7 @@
 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 /* ibus - The Input Bus
  * Copyright (C) 2013-2014 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2013-2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2013-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -108,6 +108,7 @@ parse_compose_value (IBusComposeData  *compose_data,
     }
     ++head;
     p = head;
+    end = NULL;
     while ((*p != '\0') && (end = strchr (p, '\"'))) {
         if (*(end - 1) == '\\' && *(end - 2) == '\\')
             break;
@@ -516,10 +517,10 @@ ibus_compose_hash_get_cache_path (guint32 hash)
                                 "ibus", "compose", NULL);
     }
     path = g_build_filename (dir, basename, NULL);
-    if (g_mkdir_with_parents (dir, 0755) != 0) {
-        g_warning ("Failed to mkdir %s", dir);
-        g_free (path);
-        path = NULL;
+    errno = 0;
+    if (g_mkdir_with_parents (dir, 0755)) {
+        g_warning ("Failed to mkdir %s: %s", dir, g_strerror (errno));
+        g_clear_pointer (&path, g_free);
     }
 
     g_free (dir);
@@ -812,10 +813,14 @@ ibus_compose_table_deserialize (const gchar *contents,
         }
     }
     if (data_length) {
-        retval->priv->data_second = g_new (guint32, data_length);
-        memcpy (retval->priv->data_second,
-                data_32bit_second, data_length * sizeof (guint32));
-        retval->priv->second_size = second_size;
+        if ((retval->priv->data_second = g_new (guint32, data_length))) {
+            memcpy (retval->priv->data_second,
+                    data_32bit_second, data_length * sizeof (guint32));
+            retval->priv->second_size = second_size;
+        } else {
+            g_warning ("Failed g_new");
+            retval->priv->second_size = 0;
+        }
     }
 
 
@@ -910,6 +915,43 @@ ibus_compose_table_new_with_list (GList   *compose_list,
                                   int      n_index_stride,
                                   guint32  hash)
 {
+    /* @ibus_compose_seqs: Include both compose sequence and the value(compose
+     *     output) as the tradition GTK. The value is one character only
+     *     and within 16bit. I.e. All compose sequences and the values
+     *     are 16bit.
+     * @ibus_compose_seqs_32bit_second: Include the compose values only.
+     *     The length of values by compose sequence is more than one characster
+     *     or one of the values is outside 16bit but within 32bit.
+     *     Some values could be more than one character and Emoji character
+     *     could be outside 16bit.
+     *     See also ibus/src/tests/ibus-compose.emoji file for e.g.
+     * @ibus_compose_seqs_32bit_first: Include the compose sequence only in
+     *     case the value is included in @ibus_compose_seqs_32bit_second.
+     * @s_size_total: The number of compose sequences.
+     * @s_size_16bit: The number of compose sequences whose value is one
+     *     character only and within 16bit. I.e. the number of the compose
+     *     sequence in @ibus_compose_seqs is @@s_size_16bit. And
+     *     @s_size_total - @s_size_16bit is the number of the compose sequence
+     *     in @ibus_compose_seqs_32bit_first.
+     * @v_size_32bit: The total number of compose values. Each length of the
+     *     values is more than one character or one of the value is
+     *     outside 16bit but within 32bit. I.e. The size of
+     *     @ibus_compose_seqs_32bit_second is @v_size_32bit.
+     * @v_index_32bit: Each index of the compose values in
+     *     @ibus_compose_seqs_32bit_second and this is not a fixed value in
+     *     this API. If a compose sequence is found in
+     *     @ibus_compose_seqs_32bit_first and the next value is 0, 0 is lined
+     *     in @ibus_compose_seqs_32bit_first until @max_compose_len after
+     *     the found compose sequence. And the next value is the length of
+     *     the compose values and the next value is the @v_index_32bit, i.e.
+     *     the index of @ibus_compose_seqs_32bit_second.
+     *     E.g. the following line could be found in
+     *     @ibus_compose_seqs_32bit_first:
+     *         ..., "U17ff", "0", "0", "0", "0", 2, 100, ...
+     *     @ibus_compose_seqs_32bit_second[100] is "ាំ"  and the character
+     *     length is 2.
+     *     @max_compose_len is 5 and @n_index_stride is 7.
+     */
     gsize s_size_total, s_size_16bit, v_size_32bit, v_index_32bit;
     guint n = 0, m = 0;
     int i, j;
@@ -935,13 +977,25 @@ ibus_compose_table_new_with_list (GList   *compose_list,
         }
     }
 
-    if (s_size_16bit)
+    if (s_size_16bit) {
         ibus_compose_seqs = g_new (guint16, s_size_16bit * n_index_stride);
+        if (!ibus_compose_seqs) {
+            g_warning ("Failed g_new");
+            return NULL;
+        }
+    }
     if (s_size_total > s_size_16bit) {
         ibus_compose_seqs_32bit_first =
                 g_new (guint16,
                        (s_size_total - s_size_16bit) * n_index_stride);
         ibus_compose_seqs_32bit_second = g_new (guint32, v_size_32bit);
+        if (!ibus_compose_seqs_32bit_first || !ibus_compose_seqs_32bit_second) {
+            g_warning ("Failed g_new");
+            g_free (ibus_compose_seqs);
+            g_free (ibus_compose_seqs_32bit_first);
+            g_free (ibus_compose_seqs_32bit_second);
+            return NULL;
+        }
     }
 
     v_index_32bit = 0;
@@ -951,32 +1005,45 @@ ibus_compose_table_new_with_list (GList   *compose_list,
 
         is_32bit = unichar_length (compose_data->values) > 1 ? TRUE :
                 compose_data->values[0] >= 0xFFFF ? TRUE : FALSE;
+        if (is_32bit) {
+            g_assert (ibus_compose_seqs_32bit_first);
+            g_assert (ibus_compose_seqs_32bit_second);
+        }
         for (i = 0; i < max_compose_len; i++) {
             if (compose_data->sequence[i] == 0) {
                 for (j = i; j < max_compose_len; j++) {
-                    if (is_32bit)
+                    if (is_32bit) {
+                        g_assert (m < (s_size_total - s_size_16bit)
+                                  * n_index_stride);
                         ibus_compose_seqs_32bit_first[m++] = 0;
-                    else
+                    } else {
+                        g_assert (n < s_size_16bit * n_index_stride);
                         ibus_compose_seqs[n++] = 0;
+                    }
                 }
                 break;
             }
             if (is_32bit) {
+                g_assert (m < (s_size_total - s_size_16bit) * n_index_stride);
                 ibus_compose_seqs_32bit_first[m++] =
                         (guint16) compose_data->sequence[i];
             } else {
+                g_assert (n < s_size_16bit * n_index_stride);
                 ibus_compose_seqs[n++] = (guint16) compose_data->sequence[i];
             }
         }
         if (is_32bit) {
             for (j = 0; compose_data->values[j]; j++) {
+                g_assert (v_index_32bit + j <  v_size_32bit);
                 ibus_compose_seqs_32bit_second[v_index_32bit + j] =
                         compose_data->values[j];
             }
+            g_assert (m + 1 < (s_size_total - s_size_16bit) * n_index_stride);
             ibus_compose_seqs_32bit_first[m++] = j;
             ibus_compose_seqs_32bit_first[m++] = v_index_32bit;
             v_index_32bit += j;
         } else {
+            g_assert (n + 1 < s_size_16bit * n_index_stride);
             ibus_compose_seqs[n++] = (guint16) compose_data->values[0];
             ibus_compose_seqs[n++] = 0;
         }
diff --git a/src/ibusemoji.c b/src/ibusemoji.c
index ae8907a2..df97264b 100644
--- a/src/ibusemoji.c
+++ b/src/ibusemoji.c
@@ -1,7 +1,7 @@
 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 /* vim:set et sts=4: */
 /* bus - The Input Bus
- * Copyright (C) 2017-2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2017-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
  * Copyright (C) 2017-2019 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
@@ -497,7 +497,11 @@ ibus_emoji_data_save (const gchar *path,
 
     dir = g_path_get_dirname (path);
     if (g_strcmp0 (dir, ".") != 0 && g_stat (dir, &buf) != 0) {
-        g_mkdir_with_parents (dir, 0777);
+        errno = 0;
+        if (g_mkdir_with_parents (dir, 0777)) {
+            g_warning ("Failed mkdir %s: %s", dir, g_strerror (errno));
+            return;
+        }
     }
     g_free (dir);
     if (!g_file_set_contents (path, contents, length, &error)) {
diff --git a/src/ibusenginesimple.c b/src/ibusenginesimple.c
index 43bd5283..6dbc39c7 100644
--- a/src/ibusenginesimple.c
+++ b/src/ibusenginesimple.c
@@ -2,7 +2,7 @@
 /* vim:set et sts=4: */
 /* ibus - The Input Bus
  * Copyright (C) 2014 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2015-2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2015-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
  * Copyright (C) 2014-2017 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
@@ -466,11 +466,15 @@ check_hex (IBusEngineSimple *simple,
 
         ch = ibus_keyval_to_unicode (priv->compose_buffer[i]);
 
-        if (ch == 0)
+        if (ch == 0) {
+            g_string_free (str, TRUE);
             return FALSE;
+        }
 
-        if (!g_unichar_isxdigit (ch))
+        if (!g_unichar_isxdigit (ch)) {
+            g_string_free (str, TRUE);
             return FALSE;
+        }
 
         buf[g_unichar_to_utf8 (ch, buf)] = '\0';
 
@@ -487,8 +491,9 @@ check_hex (IBusEngineSimple *simple,
     if (nptr - str->str < str->len) {
         g_string_free (str, TRUE);
         return FALSE;
-    } else
+    } else {
         g_string_free (str, TRUE);
+    }
 
     if (g_unichar_validate (n)) {
         priv->tentative_match = n;
@@ -559,11 +564,15 @@ check_emoji_table (IBusEngineSimple       *simple,
 
         ch = ibus_keyval_to_unicode (priv->compose_buffer[i]);
 
-        if (ch == 0)
+        if (ch == 0) {
+            g_string_free (str, TRUE);
             return FALSE;
+        }
 
-        if (!g_unichar_isprint (ch))
+        if (!g_unichar_isprint (ch)) {
+            g_string_free (str, TRUE);
             return FALSE;
+        }
 
         buf[g_unichar_to_utf8 (ch, buf)] = '\0';
 
diff --git a/src/ibushotkey.c b/src/ibushotkey.c
index d4ab7c23..e72b8305 100644
--- a/src/ibushotkey.c
+++ b/src/ibushotkey.c
@@ -2,7 +2,7 @@
 /* vim:set et sts=4: */
 /* IBus - The Input Bus
  * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2018-2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2018-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
  * Copyright (C) 2008-2019 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
@@ -373,6 +373,8 @@ ibus_hotkey_profile_add_hotkey (IBusHotkeyProfile *profile,
         p->event = event;
     }
 
+    if (!p)
+        return FALSE;
     p->hotkeys = g_list_append (p->hotkeys, hotkey);
 
     return TRUE;
diff --git a/src/ibusregistry.c b/src/ibusregistry.c
index 3386a5d1..23c5ca1b 100644
--- a/src/ibusregistry.c
+++ b/src/ibusregistry.c
@@ -2,7 +2,7 @@
 /* vim:set et sts=4: */
 /* bus - The Input Bus
  * Copyright (C) 2015 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2015-2020 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2015-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
  * Copyright (C) 2015-2020 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
@@ -438,7 +438,12 @@ ibus_registry_save_cache_file (IBusRegistry *registry,
     g_assert (filename != NULL);
 
     cachedir = g_path_get_dirname (filename);
-    g_mkdir_with_parents (cachedir, 0775);
+    errno = 0;
+    if (g_mkdir_with_parents (cachedir, 0775)) {
+        g_warning ("Failed to mkdir %s: %s", cachedir, g_strerror (errno));
+        g_free (cachedir);
+        return FALSE;
+    }
     g_free (cachedir);
 
     variant = ibus_serializable_serialize (IBUS_SERIALIZABLE (registry));
diff --git a/src/ibusshare.c b/src/ibusshare.c
index e0ef2ce0..8974511a 100644
--- a/src/ibusshare.c
+++ b/src/ibusshare.c
@@ -2,7 +2,7 @@
 /* vim:set et sts=4: */
 /* ibus - The Input Bus
  * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2015-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2015-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
  * Copyright (C) 2008-2018 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
@@ -197,22 +197,17 @@ ibus_get_address (void)
     FILE *pf;
 
     /* free address */
-    if (address != NULL) {
-        g_free (address);
-        address = NULL;
-    }
+    g_clear_pointer (&address, g_free);
 
     /* get address from env variable */
     address = g_strdup (g_getenv ("IBUS_ADDRESS"));
-    if (address) {
+    if (address)
         return address;
-    }
 
     /* read address from ~/.config/ibus/bus/soketfile */
     pf = fopen (ibus_get_socket_path (), "r");
-    if (pf == NULL) {
+    if (pf == NULL)
         return NULL;
-    }
 
     while (!feof (pf)) {
         gchar *p = buffer;
@@ -224,11 +219,12 @@ ibus_get_address (void)
             continue;
         /* parse IBUS_ADDRESS */
         if (strncmp (p, "IBUS_ADDRESS=", sizeof ("IBUS_ADDRESS=") - 1) == 0) {
-            address = p + sizeof ("IBUS_ADDRESS=") - 1;
-            for (p = (gchar *)address; *p != '\n' && *p != '\0'; p++);
+            gchar *head = p + sizeof ("IBUS_ADDRESS=") - 1;
+            for (p = head; *p != '\n' && *p != '\0'; p++);
             if (*p == '\n')
                 *p = '\0';
-            address = g_strdup (address);
+            g_free (address);
+            address = g_strdup (head);
             continue;
         }
 
@@ -241,9 +237,8 @@ ibus_get_address (void)
     }
     fclose (pf);
 
-    if (pid == -1 || kill (pid, 0) != 0) {
+    if (pid == -1 || kill (pid, 0) != 0)
         return NULL;
-    }
 
     return address;
 }
@@ -256,10 +251,19 @@ ibus_write_address (const gchar *address)
     g_return_if_fail (address != NULL);
 
     path = g_path_get_dirname (ibus_get_socket_path ());
-    g_mkdir_with_parents (path, 0700);
+    errno = 0;
+    if (g_mkdir_with_parents (path, 0700)) {
+        g_warning ("Failed to mkdir %s: %s", path, g_strerror (errno));
+        g_free (path);
+        return;
+    }
     g_free (path);
 
-    g_unlink (ibus_get_socket_path ());
+    errno = 0;
+    if (g_unlink (ibus_get_socket_path ())) {
+        g_warning ("Failed to unlink %s: %s",
+                   ibus_get_socket_path (), g_strerror (errno));
+    }
     pf = fopen (ibus_get_socket_path (), "w");
     g_return_if_fail (pf != NULL);
 
diff --git a/src/ibustext.c b/src/ibustext.c
index a5e3c43b..ed0fe666 100644
--- a/src/ibustext.c
+++ b/src/ibustext.c
@@ -2,7 +2,8 @@
 /* vim:set et sts=4: */
 /* IBus - The Input Bus
  * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2008-2010 Red Hat, Inc.
+ * Copyright (C) 2011-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2008-2021 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -220,7 +221,7 @@ ibus_text_new_from_unichar (gunichar c)
     text= g_object_new (IBUS_TYPE_TEXT, NULL);
 
     text->is_static = FALSE;
-    text->text = (gchar *)g_malloc (12);
+    g_return_val_if_fail ((text->text = (gchar *)g_malloc (12)), NULL);
     len = g_unichar_to_utf8 (c, text->text);
     text->text[len] =  0;
 
diff --git a/src/ibusunicode.c b/src/ibusunicode.c
index 9e6f6b2b..f7a897d1 100644
--- a/src/ibusunicode.c
+++ b/src/ibusunicode.c
@@ -1,8 +1,8 @@
 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 /* vim:set et sts=4: */
 /* bus - The Input Bus
- * Copyright (C) 2018-2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
- * Copyright (C) 2018-2019 Red Hat, Inc.
+ * Copyright (C) 2018-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2018-2021 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -472,7 +472,12 @@ ibus_unicode_data_save (const gchar *path,
 
     dir = g_path_get_dirname (path);
     if (g_strcmp0 (dir, ".") != 0 && g_stat (dir, &buf) != 0) {
-        g_mkdir_with_parents (dir, 0777);
+        errno = 0;
+        if (g_mkdir_with_parents (dir, 0777)) {
+            g_warning ("Failed to mkdir %s: %s", dir, g_strerror (errno));
+            return;
+        }
+
     }
     g_free (dir);
     if (!g_file_set_contents (path, contents, length, &error)) {
@@ -967,7 +972,11 @@ ibus_unicode_block_save (const gchar *path,
 
     dir = g_path_get_dirname (path);
     if (g_strcmp0 (dir, ".") != 0 && g_stat (dir, &buf) != 0) {
-        g_mkdir_with_parents (dir, 0777);
+        errno = 0;
+        if (g_mkdir_with_parents (dir, 0777)) {
+            g_warning ("Failed to mkdir %s: %s", dir, g_strerror (errno));
+            return;
+        }
     }
     g_free (dir);
     if (!g_file_set_contents (path, contents, length, &error)) {
diff --git a/src/tests/ibus-compose.c b/src/tests/ibus-compose.c
index 4b4c56e7..81bfc69b 100644
--- a/src/tests/ibus-compose.c
+++ b/src/tests/ibus-compose.c
@@ -360,11 +360,13 @@ main (int argc, char *argv[])
     /* Avoid a warning of "AT-SPI: Could not obtain desktop path or name"
      * with gtk_main().
      */
-    g_setenv ("NO_AT_BRIDGE", "1", TRUE);
+    if (!g_setenv ("NO_AT_BRIDGE", "1", TRUE))
+        g_message ("Failed setenv NO_AT_BRIDGE\n");
     g_test_init (&argc, &argv, NULL);
     gtk_init (&argc, &argv);
 
-    m_srcdir = argc > 1 ? g_strdup (argv[1]) : g_strdup (".");
+    m_srcdir = (argc > 1 && strlen (argv[1]) < FILENAME_MAX)
+            ? g_strdup (argv[1]) : g_strdup (".");
     m_compose_file = g_strdup (g_getenv ("COMPOSE_FILE"));
 #if GLIB_CHECK_VERSION (2, 58, 0)
     test_name = g_get_language_names_with_category ("LC_CTYPE")[0];
diff --git a/src/tests/ibus-keypress.c b/src/tests/ibus-keypress.c
index dd1b0042..bab05398 100644
--- a/src/tests/ibus-keypress.c
+++ b/src/tests/ibus-keypress.c
@@ -291,7 +291,8 @@ main (int argc, char *argv[])
     /* Avoid a warning of "AT-SPI: Could not obtain desktop path or name"
      * with gtk_main().
      */
-    g_setenv ("NO_AT_BRIDGE", "1", TRUE);
+    if (!g_setenv ("NO_AT_BRIDGE", "1", TRUE))
+        g_message ("Failed setenv NO_AT_BRIDGE\n");
     g_test_init (&argc, &argv, NULL);
     gtk_init (&argc, &argv);
 
diff --git a/src/unicode-parser.c b/src/unicode-parser.c
index b4303ea8..2c4eb677 100644
--- a/src/unicode-parser.c
+++ b/src/unicode-parser.c
@@ -1,8 +1,8 @@
 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 /* vim:set et sts=4: */
 /* ibus - The Input Bus
- * Copyright (C) 2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
- * Copyright (C) 2018 Red Hat, Inc.
+ * Copyright (C) 2018-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2018-2021 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -76,11 +76,9 @@ unicode_data_new_object (UnicodeData *data)
             ibus_unicode_data_new ("code",
                                    data->code,
                                    "name",
-                                   data->name ? g_strdup (data->name)
-                                           : g_strdup (""),
+                                   data->name ? data->name : "",
                                    "alias",
-                                   data->alias ? g_strdup (data->alias)
-                                           : g_strdup (""),
+                                   data->alias ? data->alias : "",
                                    NULL);
     data->list = g_slist_append (data->list, unicode);
 }
@@ -98,8 +96,7 @@ unicode_block_new_object (UnicodeData *data)
                                     "end",
                                     data->end,
                                     "name",
-                                    data->name ? g_strdup (data->name)
-                                           : g_strdup (""),
+                                    data->name ? data->name : "",
                                    NULL);
     data->list = g_slist_append (data->list, block);
 }
@@ -285,7 +282,7 @@ ucd_parse_file (const gchar *filename,
                    filename, error ? error->message : "");
         goto failed_to_parse_ucd_names_list;
     }
-    head = end = content;
+    end = content;
     while (*end == '\n' && end - content < length) {
         end++;
         n++;
@@ -352,6 +349,7 @@ static void
 block_list_dump (IBusUnicodeBlock *block,
                  GString          *buff)
 {
+    gchar *line;
     g_return_if_fail (buff != NULL);
 
     g_string_append (buff, "    /* TRANSLATORS: You might refer the "         \
@@ -359,9 +357,10 @@ block_list_dump (IBusUnicodeBlock *block,
                            "                    the following command:\n"     \
                            "       msgmerge -C gucharmap.po ibus.po "         \
                            "ibus.pot */\n");
-    gchar *line = g_strdup_printf ("    N_(\"%s\"),\n",
-                                   ibus_unicode_block_get_name (block));
+    line = g_strdup_printf ("    N_(\"%s\"),\n",
+                            ibus_unicode_block_get_name (block));
     g_string_append (buff, line);
+    g_free (line);
 }
 
 static void
@@ -371,7 +370,7 @@ ucd_block_translatable_save (const gchar *filename,
     gchar *content = NULL;
     gsize length = 0;
     GError *error = NULL;
-    gchar *p;
+    gchar *p, *substr;
     GString *buff = NULL;
     int i;
     GSList *list = blocks_list;
@@ -392,25 +391,30 @@ ucd_block_translatable_save (const gchar *filename,
             break;
     }
     if (p != NULL) {
-        g_string_append (buff, g_strndup (content, p - content));
+        substr = g_strndup (content, p - content);
+        g_string_append (buff, substr);
+        g_free (substr);
         g_string_append_c (buff, '\n');
     }
     g_clear_pointer (&content, g_free);
 
-    g_string_append (buff, g_strdup ("\n"));
-    g_string_append (buff, g_strdup_printf ("/* This file is generated by %s. */", __FILE__));
-    g_string_append (buff, g_strdup ("\n"));
-    g_string_append (buff, g_strdup ("include <glib/gi18n.h>\n"));
-    g_string_append (buff, g_strdup ("\n"));
-    g_string_append (buff, g_strdup ("#ifndef __IBUS_UNICODE_GEN_H_\n"));
-    g_string_append (buff, g_strdup ("#define __IBUS_UNICODE_GEN_H_\n"));
-    g_string_append (buff, g_strdup ("const static char *unicode_blocks[] = {\n"));
+    g_string_append (buff, "\n");
+    substr = g_strdup_printf ("/* This file is generated by %s. */", __FILE__);
+    g_string_append (buff, substr);
+    g_free (substr);
+    g_string_append (buff, "\n");
+    g_string_append (buff, "include <glib/gi18n.h>\n");
+    g_string_append (buff, "\n");
+    g_string_append (buff, "#ifndef __IBUS_UNICODE_GEN_H_\n");
+    g_string_append (buff, "#define __IBUS_UNICODE_GEN_H_\n");
+    g_string_append (buff, "const static char *unicode_blocks[] = {\n");
     g_slist_foreach (list, (GFunc)block_list_dump, buff);
-    g_string_append (buff, g_strdup ("};\n"));
-    g_string_append (buff, g_strdup ("#endif\n"));
+    g_string_append (buff, "};\n");
+    g_string_append (buff, "#endif\n");
 
     if (!g_file_set_contents (filename, buff->str, -1, &error)) {
-        g_warning ("Failed to save emoji category file %s: %s", filename, error->message);
+        g_warning ("Failed to save emoji category file %s: %s",
+                   filename, error->message);
         g_error_free (error);
     }
 
diff --git a/util/IMdkit/FrameMgr.c b/util/IMdkit/FrameMgr.c
index 0e91b78e..80d019a0 100644
--- a/util/IMdkit/FrameMgr.c
+++ b/util/IMdkit/FrameMgr.c
@@ -851,7 +851,7 @@ static Bool _FrameMgrProcessPadding (FrameMgr fm, FmStatus* status)
             return True;
         }
         /*endif*/
-        next_type = FrameInstGetNextType (fm->fi, &info);
+        FrameInstGetNextType (fm->fi, &info);
         fm->idx += info.num;
         if ((fitr = _FrameIterCounterIncr (fm->iters, info.num)))
             _FrameMgrRemoveIter (fm, fitr);
@@ -1525,6 +1525,11 @@ static Iter IterInit (XimFrame frame, int count)
     register XimFrameType type;
 
     it = (Iter) Xmalloc (sizeof (IterRec));
+    if (!it) {
+        fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                 __FILE__, __LINE__);
+        return NULL;
+    }
     it->template = frame;
     it->max_count = (count == NO_VALUE)  ?  0  :  count;
     it->allow_expansion = (count == NO_VALUE);
@@ -1669,8 +1674,15 @@ static Bool IterIsLoopEnd (Iter it, Bool *myself)
 
 static XimFrameType IterGetNextType (Iter it, XimFrameTypeInfo info)
 {
-    XimFrameType type = it->template->type;
+    XimFrameType type;
+
+    if (!it || !it->template) {
+        fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                 __FILE__, __LINE__);
+	return (XimFrameType) NULL;
+    }
 
+    type = it->template->type;
     if (it->start_counter)
     {
         (*it->start_watch_proc) (it, it->client_data);
@@ -1766,7 +1778,15 @@ static XimFrameType IterGetNextType (Iter it, XimFrameTypeInfo info)
 
 static XimFrameType IterPeekNextType (Iter it, XimFrameTypeInfo info)
 {
-    XimFrameType type = it->template->type;
+    XimFrameType type;
+
+    if (!it->template) {
+        fprintf (stderr, "(XIM-IMdkit) WARNING: dereference pointer %s:%d.\n",
+                 __FILE__, __LINE__);
+        return (XimFrameType) NULL;
+    }
+
+    type = it->template->type;
 
     if (!it->allow_expansion  &&  it->cur_no >= it->max_count)
         return (EOL);
@@ -1866,6 +1886,9 @@ static FmStatus IterSetSize (Iter it, int num)
                     dr.num = NO_VALUE;
                     d = ChainMgrSetData (&it->cm, i, dr);
                 }
+                if (!d) {
+                    return FmNoMoreData;
+                }
                 /*endif*/
                 if (d->num == NO_VALUE)
                 {
@@ -2254,6 +2277,11 @@ static ExtraData ChainMgrSetData (ChainMgr cm,
                                   ExtraDataRec data)
 {
     Chain cur = (Chain) Xmalloc (sizeof (ChainRec));
+    if (!cur) {
+        fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                 __FILE__, __LINE__);
+        return NULL;
+    }
 
     cur->frame_no = frame_no;
     cur->d = data;
diff --git a/util/IMdkit/i18nIc.c b/util/IMdkit/i18nIc.c
index 289837a6..14a3dc51 100644
--- a/util/IMdkit/i18nIc.c
+++ b/util/IMdkit/i18nIc.c
@@ -470,13 +470,16 @@ static XICAttribute *CreateNestedList (CARD16 attr_id,
     /*endfor*/
     
     nest_list = (XICAttribute *) malloc (sizeof (XICAttribute));
-    if (nest_list == NULL)
+    if (nest_list == NULL) {
+        XFree (values);
         return NULL;
+    }
     /*endif*/
     memset (nest_list, 0, sizeof (XICAttribute));
     nest_list->value = (void *) malloc (value_length);
     if (nest_list->value == NULL) {
         XFree (nest_list);
+        XFree (values);
         return NULL;
     }
     /*endif*/
@@ -539,7 +542,13 @@ static int GetICValue (Xi18n i18n_core,
                     attr_ret[n].attribute_id = xic_attr[j].attribute_id;
                     attr_ret[n].name_length = xic_attr[j].length;
                     attr_ret[n].name = malloc (xic_attr[j].length + 1);
-		    strcpy(attr_ret[n].name, xic_attr[j].name);
+                    if (!attr_ret[n].name) {
+                        fprintf (stderr,
+                                 "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                                 __FILE__, __LINE__);
+                    } else {
+                        strcpy(attr_ret[n].name, xic_attr[j].name);
+                    }
                     attr_ret[n].type = xic_attr[j].type;
                     n++;
                     i++;
@@ -560,7 +569,13 @@ static int GetICValue (Xi18n i18n_core,
                 attr_ret[n].attribute_id = xic_attr[j].attribute_id;
                 attr_ret[n].name_length = xic_attr[j].length;
                 attr_ret[n].name = malloc (xic_attr[j].length + 1);
-		strcpy(attr_ret[n].name, xic_attr[j].name);
+                if (!attr_ret[n].name) {
+                    fprintf (stderr,
+                             "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                             __FILE__, __LINE__);
+                } else {
+		    strcpy(attr_ret[n].name, xic_attr[j].name);
+                }
                 attr_ret[n].type = xic_attr[j].type;
                 n++;
                 break;
@@ -700,10 +715,15 @@ void _Xi18nChangeIC (XIMS ims,
         attrib_list[attrib_num].value_length = value_length;
         FrameMgrGetToken (fm, value);
         attrib_list[attrib_num].value = (void *) malloc (value_length + 1);
-        memmove (attrib_list[attrib_num].value, value, value_length);
-	((char *)attrib_list[attrib_num].value)[value_length] = '\0';
+        if (!attrib_list[attrib_num].value) {
+            fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                     __FILE__, __LINE__);
+        } else {
+            memmove (attrib_list[attrib_num].value, value, value_length);
+            ((char *)attrib_list[attrib_num].value)[value_length] = '\0';
+            total_value_length += (value_length + 1);
+        }
         attrib_num++;
-        total_value_length += (value_length + 1);
     }
     /*endwhile*/
 
@@ -917,6 +937,12 @@ void _Xi18nGetIC (XIMS ims, IMProtocol *call_data, unsigned char *p)
     FrameMgrGetToken (fm, byte_length);
 
     attrID_list = (CARD16 *) malloc (sizeof (CARD16)*IC_SIZE);  /* bogus */
+    if (!attrID_list) {
+        fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                 __FILE__, __LINE__);
+        FrameMgrFree (fm);
+        return;
+    }
     memset (attrID_list, 0, sizeof (CARD16)*IC_SIZE);
 
     number = 0;
@@ -1026,7 +1052,7 @@ void _Xi18nGetIC (XIMS ims, IMProtocol *call_data, unsigned char *p)
     {
         _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
         XFree (attrID_list);
-        FrameMgrFree (fm);
+        goto _Xi18nGetIC_finit;
         return;
     }
     /*endif*/
@@ -1097,6 +1123,7 @@ void _Xi18nGetIC (XIMS ims, IMProtocol *call_data, unsigned char *p)
     }
     /*endfor*/
     
+_Xi18nGetIC_finit:
     if (preedit_ret)
     {
         XFree (preedit_ret->value);
diff --git a/util/IMdkit/i18nMethod.c b/util/IMdkit/i18nMethod.c
index 36dd28ac..9c44e7fe 100644
--- a/util/IMdkit/i18nMethod.c
+++ b/util/IMdkit/i18nMethod.c
@@ -166,8 +166,14 @@ static Bool GetEncodings(Xi18n i18n_core, XIMEncodings **p_encoding)
     {
         (*p_encoding)->supported_encodings[i]
             = (char *) malloc (strlen (p->supported_encodings[i]) + 1);
-        strcpy ((*p_encoding)->supported_encodings[i],
-                p->supported_encodings[i]);
+        if (!((*p_encoding)->supported_encodings[i])) {
+            fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                     __FILE__, __LINE__);
+
+        } else {
+            strcpy ((*p_encoding)->supported_encodings[i],
+                    p->supported_encodings[i]);
+        }
     }
     /*endif*/
     return True;
@@ -187,11 +193,17 @@ static char *ParseArgs (Xi18n i18n_core, int mode, XIMArg *args)
                 if (address->imvalue_mask & I18N_IM_LOCALE)
                     return IMLocale;
                 /*endif*/
+                /* address->im_locale will be released later and don't need
+                 * -Wanalyzer-malloc-leak flag in gcc 11.0.1.
+                 */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
                 address->im_locale = (char *) malloc (strlen (p->value) + 1);
                 if (!address->im_locale)
                     return IMLocale;
                 /*endif*/
                 strcpy (address->im_locale, p->value);
+#pragma GCC diagnostic pop
                 address->imvalue_mask |= I18N_IM_LOCALE;
             }
             else if (strcmp (p->name, IMServerTransport) == 0)
@@ -199,11 +211,14 @@ static char *ParseArgs (Xi18n i18n_core, int mode, XIMArg *args)
                 if (address->imvalue_mask & I18N_IM_ADDRESS)
                     return IMServerTransport;
                 /*endif*/
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
                 address->im_addr = (char *) malloc (strlen (p->value) + 1);
                 if (!address->im_addr)
                     return IMServerTransport;
                 /*endif*/
                 strcpy(address->im_addr, p->value);
+#pragma GCC diagnostic pop
                 address->imvalue_mask |= I18N_IM_ADDRESS;
             }
             else if (strcmp (p->name, IMServerName) == 0)
@@ -211,11 +226,14 @@ static char *ParseArgs (Xi18n i18n_core, int mode, XIMArg *args)
                 if (address->imvalue_mask & I18N_IM_NAME)
                     return IMServerName;
                 /*endif*/
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
                 address->im_name = (char *) malloc (strlen (p->value) + 1);
                 if (!address->im_name)
                     return IMServerName;
                 /*endif*/
                 strcpy (address->im_name, p->value);
+#pragma GCC diagnostic pop
                 address->imvalue_mask |= I18N_IM_NAME;
             }
             else if (strcmp (p->name, IMServerWindow) == 0)
@@ -698,7 +716,7 @@ static void ReturnSelectionNotify (Xi18n i18n_core, XSelectionRequestEvent *ev)
 {
     XEvent event;
     Display *dpy = i18n_core->address.dpy;
-    char buf[4096];
+    char buf[4096] = { '\0', };
 
     event.type = SelectionNotify;
     event.xselection.requestor = ev->requestor;
diff --git a/util/IMdkit/i18nOffsetCache.c b/util/IMdkit/i18nOffsetCache.c
index d5379051..e2fe8c6b 100644
--- a/util/IMdkit/i18nOffsetCache.c
+++ b/util/IMdkit/i18nOffsetCache.c
@@ -94,7 +94,7 @@ void _Xi18nSetPropertyOffset (Xi18nOffsetCache *offset_cache, Atom key,
     }
 
     assert (data != NULL);
-    if (offset_cache->size > 0) {
+    if (offset_cache->size > 0 && i < offset_cache->capacity) {
         data[i].key = key;
         data[i].offset = offset;
     }
diff --git a/util/IMdkit/i18nPtHdr.c b/util/IMdkit/i18nPtHdr.c
index eaeeee1c..8dc52714 100644
--- a/util/IMdkit/i18nPtHdr.c
+++ b/util/IMdkit/i18nPtHdr.c
@@ -181,8 +181,13 @@ static void OpenMessageProc(XIMS ims, IMProtocol *call_data, unsigned char *p)
     FrameMgrGetToken (fm, name);
     imopen->lang.length = str_length;
     imopen->lang.name = malloc (str_length + 1);
-    strncpy (imopen->lang.name, name, str_length);
-    imopen->lang.name[str_length] = (char) 0;
+    if (!imopen->lang.name) {
+        fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                 __FILE__, __LINE__);
+    } else {
+        strncpy (imopen->lang.name, name, str_length);
+        imopen->lang.name[str_length] = (char) 0;
+    }
 
     FrameMgrFree (fm);
 
@@ -339,7 +344,7 @@ static XIMExt *MakeExtensionList (Xi18n i18n_core,
                                   int number,
                                   int *reply_number)
 {
-    XIMExt *ext_list;
+    XIMExt *ext_list = NULL;
     XIMExt *im_ext = (XIMExt *) i18n_core->address.extension;
     int im_ext_len = i18n_core->address.ext_num;
     int i;
@@ -358,7 +363,8 @@ static XIMExt *MakeExtensionList (Xi18n i18n_core,
         {
             for (j = 0;  j < (int) number;  j++)
             {
-                if (strcmp (lib_extension[j].name, im_ext[i].name) == 0)
+                if (lib_extension[j].name
+                    && strcmp (lib_extension[j].name, im_ext[i].name) == 0)
                 {
                     (*reply_number)++;
                     break;
@@ -389,7 +395,13 @@ static XIMExt *MakeExtensionList (Xi18n i18n_core,
             ext_list[i].minor_opcode = im_ext[i].minor_opcode;
             ext_list[i].length = im_ext[i].length;
             ext_list[i].name = malloc (im_ext[i].length + 1);
-            strcpy (ext_list[i].name, im_ext[i].name);
+            if (!ext_list[i].name) {
+                fprintf (stderr,
+                         "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                         __FILE__, __LINE__);
+            } else {
+                strcpy (ext_list[i].name, im_ext[i].name);
+            }
         }
         /*endfor*/
     }
@@ -401,13 +413,20 @@ static XIMExt *MakeExtensionList (Xi18n i18n_core,
         {
             for (j = 0;  j < (int)number;  j++)
             {
-                if (strcmp (lib_extension[j].name, im_ext[i].name) == 0)
+                if (lib_extension[j].name
+                    && strcmp (lib_extension[j].name, im_ext[i].name) == 0)
                 {
                     ext_list[n].major_opcode = im_ext[i].major_opcode;
                     ext_list[n].minor_opcode = im_ext[i].minor_opcode;
                     ext_list[n].length = im_ext[i].length;
                     ext_list[n].name = malloc (im_ext[i].length + 1);
-                    strcpy (ext_list[n].name, im_ext[i].name);
+                    if (!ext_list[n].name) {
+                        fprintf (stderr,
+                                 "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                                 __FILE__, __LINE__);
+                    } else {
+                        strcpy (ext_list[n].name, im_ext[i].name);
+                    }
                     n++;
                     break;
                 }
@@ -450,6 +469,11 @@ static void QueryExtensionMessageProc (XIMS ims,
     FrameMgrGetToken (fm, input_method_ID);
     FrameMgrGetToken (fm, byte_length);
     query_ext->extension = (XIMStr *) malloc (sizeof (XIMStr)*10);
+    if (!query_ext->extension) {
+        fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                 __FILE__, __LINE__);
+        return;
+    }
     memset (query_ext->extension, 0, sizeof (XIMStr)*10);
     number = 0;
     while (FrameMgrIsIterLoopEnd (fm, &status) == False)
@@ -461,9 +485,20 @@ static void QueryExtensionMessageProc (XIMS ims,
         FrameMgrSetSize (fm, str_length);
         query_ext->extension[number].length = str_length;
         FrameMgrGetToken (fm, name);
+        /* I don't know why extension[number].name is detected as leak
+         * with -Wanalyzer-malloc-leak option in gcc 11.0.1.
+         */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
         query_ext->extension[number].name = malloc (str_length + 1);
-        strncpy (query_ext->extension[number].name, name, str_length);
-        query_ext->extension[number].name[str_length] = (char) 0;
+        if (!query_ext->extension[number].name) {
+            fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                     __FILE__, __LINE__);
+        } else {
+            strncpy (query_ext->extension[number].name, name, str_length);
+            query_ext->extension[number].name[str_length] = (char) 0;
+        }
+#pragma GCC diagnostic pop
         number++;
     }
     /*endwhile*/
@@ -490,6 +525,8 @@ static void QueryExtensionMessageProc (XIMS ims,
         XFree (query_ext->extension[i].name);
     /*endfor*/
     XFree (query_ext->extension);
+    if (!ext_list)
+        return;
 
     fm = FrameMgrInit (query_extension_reply_fr,
                        NULL,
@@ -501,7 +538,10 @@ static void QueryExtensionMessageProc (XIMS ims,
     /* set length of BARRAY item in ext_fr */
     for (i = 0;  i < reply_number;  i++)
     {
-        str_size = strlen (ext_list[i].name);
+        if (ext_list[i].name)
+            str_size = strlen (ext_list[i].name);
+        else
+            str_size = 0;
         FrameMgrSetSize (fm, str_size);
     }
     /*endfor*/
@@ -700,7 +740,13 @@ static XIMAttribute *MakeIMAttributeList (Xi18n i18n_core,
                                     &value_length);
                 attrib_list[list_num].value_length = value_length;
                 attrib_list[list_num].value = (void *) malloc (value_length);
-                memset(attrib_list[list_num].value, 0, value_length);
+                if (attrib_list[list_num].value) {
+                    memset(attrib_list[list_num].value, 0, value_length);
+                } else {
+                    fprintf (stderr,
+                             "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                             __FILE__, __LINE__);
+                }
                 GetIMValueFromName (i18n_core,
                                     connect_id,
                                     attrib_list[list_num].value,
@@ -737,10 +783,10 @@ static void GetIMValuesMessageProc (XIMS ims,
     register int i;
     register int j;
     int number;
-    CARD16 *im_attrID_list;
-    char **name_list;
+    CARD16 *im_attrID_list = NULL;
+    char **name_list = NULL;
     CARD16 name_number;
-    XIMAttribute *im_attribute_list;
+    XIMAttribute *im_attribute_list = NULL;
     IMGetIMValuesStruct *getim = (IMGetIMValuesStruct *)&call_data->getim;
     CARD16 connect_id = call_data->any.connect_id;
     CARD16 input_method_ID;
@@ -753,8 +799,18 @@ static void GetIMValuesMessageProc (XIMS ims,
     FrameMgrGetToken (fm, input_method_ID);
     FrameMgrGetToken (fm, byte_length);
     im_attrID_list = (CARD16 *) malloc (sizeof (CARD16)*20);
+    if (!im_attrID_list) {
+        fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                 __FILE__, __LINE__);
+        goto GetIMValuesMessageProc_finit;
+    }
     memset (im_attrID_list, 0, sizeof (CARD16)*20);
     name_list = (char **)malloc(sizeof(char *) * 20);
+    if (!name_list) {
+        fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                 __FILE__, __LINE__);
+        goto GetIMValuesMessageProc_finit;
+    }
     memset(name_list, 0, sizeof(char *) * 20);
     number = 0;
     while (FrameMgrIsIterLoopEnd (fm, &status) == False)
@@ -792,8 +848,11 @@ static void GetIMValuesMessageProc (XIMS ims,
                                              im_attrID_list,
                                              &number,
                                              &list_len);
-    if (im_attrID_list)
-        XFree (im_attrID_list);
+    if (!im_attribute_list) {
+        fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                 __FILE__, __LINE__);
+        goto GetIMValuesMessageProc_finit2;
+    }
     /*endif*/
 
     fm = FrameMgrInit (get_im_values_reply_fr,
@@ -815,11 +874,7 @@ static void GetIMValuesMessageProc (XIMS ims,
     if (!reply)
     {
         _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
-        FrameMgrFree (fm);
-        for (i = 0; i < iter_count; i++)
-            XFree(im_attribute_list[i].value);
-        XFree (im_attribute_list);
-        return;
+        goto GetIMValuesMessageProc_finit;
     }
     /*endif*/
     memset (reply, 0, total_size);
@@ -840,12 +895,18 @@ static void GetIMValuesMessageProc (XIMS ims,
                        0,
                        reply,
                        total_size);
-    FrameMgrFree (fm);
     XFree (reply);
 
-    for (i = 0; i < iter_count; i++)
-        XFree(im_attribute_list[i].value);
-    XFree (im_attribute_list);
+GetIMValuesMessageProc_finit:
+    FrameMgrFree (fm);
+GetIMValuesMessageProc_finit2:
+    if (im_attrID_list)
+        XFree (im_attrID_list);
+    if (im_attribute_list) {
+        for (i = 0; i < iter_count; i++)
+            XFree(im_attribute_list[i].value);
+        XFree (im_attribute_list);
+    }
 }
 
 static void CreateICMessageProc (XIMS ims,
@@ -1435,6 +1496,11 @@ static void EncodingNegotiatonMessageProc (XIMS ims,
     if (byte_length > 0)
     {
         enc_nego->encoding = (XIMStr *) malloc (sizeof (XIMStr)*10);
+        if (!enc_nego->encoding) {
+            fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                     __FILE__, __LINE__);
+            goto EncodingNegotiatonMessageProc_finit;
+        }
         memset (enc_nego->encoding, 0, sizeof (XIMStr)*10);
         i = 0;
         while (FrameMgrIsIterLoopEnd (fm, &status) == False)
@@ -1446,9 +1512,21 @@ static void EncodingNegotiatonMessageProc (XIMS ims,
             FrameMgrSetSize (fm, str_length);
             enc_nego->encoding[i].length = str_length;
             FrameMgrGetToken (fm, name);
+            /* I don't know why encoding[i].name is detected as leak
+             * with -Wanalyzer-malloc-leak option in gcc 11.0.1.
+             */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
             enc_nego->encoding[i].name = malloc (str_length + 1);
+            if (!(enc_nego->encoding[i].name)) {
+                fprintf (stderr,
+                         "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                         __FILE__, __LINE__);
+                goto EncodingNegotiatonMessageProc_finit;
+            }
             strncpy (enc_nego->encoding[i].name, name, str_length);
             enc_nego->encoding[i].name[str_length] = '\0';
+#pragma GCC diagnostic pop
             i++;
         }
         /*endwhile*/
@@ -1460,20 +1538,37 @@ static void EncodingNegotiatonMessageProc (XIMS ims,
     if (byte_length > 0)
     {
         enc_nego->encodinginfo = (XIMStr *) malloc (sizeof (XIMStr)*10);
+        if (!enc_nego->encodinginfo) {
+            fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                     __FILE__, __LINE__);
+            goto EncodingNegotiatonMessageProc_finit;
+        }
         memset (enc_nego->encodinginfo, 0, sizeof (XIMStr)*10);
         i = 0;
         while (FrameMgrIsIterLoopEnd (fm, &status) == False)
         {
             char *name;
             int str_length;
-            
+
             FrameMgrGetToken (fm, str_length);
             FrameMgrSetSize (fm, str_length);
             enc_nego->encodinginfo[i].length = str_length;
             FrameMgrGetToken (fm, name);
+            /* I don't know why encodinginfo[i].name is detected as leak
+             * with -Wanalyzer-malloc-leak option in gcc 11.0.1.
+             */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
             enc_nego->encodinginfo[i].name = malloc (str_length + 1);
+            if (!enc_nego->encodinginfo[i].name) {
+                fprintf (stderr,
+                         "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                         __FILE__, __LINE__);
+                goto EncodingNegotiatonMessageProc_finit;
+            }
             strncpy (enc_nego->encodinginfo[i].name, name, str_length);
             enc_nego->encodinginfo[i].name[str_length] = '\0';
+#pragma GCC diagnostic pop
             i++;
         }
         /*endwhile*/
@@ -1524,6 +1619,7 @@ static void EncodingNegotiatonMessageProc (XIMS ims,
                        total_size);
     XFree (reply);
 
+EncodingNegotiatonMessageProc_finit:
     /* free data for encoding list */
     if (enc_nego->encoding)
     {
diff --git a/util/IMdkit/i18nUtil.c b/util/IMdkit/i18nUtil.c
index 109dcdf9..c62154e7 100644
--- a/util/IMdkit/i18nUtil.c
+++ b/util/IMdkit/i18nUtil.c
@@ -46,6 +46,8 @@ _Xi18nNeedSwap (Xi18n i18n_core, CARD16 connect_id)
     CARD8 im_byteOrder = i18n_core->address.im_byteOrder;
     Xi18nClient *client = _Xi18nFindClient (i18n_core, connect_id);
 
+    if (!client)
+        return True;
     return (client->byte_order != im_byteOrder);
 }
 
@@ -67,6 +69,11 @@ Xi18nClient *_Xi18nNewClient(Xi18n i18n_core)
 	new_connect_id = ++connect_id;
     }
     /*endif*/
+    if (!client) {
+        fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                 __FILE__, __LINE__);
+        return NULL;
+    }
     memset (client, 0, sizeof (Xi18nClient));
     client->connect_id = new_connect_id;
     client->pending = (XIMPending *) NULL;
@@ -113,7 +120,14 @@ void _Xi18nDeleteClient (Xi18n i18n_core, CARD16 connect_id)
                 ccp0->next = ccp->next;
             /*endif*/
             /* put it back to free list */
+            /* gcc 11.0.1 warns dereference of NULL with
+             * -Wanalyzer-null-dereference option
+             * but target should not be NULL.
+             */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wanalyzer-null-dereference"
             target->next = i18n_core->address.free_clients;
+#pragma GCC diagnostic pop
             i18n_core->address.free_clients = target;
             return;
         }
@@ -161,6 +175,12 @@ void _Xi18nSendMessage (XIMS ims,
 
     reply_length = header_size + length;
     reply = (unsigned char *) malloc (reply_length);
+    if (!reply) {
+        _Xi18nSendMessage (ims, connect_id, XIM_ERROR, 0, 0, 0);
+        XFree (reply_hdr);
+        FrameMgrFree (fm);
+        return;
+    }
     replyp = reply;
     memmove (reply, reply_hdr, header_size);
     replyp += header_size;
diff --git a/util/IMdkit/i18nX.c b/util/IMdkit/i18nX.c
index 5e5c15fa..152fc4e8 100644
--- a/util/IMdkit/i18nX.c
+++ b/util/IMdkit/i18nX.c
@@ -58,16 +58,21 @@ static XClient *NewXClient (Xi18n i18n_core, Window new_client)
     XClient *x_client;
 
     x_client = (XClient *) malloc (sizeof (XClient));
-    x_client->client_win = new_client;
-    x_client->accept_win = XCreateSimpleWindow (dpy,
-                                                DefaultRootWindow(dpy),
-                                                0,
-                                                0,
-                                                1,
-                                                1,
-                                                1,
-                                                0,
-                                                0);
+    if (!x_client) {
+        fprintf (stderr, "(XIM-IMdkit) WARNING: malloc failed in %s:%d.\n",
+                 __FILE__, __LINE__);
+    } else {
+        x_client->client_win = new_client;
+        x_client->accept_win = XCreateSimpleWindow (dpy,
+                                                    DefaultRootWindow(dpy),
+                                                    0,
+                                                    0,
+                                                    1,
+                                                    1,
+                                                    1,
+                                                    0,
+                                                    0);
+    }
     client->trans_rec = x_client;
     return ((XClient *) x_client);
 }
@@ -219,7 +224,7 @@ static void ReadXConnectMessage (XIMS ims, XClientMessageEvent *ev)
     }
     /*endif*/
     _XRegisterFilterByType (dpy,
-                            x_client->accept_win,
+                            x_client ? x_client->accept_win : 0,
                             ClientMessage,
                             ClientMessage,
                             WaitXIMProtocol,
@@ -229,7 +234,7 @@ static void ReadXConnectMessage (XIMS ims, XClientMessageEvent *ev)
     event.xclient.window = new_client;
     event.xclient.message_type = spec->connect_request;
     event.xclient.format = 32;
-    event.xclient.data.l[0] = x_client->accept_win;
+    event.xclient.data.l[0] = x_client ? x_client->accept_win : 0;
     event.xclient.data.l[1] = major_version;
     event.xclient.data.l[2] = minor_version;
     event.xclient.data.l[3] = XCM_DATA_LIMIT;
-- 
2.28.0