From 313f24f18bcc0b9cd5cdea3e6727d21c6b49f250 Mon Sep 17 00:00:00 2001
From: fujiwarat <takao.fujiwara1@gmail.com>
Date: Wed, 26 Nov 2025 14:55:28 +0900
Subject: [PATCH] util/IMdkit: Fix memory leaks with fail safe

Index: util/IMdkit/i18nMethod.c
--- util/IMdkit/i18nMethod.c.orig
+++ util/IMdkit/i18nMethod.c
@@ -2,7 +2,8 @@
  
          Copyright 1994, 1995 by Sun Microsystems, Inc.
          Copyright 1993, 1994 by Hewlett-Packard Company
-         Copyright (C) 2014-2025 Red Hat, Inc.
+         Copyright (C) 2008-2025 Red Hat, Inc.
+         Copyright (C) 2018-2025 Takao Fujiwara
  
 Permission to use, copy, modify, distribute, and sell this software
 and its documentation for any purpose is hereby granted without fee,
@@ -37,6 +38,8 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFT
 #endif
 #include <X11/Xproto.h>
 #undef NEED_EVENTS
+#include <assert.h>
+
 #include "FrameMgr.h"
 #include "IMdkit.h"
 #include "Xi18n.h"
@@ -194,17 +197,18 @@ static char *ParseArgs (Xi18n i18n_core, int mode, XIM
                 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.
+                /* xi18n_setup() initialize the `address` structure with 0 and
+                 * the pointer of the `address` is not changed and
+                 * `address->imvalue_mask` should avoid the reallocation so
+                 * the `-Wanalyzer-malloc-leak` flag in GCC 11.0.1 should not
+                 * warn about leaks of CWE-401.
                  */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
-                address->im_locale = (char *) malloc (strlen (p->value) + 1);
+                assert (!address->im_locale);
+                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)
@@ -212,14 +216,12 @@ static char *ParseArgs (Xi18n i18n_core, int mode, XIM
                 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);
+                assert (!address->im_addr);
+                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)
@@ -227,14 +229,12 @@ static char *ParseArgs (Xi18n i18n_core, int mode, XIM
                 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);
+                assert (!address->im_name);
+                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)
@@ -242,7 +242,7 @@ static char *ParseArgs (Xi18n i18n_core, int mode, XIM
                 if (address->imvalue_mask & I18N_IMSERVER_WIN)
                     return IMServerWindow;
                 /*endif*/
-                address->im_window = (Window) p->value;
+                address->im_window = (Window)p->value;
                 address->imvalue_mask |= I18N_IMSERVER_WIN;
             }
             else if (strcmp (p->name, IMInputStyles) == 0)
@@ -252,19 +252,21 @@ static char *ParseArgs (Xi18n i18n_core, int mode, XIM
                 /*endif*/
                 address->input_styles.count_styles =
                     ((XIMStyles*)p->value)->count_styles;
-                address->input_styles.supported_styles =
-                    (XIMStyle *) malloc (sizeof (XIMStyle)*address->input_styles.count_styles);
-                if (address->input_styles.supported_styles == (XIMStyle *) NULL)
+                assert (!address->input_styles.supported_styles);
+                address->input_styles.supported_styles = (XIMStyle *)malloc (
+                        sizeof (XIMStyle) * address->input_styles.count_styles);
+                if (address->input_styles.supported_styles == (XIMStyle *)NULL)
                     return IMInputStyles;
                 /*endif*/
                 memmove (address->input_styles.supported_styles,
-                         ((XIMStyles *) p->value)->supported_styles,
-                         sizeof (XIMStyle)*address->input_styles.count_styles);
+                         ((XIMStyles *)p->value)->supported_styles,
+                         sizeof (XIMStyle) *
+                                 address->input_styles.count_styles);
                 address->imvalue_mask |= I18N_INPUT_STYLES;
             }
             else if (strcmp (p->name, IMProtocolHandler) == 0)
             {
-                address->improto = (IMProtoHandler) p->value;
+                address->improto = (IMProtoHandler)p->value;
                 address->imvalue_mask |= I18N_IM_HANDLER;
             }
             else if (strcmp (p->name, IMOnKeysList) == 0)
@@ -273,15 +275,16 @@ static char *ParseArgs (Xi18n i18n_core, int mode, XIM
                     return IMOnKeysList;
                 /*endif*/
                 address->on_keys.count_keys =
-                    ((XIMTriggerKeys *) p->value)->count_keys;
-                address->on_keys.keylist =
-                    (XIMTriggerKey *) malloc (sizeof (XIMTriggerKey)*address->on_keys.count_keys);
-                if (address->on_keys.keylist == (XIMTriggerKey *) NULL)
+                    ((XIMTriggerKeys *)p->value)->count_keys;
+                assert (!address->on_keys.keylist);
+                address->on_keys.keylist = (XIMTriggerKey *)malloc (
+                        sizeof (XIMTriggerKey) * address->on_keys.count_keys);
+                if (address->on_keys.keylist == (XIMTriggerKey *)NULL)
                     return IMOnKeysList;
                 /*endif*/
                 memmove (address->on_keys.keylist,
-                         ((XIMTriggerKeys *) p->value)->keylist,
-                         sizeof (XIMTriggerKey)*address->on_keys.count_keys);
+                         ((XIMTriggerKeys *)p->value)->keylist,
+                         sizeof (XIMTriggerKey) * address->on_keys.count_keys);
                 address->imvalue_mask |= I18N_ON_KEYS;
             }
             else if (strcmp (p->name, IMOffKeysList) == 0)
