emacs-diffs
[Top][All Lists]
Advanced

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

master bb417daa703: Correct local reference leaks


From: Po Lu
Subject: master bb417daa703: Correct local reference leaks
Date: Wed, 4 Oct 2023 04:35:35 -0400 (EDT)

branch: master
commit bb417daa703b0dd8871470ce53a40b16b1ca300b
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Correct local reference leaks
    
    * src/android.c (android_build_string): Accept a list of local
    references to destroy upon an allocation failure, facilitating
    the proper deallocation of local references in such situations.
    (android_browse_url): Revise for new calling convention.
    
    * src/android.h (android_build_string): Update declaration
    correspondingly.
    
    * src/androidmenu.c (android_menu_show, android_dialog_show):
    Revise for new calling convention.
    
    * src/androidselect.c (android_notifications_notify_1): Supply
    each successive local reference to android_build_string as
    notification text is being encoded.
    
    * src/androidvfs.c (android_saf_exception_check): Introduce
    absent va_end.
---
 src/android.c       | 45 +++++++++++++++++++++++++++++++++++++++------
 src/android.h       |  2 +-
 src/androidmenu.c   | 16 ++++++++--------
 src/androidselect.c | 10 ++++++----
 src/androidvfs.c    |  8 ++++++--
 5 files changed, 60 insertions(+), 21 deletions(-)

diff --git a/src/android.c b/src/android.c
index aa4033c676f..1424270e785 100644
--- a/src/android.c
+++ b/src/android.c
@@ -5593,15 +5593,20 @@ android_verify_jni_string (const char *name)
 }
 
 /* Given a Lisp string TEXT, return a local reference to an equivalent
-   Java string.  */
+   Java string.  Each argument following TEXT should be NULL or a
+   local reference that will be freed if creating the string fails,
+   whereupon memory_full will also be signaled.  */
 
 jstring
-android_build_string (Lisp_Object text)
+android_build_string (Lisp_Object text, ...)
 {
   Lisp_Object encoded;
   jstring string;
   size_t nchars;
   jchar *characters;
+  va_list ap;
+  jobject object;
+
   USE_SAFE_ALLOCA;
 
   /* Directly encode TEXT if it contains no non-ASCII characters, or
@@ -5619,9 +5624,11 @@ android_build_string (Lisp_Object text)
     {
       string = (*android_java_env)->NewStringUTF (android_java_env,
                                                  SSDATA (text));
-      android_exception_check ();
-      SAFE_FREE ();
 
+      if ((*android_java_env)->ExceptionCheck (android_java_env))
+       goto error;
+
+      SAFE_FREE ();
       return string;
     }
 
@@ -5640,10 +5647,36 @@ android_build_string (Lisp_Object text)
   string
     = (*android_java_env)->NewString (android_java_env,
                                      characters, nchars);
-  android_exception_check ();
+
+  if ((*android_java_env)->ExceptionCheck (android_java_env))
+    goto error;
 
   SAFE_FREE ();
   return string;
+
+ error:
+  /* An exception arose while creating the string.  When this
+     transpires, an assumption is made that the error was induced by
+     running out of memory.  Delete each of the local references
+     within AP.  */
+
+  va_start (ap, text);
+
+  __android_log_print (ANDROID_LOG_WARN, __func__,
+                      "Possible out of memory error. "
+                      " The Java exception follows:  ");
+  /* Describe exactly what went wrong.  */
+  (*android_java_env)->ExceptionDescribe (android_java_env);
+  (*android_java_env)->ExceptionClear (android_java_env);
+
+  /* Now remove each and every local reference provided after
+     OBJECT.  */
+
+  while ((object = va_arg (ap, jobject)))
+    ANDROID_DELETE_LOCAL_REF (object);
+
+  va_end (ap);
+  memory_full (0);
 }
 
 /* Do the same, except TEXT is constant string data in ASCII or
@@ -6154,7 +6187,7 @@ android_browse_url (Lisp_Object url, Lisp_Object send)
   Lisp_Object tem;
   const char *buffer;
 
-  string = android_build_string (url);
+  string = android_build_string (url, NULL);
   value
     = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
                                                       emacs_service,
diff --git a/src/android.h b/src/android.h
index d4605c11ad0..28d9d25930e 100644
--- a/src/android.h
+++ b/src/android.h
@@ -108,7 +108,7 @@ extern void android_set_dont_focus_on_map (android_window, 
bool);
 extern void android_set_dont_accept_focus (android_window, bool);
 
 extern int android_verify_jni_string (const char *);
-extern jstring android_build_string (Lisp_Object);
+extern jstring android_build_string (Lisp_Object, ...);
 extern jstring android_build_jstring (const char *);
 extern void android_exception_check (void);
 extern void android_exception_check_1 (jobject);
diff --git a/src/androidmenu.c b/src/androidmenu.c
index ed26bdafa85..1f4d91b527d 100644
--- a/src/androidmenu.c
+++ b/src/androidmenu.c
@@ -278,7 +278,7 @@ android_menu_show (struct frame *f, int x, int y, int 
menuflags,
 
   title_string = NULL;
   if (STRINGP (title) && menu_items_n_panes < 2)
-    title_string = android_build_string (title);
+    title_string = android_build_string (title, NULL);
 
   /* Push the first local frame for the context menu.  */
   method = menu_class.create_context_menu;
