aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMattias EngdegÄrd2020-08-18 12:58:12 +0200
committerMattias EngdegÄrd2020-08-20 19:39:14 +0200
commitbf60338d6dd02b4d848229878c8e14182f6f861f (patch)
treebbeb8e4a96460f3da3b8bc44fee10a3dc3be70c8 /src
parent3b8a6ef18543cc56ed4524ac3d6a6843e818f6fb (diff)
downloademacs-bf60338d6dd02b4d848229878c8e14182f6f861f.tar.gz
emacs-bf60338d6dd02b4d848229878c8e14182f6f861f.zip
Fix NS crash on invalid frame title string (bug#42904)
Instead of blindly assuming that all Emacs strings are valid UTF-8, which they are not, use a more careful conversion going via UTF-16 which is what NSString uses internally. Unpaired surrogates will still go through to the NSString objects, but the NS libs handle them gracefully. * src/nsterm.h (EmacsString): New category. * src/nsfns.m (all_nonzero_ascii): New helper function. ([NSString stringWithLispString:]): New method. (ns_set_name_internal): Use new conversion method.
Diffstat (limited to 'src')
-rw-r--r--src/nsfns.m65
-rw-r--r--src/nsterm.h5
2 files changed, 56 insertions, 14 deletions
diff --git a/src/nsfns.m b/src/nsfns.m
index 628233ea0dd..5fca15588d0 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -401,26 +401,15 @@ ns_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
401static void 401static void
402ns_set_name_internal (struct frame *f, Lisp_Object name) 402ns_set_name_internal (struct frame *f, Lisp_Object name)
403{ 403{
404 Lisp_Object encoded_name, encoded_icon_name;
405 NSString *str;
406 NSView *view = FRAME_NS_VIEW (f); 404 NSView *view = FRAME_NS_VIEW (f);
407 405 NSString *str = [NSString stringWithLispString: name];
408
409 encoded_name = ENCODE_UTF_8 (name);
410
411 str = [NSString stringWithUTF8String: SSDATA (encoded_name)];
412
413 406
414 /* Don't change the name if it's already NAME. */ 407 /* Don't change the name if it's already NAME. */
415 if (! [[[view window] title] isEqualToString: str]) 408 if (! [[[view window] title] isEqualToString: str])
416 [[view window] setTitle: str]; 409 [[view window] setTitle: str];
417 410
418 if (!STRINGP (f->icon_name)) 411 if (STRINGP (f->icon_name))
419 encoded_icon_name = encoded_name; 412 str = [NSString stringWithLispString: f->icon_name];
420 else
421 encoded_icon_name = ENCODE_UTF_8 (f->icon_name);
422
423 str = [NSString stringWithUTF8String: SSDATA (encoded_icon_name)];
424 413
425 if ([[view window] miniwindowTitle] 414 if ([[view window] miniwindowTitle]
426 && ! [[[view window] miniwindowTitle] isEqualToString: str]) 415 && ! [[[view window] miniwindowTitle] isEqualToString: str])
@@ -3031,6 +3020,54 @@ DEFUN ("ns-show-character-palette",
3031#endif 3020#endif
3032 3021
3033 3022
3023/* Whether N bytes at STR are in the [0,127] range. */
3024static bool
3025all_nonzero_ascii (unsigned char *str, ptrdiff_t n)
3026{
3027 for (ptrdiff_t i = 0; i < n; i++)
3028 if (str[i] < 1 || str[i] > 127)
3029 return false;
3030 return true;
3031}
3032
3033@implementation NSString (EmacsString)
3034/* Make an NSString from a Lisp string. */
3035+ (NSString *)stringWithLispString:(Lisp_Object)string
3036{
3037 /* Shortcut for the common case. */
3038 if (all_nonzero_ascii (SDATA (string), SBYTES (string)))
3039 return [NSString stringWithCString: SSDATA (string)
3040 encoding: NSASCIIStringEncoding];
3041 string = string_to_multibyte (string);
3042
3043 /* Now the string is multibyte; convert to UTF-16. */
3044 unichar *chars = xmalloc (4 * SCHARS (string));
3045 unichar *d = chars;
3046 const unsigned char *s = SDATA (string);
3047 const unsigned char *end = s + SBYTES (string);
3048 while (s < end)
3049 {
3050 int c = string_char_advance (&s);
3051 /* We pass unpaired surrogates through, because they are typically
3052 handled fairly well by the NS libraries (displayed with distinct
3053 glyphs etc). */
3054 if (c <= 0xffff)
3055 *d++ = c;
3056 else if (c <= 0x10ffff)
3057 {
3058 *d++ = 0xd800 + (c & 0x3ff);
3059 *d++ = 0xdc00 + ((c - 0x10000) >> 10);
3060 }
3061 else
3062 *d++ = 0xfffd; /* Not valid for UTF-16. */
3063 }
3064 NSString *str = [NSString stringWithCharacters: chars
3065 length: d - chars];
3066 xfree (chars);
3067 return str;
3068}
3069@end
3070
3034/* ========================================================================== 3071/* ==========================================================================
3035 3072
3036 Lisp interface declaration 3073 Lisp interface declaration
diff --git a/src/nsterm.h b/src/nsterm.h
index a511fef5b98..ab868ed3442 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -361,6 +361,11 @@ typedef id instancetype;
361 361
362@end 362@end
363 363
364
365@interface NSString (EmacsString)
366+ (NSString *)stringWithLispString:(Lisp_Object)string;
367@end
368
364/* ========================================================================== 369/* ==========================================================================
365 370
366 The Emacs application 371 The Emacs application