diff options
| author | Po Lu | 2023-10-04 16:33:05 +0800 |
|---|---|---|
| committer | Po Lu | 2023-10-04 16:33:05 +0800 |
| commit | bb417daa703b0dd8871470ce53a40b16b1ca300b (patch) | |
| tree | e826d39aef4b622acfdc9c77a4b581dbab447fab /src | |
| parent | fbfdd1e0e3e67f765c6dbf9f61b5f913e55e004e (diff) | |
| download | emacs-bb417daa703b0dd8871470ce53a40b16b1ca300b.tar.gz emacs-bb417daa703b0dd8871470ce53a40b16b1ca300b.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/android.c | 45 | ||||
| -rw-r--r-- | src/android.h | 2 | ||||
| -rw-r--r-- | src/androidmenu.c | 16 | ||||
| -rw-r--r-- | src/androidselect.c | 10 | ||||
| -rw-r--r-- | 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) | |||
| 5593 | } | 5593 | } |
| 5594 | 5594 | ||
| 5595 | /* Given a Lisp string TEXT, return a local reference to an equivalent | 5595 | /* Given a Lisp string TEXT, return a local reference to an equivalent |
| 5596 | Java string. */ | 5596 | Java string. Each argument following TEXT should be NULL or a |
| 5597 | local reference that will be freed if creating the string fails, | ||
| 5598 | whereupon memory_full will also be signaled. */ | ||
| 5597 | 5599 | ||
| 5598 | jstring | 5600 | jstring |
| 5599 | android_build_string (Lisp_Object text) | 5601 | android_build_string (Lisp_Object text, ...) |
| 5600 | { | 5602 | { |
| 5601 | Lisp_Object encoded; | 5603 | Lisp_Object encoded; |
| 5602 | jstring string; | 5604 | jstring string; |
| 5603 | size_t nchars; | 5605 | size_t nchars; |
| 5604 | jchar *characters; | 5606 | jchar *characters; |
| 5607 | va_list ap; | ||
| 5608 | jobject object; | ||
| 5609 | |||
| 5605 | USE_SAFE_ALLOCA; | 5610 | USE_SAFE_ALLOCA; |
| 5606 | 5611 | ||
| 5607 | /* Directly encode TEXT if it contains no non-ASCII characters, or | 5612 | /* Directly encode TEXT if it contains no non-ASCII characters, or |
| @@ -5619,9 +5624,11 @@ android_build_string (Lisp_Object text) | |||
| 5619 | { | 5624 | { |
| 5620 | string = (*android_java_env)->NewStringUTF (android_java_env, | 5625 | string = (*android_java_env)->NewStringUTF (android_java_env, |
| 5621 | SSDATA (text)); | 5626 | SSDATA (text)); |
| 5622 | android_exception_check (); | ||
| 5623 | SAFE_FREE (); | ||
| 5624 | 5627 | ||
| 5628 | if ((*android_java_env)->ExceptionCheck (android_java_env)) | ||
| 5629 | goto error; | ||
| 5630 | |||
| 5631 | SAFE_FREE (); | ||
| 5625 | return string; | 5632 | return string; |
| 5626 | } | 5633 | } |
| 5627 | 5634 | ||
| @@ -5640,10 +5647,36 @@ android_build_string (Lisp_Object text) | |||
| 5640 | string | 5647 | string |
| 5641 | = (*android_java_env)->NewString (android_java_env, | 5648 | = (*android_java_env)->NewString (android_java_env, |
| 5642 | characters, nchars); | 5649 | characters, nchars); |
| 5643 | android_exception_check (); | 5650 | |
| 5651 | if ((*android_java_env)->ExceptionCheck (android_java_env)) | ||
| 5652 | goto error; | ||
| 5644 | 5653 | ||
| 5645 | SAFE_FREE (); | 5654 | SAFE_FREE (); |
| 5646 | return string; | 5655 | return string; |
| 5656 | |||
| 5657 | error: | ||
| 5658 | /* An exception arose while creating the string. When this | ||
| 5659 | transpires, an assumption is made that the error was induced by | ||
| 5660 | running out of memory. Delete each of the local references | ||
| 5661 | within AP. */ | ||
| 5662 | |||
| 5663 | va_start (ap, text); | ||
| 5664 | |||
| 5665 | __android_log_print (ANDROID_LOG_WARN, __func__, | ||
| 5666 | "Possible out of memory error. " | ||
| 5667 | " The Java exception follows: "); | ||
| 5668 | /* Describe exactly what went wrong. */ | ||
| 5669 | (*android_java_env)->ExceptionDescribe (android_java_env); | ||
| 5670 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 5671 | |||
| 5672 | /* Now remove each and every local reference provided after | ||
| 5673 | OBJECT. */ | ||
| 5674 | |||
| 5675 | while ((object = va_arg (ap, jobject))) | ||
| 5676 | ANDROID_DELETE_LOCAL_REF (object); | ||
| 5677 | |||
| 5678 | va_end (ap); | ||
| 5679 | memory_full (0); | ||
| 5647 | } | 5680 | } |
| 5648 | 5681 | ||
| 5649 | /* Do the same, except TEXT is constant string data in ASCII or | 5682 | /* 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) | |||
| 6154 | Lisp_Object tem; | 6187 | Lisp_Object tem; |
| 6155 | const char *buffer; | 6188 | const char *buffer; |
| 6156 | 6189 | ||
| 6157 | string = android_build_string (url); | 6190 | string = android_build_string (url, NULL); |
| 6158 | value | 6191 | value |
| 6159 | = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env, | 6192 | = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env, |
| 6160 | emacs_service, | 6193 | 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); | |||
| 108 | extern void android_set_dont_accept_focus (android_window, bool); | 108 | extern void android_set_dont_accept_focus (android_window, bool); |
| 109 | 109 | ||
| 110 | extern int android_verify_jni_string (const char *); | 110 | extern int android_verify_jni_string (const char *); |
| 111 | extern jstring android_build_string (Lisp_Object); | 111 | extern jstring android_build_string (Lisp_Object, ...); |
| 112 | extern jstring android_build_jstring (const char *); | 112 | extern jstring android_build_jstring (const char *); |
| 113 | extern void android_exception_check (void); | 113 | extern void android_exception_check (void); |
| 114 | extern void android_exception_check_1 (jobject); | 114 | 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, | |||
| 278 | 278 | ||
| 279 | title_string = NULL; | 279 | title_string = NULL; |
| 280 | if (STRINGP (title) && menu_items_n_panes < 2) | 280 | if (STRINGP (title) && menu_items_n_panes < 2) |
| 281 | title_string = android_build_string (title); | 281 | title_string = android_build_string (title, NULL); |
| 282 | 282 | ||
| 283 | /* Push the first local frame for the context menu. */ | 283 | /* Push the first local frame for the context menu. */ |
| 284 | method = menu_class.create_context_menu; | 284 | method = menu_class.create_context_menu; |
| @@ -370,7 +370,7 @@ android_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 370 | pane_name = Fsubstring (pane_name, make_fixnum (1), Qnil); | 370 | pane_name = Fsubstring (pane_name, make_fixnum (1), Qnil); |
| 371 | 371 | ||
| 372 | /* Add the pane. */ | 372 | /* Add the pane. */ |
| 373 | temp = android_build_string (pane_name); | 373 | temp = android_build_string (pane_name, NULL); |
| 374 | android_exception_check (); | 374 | android_exception_check (); |
| 375 | 375 | ||
| 376 | (*env)->CallNonvirtualVoidMethod (env, current_context_menu, | 376 | (*env)->CallNonvirtualVoidMethod (env, current_context_menu, |
| @@ -399,7 +399,7 @@ android_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 399 | { | 399 | { |
| 400 | /* This is a submenu. Add it. */ | 400 | /* This is a submenu. Add it. */ |
| 401 | title_string = (!NILP (item_name) | 401 | title_string = (!NILP (item_name) |
| 402 | ? android_build_string (item_name) | 402 | ? android_build_string (item_name, NULL) |
| 403 | : NULL); | 403 | : NULL); |
| 404 | help_string = NULL; | 404 | help_string = NULL; |
| 405 | 405 | ||
| @@ -408,7 +408,7 @@ android_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 408 | 408 | ||
| 409 | if (android_get_current_api_level () >= 26 | 409 | if (android_get_current_api_level () >= 26 |
| 410 | && STRINGP (help)) | 410 | && STRINGP (help)) |
| 411 | help_string = android_build_string (help); | 411 | help_string = android_build_string (help, NULL); |
| 412 | 412 | ||
| 413 | store = current_context_menu; | 413 | store = current_context_menu; |
| 414 | current_context_menu | 414 | current_context_menu |
| @@ -443,7 +443,7 @@ android_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 443 | /* Add this menu item with the appropriate state. */ | 443 | /* Add this menu item with the appropriate state. */ |
| 444 | 444 | ||
| 445 | title_string = (!NILP (item_name) | 445 | title_string = (!NILP (item_name) |
| 446 | ? android_build_string (item_name) | 446 | ? android_build_string (item_name, NULL) |
| 447 | : NULL); | 447 | : NULL); |
| 448 | help_string = NULL; | 448 | help_string = NULL; |
| 449 | 449 | ||
| @@ -452,7 +452,7 @@ android_menu_show (struct frame *f, int x, int y, int menuflags, | |||
| 452 | 452 | ||
| 453 | if (android_get_current_api_level () >= 26 | 453 | if (android_get_current_api_level () >= 26 |
| 454 | && STRINGP (help)) | 454 | && STRINGP (help)) |
| 455 | help_string = android_build_string (help); | 455 | help_string = android_build_string (help, NULL); |
| 456 | 456 | ||
| 457 | /* Determine whether or not to display a check box. */ | 457 | /* Determine whether or not to display a check box. */ |
| 458 | 458 | ||
| @@ -686,7 +686,7 @@ android_dialog_show (struct frame *f, Lisp_Object title, | |||
| 686 | : android_build_jstring ("Question")); | 686 | : android_build_jstring ("Question")); |
| 687 | 687 | ||
| 688 | /* And the title. */ | 688 | /* And the title. */ |
| 689 | java_title = android_build_string (title); | 689 | java_title = android_build_string (title, NULL); |
| 690 | 690 | ||
| 691 | /* Now create the dialog. */ | 691 | /* Now create the dialog. */ |
| 692 | method = dialog_class.create_dialog; | 692 | method = dialog_class.create_dialog; |
| @@ -738,7 +738,7 @@ android_dialog_show (struct frame *f, Lisp_Object title, | |||
| 738 | } | 738 | } |
| 739 | 739 | ||
| 740 | /* Add the button. */ | 740 | /* Add the button. */ |
| 741 | temp = android_build_string (item_name); | 741 | temp = android_build_string (item_name, NULL); |
| 742 | (*env)->CallNonvirtualVoidMethod (env, dialog, | 742 | (*env)->CallNonvirtualVoidMethod (env, dialog, |
| 743 | dialog_class.class, | 743 | dialog_class.class, |
| 744 | dialog_class.add_button, | 744 | 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, | |||
| 613 | (long int) (boot_time.tv_sec / 2), id); | 613 | (long int) (boot_time.tv_sec / 2), id); |
| 614 | 614 | ||
| 615 | /* Encode all strings into their Java counterparts. */ | 615 | /* Encode all strings into their Java counterparts. */ |
| 616 | title1 = android_build_string (title); | 616 | title1 = android_build_string (title, NULL); |
| 617 | body1 = android_build_string (body); | 617 | body1 = android_build_string (body, title1, NULL); |
| 618 | group1 = android_build_string (group); | 618 | group1 = android_build_string (group, body1, title1, NULL); |
| 619 | identifier1 = android_build_jstring (identifier); | 619 | identifier1 |
| 620 | = (*android_java_env)->NewStringUTF (android_java_env, identifier); | ||
| 621 | android_exception_check_3 (title1, body1, group1); | ||
| 620 | 622 | ||
| 621 | /* Create the notification. */ | 623 | /* Create the notification. */ |
| 622 | notification | 624 | 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, ...) | |||
| 3995 | /* First, check for an exception. */ | 3995 | /* First, check for an exception. */ |
| 3996 | 3996 | ||
| 3997 | if (!(*env)->ExceptionCheck (env)) | 3997 | if (!(*env)->ExceptionCheck (env)) |
| 3998 | /* No exception has taken place. Return 0. */ | 3998 | { |
| 3999 | return 0; | 3999 | /* No exception has taken place. Return 0. */ |
| 4000 | va_end (ap); | ||
| 4001 | return 0; | ||
| 4002 | } | ||
| 4000 | 4003 | ||
| 4001 | /* Print the exception. */ | 4004 | /* Print the exception. */ |
| 4002 | (*env)->ExceptionDescribe (env); | 4005 | (*env)->ExceptionDescribe (env); |
| @@ -4045,6 +4048,7 @@ android_saf_exception_check (int n, ...) | |||
| 4045 | /* expression is still a local reference! */ | 4048 | /* expression is still a local reference! */ |
| 4046 | ANDROID_DELETE_LOCAL_REF ((jobject) exception); | 4049 | ANDROID_DELETE_LOCAL_REF ((jobject) exception); |
| 4047 | errno = new_errno; | 4050 | errno = new_errno; |
| 4051 | va_end (ap); | ||
| 4048 | return 1; | 4052 | return 1; |
| 4049 | } | 4053 | } |
| 4050 | 4054 | ||