@@ -290,15 +293,16 @@ static char *ParseArgs (Xi18n i18n_core, int mode, XIM
                     return IMOffKeysList;
                 /*endif*/
                 address->off_keys.count_keys =
-                    ((XIMTriggerKeys *) p->value)->count_keys;
-                address->off_keys.keylist =
-                    (XIMTriggerKey *) malloc (sizeof (XIMTriggerKey)*address->off_keys.count_keys);
-                if (address->off_keys.keylist == (XIMTriggerKey *) NULL)
+                    ((XIMTriggerKeys *)p->value)->count_keys;
+                assert (!address->off_keys.keylist);
+                address->off_keys.keylist = (XIMTriggerKey *)malloc (
+                        sizeof (XIMTriggerKey) * address->off_keys.count_keys);
+                if (address->off_keys.keylist == (XIMTriggerKey *)NULL)
                     return IMOffKeysList;
                 /*endif*/
                 memmove (address->off_keys.keylist,
-                         ((XIMTriggerKeys *) p->value)->keylist,
-                         sizeof (XIMTriggerKey)*address->off_keys.count_keys);
+                         ((XIMTriggerKeys *)p->value)->keylist,
+                         sizeof (XIMTriggerKey) * address->off_keys.count_keys);
                 address->imvalue_mask |= I18N_OFF_KEYS;
             }
             else if (strcmp (p->name, IMEncodingList) == 0)
@@ -308,17 +312,19 @@ static char *ParseArgs (Xi18n i18n_core, int mode, XIM
                 /*endif*/
                 address->encoding_list.count_encodings =
                     ((XIMEncodings *) p->value)->count_encodings;
+                assert (!address->encoding_list.supported_encodings);
                 address->encoding_list.supported_encodings =
-                    (XIMEncoding *) malloc (sizeof (XIMEncoding)*address->encoding_list.count_encodings);
+                        (XIMEncoding *)malloc (sizeof (XIMEncoding) *
+                                address->encoding_list.count_encodings);
                 if (address->encoding_list.supported_encodings
-                    == (XIMEncoding *) NULL)
-                {
+                    == (XIMEncoding *)NULL) {
                     return IMEncodingList;
                 }
                 /*endif*/
                 memmove (address->encoding_list.supported_encodings,
-                         ((XIMEncodings *) p->value)->supported_encodings,
-                         sizeof (XIMEncoding)*address->encoding_list.count_encodings);
+                         ((XIMEncodings *)p->value)->supported_encodings,
+                         sizeof (XIMEncoding) *
+                                 address->encoding_list.count_encodings);
                 address->imvalue_mask |= I18N_ENCODINGS;
             }
             else if (strcmp (p->name, IMFilterEventMask) == 0)
@@ -354,30 +360,38 @@ static char *ParseArgs (Xi18n i18n_core, int mode, XIM
     {
         for (p = args;  p->name != NULL;  p++)
         {
+            register char *_p = NULL;
             if (strcmp (p->name, IMLocale) == 0)
             {
-                p->value = (char *) malloc (strlen (address->im_locale) + 1);
-                if (!p->value)
+                _p = (char *)malloc (strlen (address->im_locale) + 1);
+                /* Workaround to avoid the warning of the leak of '*p.value'
+                 * CWE-401 and -Wanalyzer-malloc-leak. Seems GCC does not
+                 * understand the `if (!p->value)` sentence.
+                 */
+                if (!_p)
                     return IMLocale;
                 /*endif*/
+                p->value = _p;
                 strcpy (p->value, address->im_locale);
             }
             else if (strcmp (p->name, IMServerTransport) == 0)
             {
-                p->value = (char *) malloc (strlen (address->im_addr) + 1);
-                if (!p->value)
+                _p = (char *)malloc (strlen (address->im_addr) + 1);
+                if (!_p)
                     return IMServerTransport;
                 /*endif*/
+                p->value = _p;
                 strcpy (p->value, address->im_addr);
             }
             else if (strcmp (p->name, IMServerName) == 0)
             {
                 if (address->imvalue_mask & I18N_IM_NAME)
                 {
-                    p->value = (char *) malloc (strlen (address->im_name) + 1);
-                    if (!p->value)
+                    _p = (char *)malloc (strlen (address->im_name) + 1);
+                    if (!_p)
                         return IMServerName;
                     /*endif*/
+                    p->value = _p;
                     strcpy (p->value, address->im_name);
                 }
                 else