@@ -370,7 +370,7 @@ android_menu_show (struct frame *f, int x, int y, int 
menuflags,
            pane_name = Fsubstring (pane_name, make_fixnum (1), Qnil);
 
          /* Add the pane.  */
-         temp = android_build_string (pane_name);
+         temp = android_build_string (pane_name, NULL);
          android_exception_check ();
 
          (*env)->CallNonvirtualVoidMethod (env, current_context_menu,
@@ -399,7 +399,7 @@ android_menu_show (struct frame *f, int x, int y, int 
menuflags,
            {
              /* This is a submenu.  Add it.  */
              title_string = (!NILP (item_name)
-                             ? android_build_string (item_name)
+                             ? android_build_string (item_name, NULL)
                              : NULL);
              help_string = NULL;
 
@@ -408,7 +408,7 @@ android_menu_show (struct frame *f, int x, int y, int 
menuflags,
 
              if (android_get_current_api_level () >= 26
                  && STRINGP (help))
-               help_string = android_build_string (help);
+               help_string = android_build_string (help, NULL);
 
              store = current_context_menu;
              current_context_menu
@@ -443,7 +443,7 @@ android_menu_show (struct frame *f, int x, int y, int 
menuflags,
              /* Add this menu item with the appropriate state.  */
 
              title_string = (!NILP (item_name)
-                             ? android_build_string (item_name)
+                             ? android_build_string (item_name, NULL)
                              : NULL);
              help_string = NULL;
 
@@ -452,7 +452,7 @@ android_menu_show (struct frame *f, int x, int y, int 
menuflags,
 
              if (android_get_current_api_level () >= 26
                  && STRINGP (help))
-               help_string = android_build_string (help);
+               help_string = android_build_string (help, NULL);
 
              /* Determine whether or not to display a check box.  */
 
@@ -686,7 +686,7 @@ android_dialog_show (struct frame *f, Lisp_Object title,
                 : android_build_jstring ("Question"));
 
   /* And the title.  */
-  java_title = android_build_string (title);
+  java_title = android_build_string (title, NULL);
 
   /* Now create the dialog.  */
   method = dialog_class.create_dialog;
@@ -738,7 +738,7 @@ android_dialog_show (struct frame *f, Lisp_Object title,
            }
 
          /* Add the button.  */
-         temp = android_build_string (item_name);
+         temp = android_build_string (item_name, NULL);
          (*env)->CallNonvirtualVoidMethod (env, dialog,
                                            dialog_class.class,
                                            dialog_class.add_button,
diff --git a/src/androidselect.c b/src/androidselect.c
index cf2265d4cf4..3f025351093 100644
--- a/src/androidselect.c
+++ b/src/androidselect.c
@@ -613,10 +613,12 @@ android_notifications_notify_1 (Lisp_Object title, 
Lisp_Object body,
           (long int) (boot_time.tv_sec / 2), id);
 
   /* Encode all strings into their Java counterparts.  */
-  title1 = android_build_string (title);
-  body1  = android_build_string (body);
-  group1 = android_build_string (group);
-  identifier1 = android_build_jstring (identifier);
+  title1 = android_build_string (title, NULL);
+  body1  = android_build_string (body, title1, NULL);
+  group1 = android_build_string (group, body1, title1, NULL);
+  identifier1
+    = (*android_java_env)->NewStringUTF (android_java_env, identifier);
+  android_exception_check_3 (title1, body1, group1);
 
   /* Create the notification.  */
   notification
diff --git a/src/androidvfs.c b/src/androidvfs.c
index 0e5bbf8a13e..94c5d35ed2c 100644
--- a/src/androidvfs.c
+++ b/src/androidvfs.c
@@ -3995,8 +3995,11 @@ android_saf_exception_check (int n, ...)
   /* First, check for an exception.  */
 
   if (!(*env)->ExceptionCheck (env))
-    /* No exception has taken place.  Return 0.  */
-    return 0;
+    {
+      /* No exception has taken place.  Return 0.  */
+      va_end (ap);
+      return 0;
+    }
 
   /* Print the exception.  */
   (*env)->ExceptionDescribe (env);
@@ -4045,6 +4048,7 @@ android_saf_exception_check (int n, ...)
   /* expression is still a local reference! */
   ANDROID_DELETE_LOCAL_REF ((jobject) exception);
   errno = new_errno;
+  va_end (ap);
   return 1;
 }
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]