]> git.eshelyaron.com Git - emacs.git/commitdiff
Correct local reference leaks
authorPo Lu <luangruo@yahoo.com>
Wed, 4 Oct 2023 08:33:05 +0000 (16:33 +0800)
committerPo Lu <luangruo@yahoo.com>
Wed, 4 Oct 2023 08:33:05 +0000 (16:33 +0800)
* 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
src/android.h
src/androidmenu.c
src/androidselect.c
src/androidvfs.c

index aa4033c676f853d0fd78a663f42412199375d742..1424270e785846acee41824ec18158fed7543a06 100644 (file)
@@ -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,
index d4605c11ad0442d65b5fdc1e7def9345b15de59b..28d9d25930e2aa030ed1b6067dcc7dbd0b4c00ff 100644 (file)
@@ -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);
index ed26bdafa854e25154a49f7dc2cd3ba2700165f0..1f4d91b527d39cdfc8b830aaf10b2af8c46ca388 100644 (file)
@@ -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,
index cf2265d4cf4c8cec55411df900ad983367346df6..3f02535109388a7ff2ee0026e810960a172bc0cb 100644 (file)
@@ -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
index 0e5bbf8a13eaab53f097c1e05dc361692127e1ba..94c5d35ed2c2112e6a1036397fe6a3a2d1679f03 100644 (file)
@@ -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;
 }