Revert "patches: add 0009 resource safety hardening + update 0007/0008"

This reverts commit acc2a2985e.
This commit is contained in:
Martin Sukany
2026-02-28 19:05:02 +01:00
parent acc2a2985e
commit 98b3d04597
3 changed files with 26 additions and 179 deletions

View File

@@ -1,7 +1,7 @@
From 8712cf8f567f3b0c02cc70a93aff931faa3a2df3 Mon Sep 17 00:00:00 2001
From 6e907a1000a8b138976d6a906e40449fdf1a61c5 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 14:46:25 +0100
Subject: [PATCH 1/3] ns: announce overlay completion candidates for VoiceOver
Subject: [PATCH 1/2] ns: announce overlay completion candidates for VoiceOver
Completion frameworks such as Vertico, Ivy, and Icomplete render
candidates via overlay before-string/after-string properties rather
@@ -52,8 +52,8 @@ Independent overlay branch, BUF_CHARS_MODIFF gating, candidate
announcement with overlay Zoom rect storage.
---
src/nsterm.h | 3 +
src/nsterm.m | 333 +++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 300 insertions(+), 36 deletions(-)
src/nsterm.m | 331 +++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 298 insertions(+), 36 deletions(-)
diff --git a/src/nsterm.h b/src/nsterm.h
index 51c30ca..5c15639 100644
@@ -77,7 +77,7 @@ index 51c30ca..5c15639 100644
BOOL font_panel_active;
NSFont *font_panel_result;
diff --git a/src/nsterm.m b/src/nsterm.m
index 1780194..c1fc3cb 100644
index 1780194..143e784 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -3258,7 +3258,12 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
@@ -403,7 +403,7 @@ index 1780194..c1fc3cb 100644
self.cachedPoint = point;
NSDictionary *change = @{
@@ -8789,16 +8938,128 @@ ns_ax_completion_text_for_span (EmacsAccessibilityBuffer *elem,
@@ -8789,16 +8938,126 @@ ns_ax_completion_text_for_span (EmacsAccessibilityBuffer *elem,
BOOL markActive = !NILP (BVAR (b, mark_active));
/* --- Text changed (edit) --- */
@@ -428,7 +428,6 @@ index 1780194..c1fc3cb 100644
+ if (chars_modiff != self.cachedCharsModiff)
+ {
+ self.cachedCharsModiff = chars_modiff;
+ if (self.emacsView)
+ self.emacsView->overlayZoomActive = NO;
+ [self postTextChangedNotification:point];
+ textDidChange = YES;
@@ -517,7 +516,6 @@ index 1780194..c1fc3cb 100644
+ (minibuffer exit, C-g, etc.) or overlay has no
+ recognizable selection face. Return Zoom to the
+ text cursor. */
+ if (self.emacsView)
+ self.emacsView->overlayZoomActive = NO;
+ }
}
@@ -536,7 +534,7 @@ index 1780194..c1fc3cb 100644
{
ptrdiff_t oldPoint = self.cachedPoint;
BOOL oldMarkActive = self.cachedMarkActive;
@@ -8966,7 +9227,7 @@ ns_ax_completion_text_for_span (EmacsAccessibilityBuffer *elem,
@@ -8966,7 +9225,7 @@ ns_ax_completion_text_for_span (EmacsAccessibilityBuffer *elem,
/* ===================================================================
@@ -545,7 +543,7 @@ index 1780194..c1fc3cb 100644
=================================================================== */
/* Scan visible range of window W for interactive spans.
@@ -9157,7 +9418,7 @@ ns_ax_scan_interactive_spans (struct window *w,
@@ -9157,7 +9416,7 @@ ns_ax_scan_interactive_spans (struct window *w,
- (BOOL) isAccessibilityFocused
{
/* Read the cached point stored by EmacsAccessibilityBuffer on the main
@@ -554,7 +552,7 @@ index 1780194..c1fc3cb 100644
EmacsAccessibilityBuffer *pb = self.parentBuffer;
if (!pb)
return NO;
@@ -9174,7 +9435,7 @@ ns_ax_scan_interactive_spans (struct window *w,
@@ -9174,7 +9433,7 @@ ns_ax_scan_interactive_spans (struct window *w,
dispatch_async (dispatch_get_main_queue (), ^{
/* lwin is a Lisp_Object captured by value. This is GC-safe
because Lisp_Objects are tagged integers/pointers that
@@ -563,7 +561,7 @@ index 1780194..c1fc3cb 100644
Emacs. The WINDOW_LIVE_P check below guards against the
window being deleted between capture and execution. */
if (!WINDOWP (lwin) || NILP (Fwindow_live_p (lwin)))
@@ -9200,7 +9461,7 @@ ns_ax_scan_interactive_spans (struct window *w,
@@ -9200,7 +9459,7 @@ ns_ax_scan_interactive_spans (struct window *w,
@end
@@ -572,7 +570,7 @@ index 1780194..c1fc3cb 100644
Methods are kept here (same .m file) so they access the ivars
declared in the @interface ivar block. */
@implementation EmacsAccessibilityBuffer (InteractiveSpans)
@@ -11922,7 +12183,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
@@ -11922,7 +12181,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
if (WINDOW_LEAF_P (w))
{
@@ -581,7 +579,7 @@ index 1780194..c1fc3cb 100644
EmacsAccessibilityBuffer *elem
= [existing objectForKey:[NSValue valueWithPointer:w]];
if (!elem)
@@ -11956,7 +12217,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
@@ -11956,7 +12215,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
}
else
{
@@ -590,7 +588,7 @@ index 1780194..c1fc3cb 100644
Lisp_Object child = w->contents;
while (!NILP (child))
{
@@ -12068,7 +12329,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
@@ -12068,7 +12327,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
accessibilityUpdating = YES;
/* Detect window tree change (split, delete, new buffer). Compare
@@ -599,7 +597,7 @@ index 1780194..c1fc3cb 100644
Lisp_Object curRoot = FRAME_ROOT_WINDOW (emacsframe);
if (!EQ (curRoot, lastRootWindow))
{
@@ -12077,12 +12338,12 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
@@ -12077,12 +12336,12 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
}
/* If tree is stale, rebuild FIRST so we don't iterate freed

View File

@@ -1,7 +1,7 @@
From 7d20ec80aa0d4ca97fa789f9b85389e25d2ff719 Mon Sep 17 00:00:00 2001
From 8564e4989f5f358092bd1494c3894a42974ee6e1 Mon Sep 17 00:00:00 2001
From: Martin Sukany <martin@sukany.cz>
Date: Sat, 28 Feb 2026 16:01:29 +0100
Subject: [PATCH 2/3] ns: announce child frame completion candidates for
Subject: [PATCH 2/2] ns: announce child frame completion candidates for
VoiceOver
Completion frameworks such as Corfu, Company-box, and similar
@@ -43,8 +43,8 @@ childFrameCompletionActive flag.
refocus parent buffer element when child frame closes.
---
src/nsterm.h | 2 +
src/nsterm.m | 306 ++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 305 insertions(+), 3 deletions(-)
src/nsterm.m | 279 ++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 278 insertions(+), 3 deletions(-)
diff --git a/src/nsterm.h b/src/nsterm.h
index 5c15639..8b34300 100644
@@ -67,7 +67,7 @@ index 5c15639..8b34300 100644
@end
diff --git a/src/nsterm.m b/src/nsterm.m
index c1fc3cb..abecb4c 100644
index 143e784..da1a319 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -7066,6 +7066,110 @@ ns_ax_selected_overlay_text (struct buffer *b,
@@ -181,7 +181,7 @@ index c1fc3cb..abecb4c 100644
/* Build accessibility text for window W, skipping invisible text.
Populates *OUT_START with the buffer start charpos.
Populates *OUT_RUNS with an array of visible runs and *OUT_NRUNS
@@ -12313,6 +12417,146 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
@@ -12311,6 +12415,122 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
The existing elements carry cached state (modiff, point) from the
previous redisplay cycle. Rebuilding first would create fresh
elements with current values, making change detection impossible. */
@@ -289,30 +289,6 @@ index c1fc3cb..abecb4c 100644
+static EMACS_INT lastChildFrameModiff;
+static char *lastChildFrameCandidate;
+
+/* Child frame completion dedup state. File-scope so that
+ lastChildFrameBuffer can be staticpro'd against GC. */
+static Lisp_Object lastChildFrameBuffer;
+static EMACS_INT lastChildFrameModiff;
+static char *lastChildFrameCandidate;
+
+/* Reset the re-entrance guard when unwinding past
+ postAccessibilityUpdates due to a Lisp signal (longjmp).
+ Without this, a signal during Lisp calls (e.g. Fget_char_property
+ in overlay or child frame scanning) would leave
+ accessibilityUpdating = YES permanently, suppressing all future
+ accessibility notifications. */
+static void
+ns_ax_reset_accessibility_updating (void *view)
+{
+ ((EmacsView *)view)->accessibilityUpdating = NO;
+}
+
+/* Child frame completion dedup state. File-scope so that
+ lastChildFrameBuffer can be staticpro'd against GC. */
+static Lisp_Object lastChildFrameBuffer;
+static EMACS_INT lastChildFrameModiff;
+static char *lastChildFrameCandidate;
+
+/* Reset the re-entrance guard when unwinding past
+ postAccessibilityUpdates due to a Lisp signal (longjmp).
+ Without this, a signal during Lisp calls (e.g. Fget_char_property
@@ -328,7 +304,7 @@ index c1fc3cb..abecb4c 100644
- (void)postAccessibilityUpdates
{
NSTRACE ("[EmacsView postAccessibilityUpdates]");
@@ -12323,10 +12567,60 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
@@ -12321,10 +12541,60 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
/* Re-entrance guard: VoiceOver callbacks during notification posting
can trigger redisplay, which calls ns_update_end, which calls us
@@ -390,7 +366,7 @@ index c1fc3cb..abecb4c 100644
/* Detect window tree change (split, delete, new buffer). Compare
FRAME_ROOT_WINDOW --- if it changed, the tree structure changed. */
@@ -12357,7 +12651,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
@@ -12355,7 +12625,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
NSAccessibilityFocusedUIElementChangedNotification);
lastSelectedWindow = emacsframe->selected_window;
@@ -399,7 +375,7 @@ index c1fc3cb..abecb4c 100644
return;
}
@@ -12401,7 +12695,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
@@ -12399,7 +12669,7 @@ ns_ax_collect_windows (Lisp_Object window, EmacsView *view,
NSAccessibilityFocusedUIElementChangedNotification);
}
@@ -408,15 +384,12 @@ index c1fc3cb..abecb4c 100644
}
/* ---- Cursor position for Zoom (via accessibilityBoundsForRange:) ----
@@ -14343,6 +14637,12 @@ syms_of_nsterm (void)
@@ -14341,6 +14611,9 @@ syms_of_nsterm (void)
DEFSYM (Qns_ax_completion, "completion");
DEFSYM (Qns_ax_completions_highlight, "completions-highlight");
DEFSYM (Qns_ax_backtab, "backtab");
+
+ lastChildFrameBuffer = Qnil;
+ staticpro (&lastChildFrameBuffer);
+
+ lastChildFrameBuffer = Qnil;
+ staticpro (&lastChildFrameBuffer);
/* Qmouse_face and Qkeymap are defined in textprop.c / keymap.c. */
Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier));

View File

@@ -1,124 +0,0 @@
From 0812e650c24f90bda79368078fa0ad45c18f39d2 Mon Sep 17 00:00:00 2001
From: T <t@t>
Date: Sat, 28 Feb 2026 18:45:14 +0100
Subject: [PATCH 3/3] ns: harden VoiceOver accessibility resource safety
Fix several resource safety issues found during maintainer review:
* Announcement coalescing: add 50ms minimum interval between
AnnouncementRequested notifications to prevent VoiceOver speech
synthesizer stalls from rapid-fire high-priority interruptions
(e.g. holding C-n in a completion list).
* cachedText thread safety: return [[cachedText retain] autorelease]
from accessibilityValue to prevent use-after-free when the main
thread replaces cachedText while the AX server thread is still
using the previous value.
* EmacsView dealloc safety: nil out emacsView back-references on
all accessibility elements before releasing them. Queued
dispatch_async blocks that hold a retained element reference would
otherwise access a dangling emacsView pointer.
* Nil guards: add emacsView nil checks in accessibilityParent,
accessibilityWindow, accessibilityTopLevelUIElement, and
overlayZoomActive access sites.
* src/nsterm.m (ns_ax_post_notification_with_info): Add timestamp
coalescing for AnnouncementRequested.
(accessibilityValue): Return retained+autoreleased cachedText.
(dealloc): Nil out emacsView on all accessibility elements.
(accessibilityParent, accessibilityWindow)
(accessibilityTopLevelUIElement): Add nil guards.
---
src/nsterm.m | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/src/nsterm.m b/src/nsterm.m
index abecb4c..3724b05 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -7521,11 +7521,32 @@ ns_ax_post_notification (id element,
});
}
+/* Minimum interval between AnnouncementRequested notifications
+ (in seconds). VoiceOver can stall if overwhelmed with rapid-fire
+ high-priority announcements that each interrupt the previous
+ utterance. 50ms lets the speech synthesizer start before the
+ next interruption. */
+#define NS_AX_ANNOUNCE_MIN_INTERVAL 0.05
+
static inline void
ns_ax_post_notification_with_info (id element,
NSAccessibilityNotificationName name,
NSDictionary *info)
{
+ /* Coalesce AnnouncementRequested: skip if the previous one was
+ less than NS_AX_ANNOUNCE_MIN_INTERVAL seconds ago. Prevents
+ speech synthesizer stalls from rapid-fire high-priority
+ interruptions (e.g. holding C-n in a completion list). */
+ if ([name isEqualToString:
+ NSAccessibilityAnnouncementRequestedNotification])
+ {
+ static CFAbsoluteTime lastAnnouncementTime;
+ CFAbsoluteTime now = CFAbsoluteTimeGetCurrent ();
+ if (now - lastAnnouncementTime < NS_AX_ANNOUNCE_MIN_INTERVAL)
+ return;
+ lastAnnouncementTime = now;
+ }
+
dispatch_async (dispatch_get_main_queue (), ^{
NSAccessibilityPostNotificationWithUserInfo (element, name, info);
});
@@ -7571,16 +7592,22 @@ ns_ax_post_notification_with_info (id element,
- (id)accessibilityParent
{
+ if (!self.emacsView)
+ return nil;
return NSAccessibilityUnignoredAncestor (self.emacsView);
}
- (id)accessibilityWindow
{
+ if (!self.emacsView)
+ return nil;
return [self.emacsView window];
}
- (id)accessibilityTopLevelUIElement
{
+ if (!self.emacsView)
+ return nil;
return [self.emacsView window];
}
@@ -8143,7 +8170,7 @@ ns_ax_completion_text_for_span (EmacsAccessibilityBuffer *elem,
return result;
}
[self ensureTextCache];
- return cachedText ? cachedText : @"";
+ return cachedText ? [[cachedText retain] autorelease] : @"";
}
- (NSInteger)accessibilityNumberOfCharacters
@@ -9659,6 +9686,15 @@ ns_ax_scan_interactive_spans (struct window *w,
[layer release];
#endif
+ /* Nil out back-references before releasing elements. Queued
+ dispatch_async blocks may still hold a retained reference to
+ an element; without this they would access a dangling
+ emacsView pointer after EmacsView is freed. */
+ for (id elem in accessibilityElements)
+ {
+ if ([elem respondsToSelector:@selector (setEmacsView:)])
+ [elem setEmacsView:nil];
+ }
[accessibilityElements release];
[[self menu] release];
[super dealloc];
--
2.43.0