GNU bug report logs -
#51105
29.0.50; Buffer overflow bug in ns_compute_glyph_string_overhangs
Previous Next
Reported by: Daniel Martín <mardani29 <at> yahoo.es>
Date: Sat, 9 Oct 2021 00:31:01 UTC
Severity: normal
Tags: patch
Found in version 29.0.50
Fixed in version 29.1
Done: Lars Ingebrigtsen <larsi <at> gnus.org>
Bug is archived. No further changes may be made.
To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 51105 in the body.
You can then email your comments to 51105 AT debbugs.gnu.org in the normal way.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#51105
; Package
emacs
.
(Sat, 09 Oct 2021 00:31:02 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Daniel Martín <mardani29 <at> yahoo.es>
:
New bug report received and forwarded. Copy sent to
bug-gnu-emacs <at> gnu.org
.
(Sat, 09 Oct 2021 00:31:02 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
There is a buffer overflow bug in the function
ns_compute_glyph_string_overhangs with some particular information
received from the display engine.
(I haven't reduced the test case yet so you may not reproduce the
issue with the following recipe.)
emacs -Q
Attach a debugger to the Emacs process and add the following
conditional breakpoint:
br set -f nsterm.m -l 2853 -c 's->nchars==0'
Continue running Emacs
M-x eww RET wikipedia.org RET
The debugger will stop with the following backtrace:
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x000000010e25a20e emacs`ns_compute_glyph_string_overhangs(s=0x00007ffee232ef40) at nsterm.m:2853:7
frame #1: 0x000000010da4cbdf emacs`draw_glyphs(w=0x00006210000ac130, x=66, row=0x000062b00029ae00, area=TEXT_AREA, start=0, end=12, hl=DRAW_NORMAL_TEXT, overlaps=0) at xdisp.c:29036:4
frame #2: 0x000000010da49bd0 emacs`gui_write_glyphs(w=0x00006210000ac130, updated_row=0x000062b00029ae00, start=0x0000629001be4200, updated_area=TEXT_AREA, len=12) at xdisp.c:31179:7
frame #3: 0x000000010d90bc4d emacs`update_text_area(w=0x00006210000ac130, updated_row=0x000062b00029ae00, vpos=28) at dispnew.c:3934:2
frame #4: 0x000000010d902191 emacs`update_window_line(w=0x00006210000ac130, vpos=28, mouse_face_overwritten_p=0x00007ffee2331720) at dispnew.c:4177:11
frame #5: 0x000000010d8d84f7 emacs`update_window(w=0x00006210000ac130, force_p=true) at dispnew.c:3680:19
frame #6: 0x000000010d8d9bbc emacs`update_window_tree(w=0x00006210000ac130, force_p=true) at dispnew.c:3405:14
frame #7: 0x000000010d8d67e6 emacs`update_frame(f=0x00006210000ad530, force_p=true, inhibit_hairy_id_p=false) at dispnew.c:3240:18
frame #8: 0x000000010d9db568 emacs`redisplay_internal at xdisp.c:16160:16
frame #9: 0x000000010d9eb0a9 emacs`redisplay_preserve_echo_area(from_where=12) at xdisp.c:16429:7
frame #10: 0x000000010e0cb8e1 emacs`wait_reading_process_output(time_limit=0, nsecs=0, read_kbd=-1, do_display=true, wait_for_cell=0x0000000000000000, wait_proc=0x0000000000000000, just_wait_proc=0) at process.c:5789:7
frame #11: 0x000000010dd99c82 emacs`kbd_buffer_get_event(kbp=0x00007ffee23371c0, used_mouse_menu=0x00007ffee23386c0, end_time=0x0000000000000000) at keyboard.c:3924:4
frame #12: 0x000000010dd9825e emacs`read_event_from_main_queue(end_time=0x0000000000000000, local_getcjmp=0x00007ffee2338300, used_mouse_menu=0x00007ffee23386c0) at keyboard.c:2198:7
frame #13: 0x000000010dd6a19a emacs`read_decoded_event_from_main_queue(end_time=0x0000000000000000, local_getcjmp=0x00007ffee2338300, prev_event=0x0000000000000000, used_mouse_menu=0x00007ffee23386c0) at keyboard.c:2262:11
frame #14: 0x000000010dd632c8 emacs`read_char(commandflag=1, map=0x00006290003eb8a3, prev_event=0x0000000000000000, used_mouse_menu=0x00007ffee23386c0, end_time=0x0000000000000000) at keyboard.c:2892:11
frame #15: 0x000000010dd58e1d emacs`read_key_sequence(keybuf=0x00007ffee23393a0, prompt=0x0000000000000000, dont_downcase_last=false, can_return_switch_frame=true, fix_current_buffer=true, prevent_redisplay=false) at keyboard.c:9619:12
frame #16: 0x000000010dd539f3 emacs`command_loop_1 at keyboard.c:1392:15
frame #17: 0x000000010dfa45d9 emacs`internal_condition_case(bfun=(emacs`command_loop_1 at keyboard.c:1278), handlers=0x0000000000000090, hfun=(emacs`cmd_error at keyboard.c:936)) at eval.c:1453:25
frame #18: 0x000000010dd52903 emacs`command_loop_2(handlers=0x0000000000000090) at keyboard.c:1133:11
frame #19: 0x000000010dfa2ff9 emacs`internal_catch(tag=0x000000000000df80, func=(emacs`command_loop_2 at keyboard.c:1129), arg=0x0000000000000090) at eval.c:1184:25
frame #20: 0x000000010dd50f81 emacs`command_loop at keyboard.c:1111:2
frame #21: 0x000000010dd50c9b emacs`recursive_edit_1 at keyboard.c:720:9
frame #22: 0x000000010dd5147a emacs`Frecursive_edit at keyboard.c:803:3
frame #23: 0x000000010dd4a05a emacs`main(argc=2, argv=0x00007ffee233a310) at emacs.c:2310:3
frame #24: 0x00007fff20496f3d libdyld.dylib`start + 1
This line in nsterm.m will be executed and is problematic:
codes[1] = *(s->char2b + s->nchars - 1);
When s->nchars is 0, the code will reference one position before
s->char2b.
I have two questions:
1) Is there any reason the function chooses the first and last glyphs
instead of passing the whole glyph string and rely on text_extents to
perfom boundary checks? That is, I propose:
diff --git a/src/nsterm.m b/src/nsterm.m
index a6c2e7505b..207da60481 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -2853,11 +2853,7 @@ Hide the window (X11 semantics)
if (s->char2b)
{
struct font_metrics metrics;
- unsigned int codes[2];
- codes[0] = *(s->char2b);
- codes[1] = *(s->char2b + s->nchars - 1);
-
- font->driver->text_extents (font, codes, 2, &metrics);
+ font->driver->text_extents (font, s->char2b, s->nchars, &metrics);
s->left_overhang = -metrics.lbearing;
s->right_overhang
= metrics.rbearing > metrics.width
This way to call the text_extents API is also implemented in w32term.c
and xterm.c.
2) The root cause of the issue may be that s->nchars is 0 when it
shouldn't. Is there any legitimate scenario where the display engine
may call this routine with s->nchars equal to 0? If so, what are those
situations?
In GNU Emacs 29.0.50 (build 1, x86_64-apple-darwin20.6.0, NS appkit-2022.60 Version 11.6 (Build 20G165))
of 2021-10-09 built on Daniels-MacBook-Pro.local
Repository revision: 36d7c4af7c83c4f3ea9ab9fdd0822b986564d78e
Repository branch: master
Windowing system distributor 'Apple', version 10.3.2022
System Description: macOS 11.6
Configured using:
'configure 'CFLAGS=-O0 -g3''
Configured features:
ACL DBUS GIF GLIB GMP GNUTLS JPEG JSON LCMS2 LIBXML2 MODULES NOTIFY
KQUEUE NS PDUMPER PNG RSVG THREADS TIFF TOOLKIT_SCROLL_BARS XIM ZLIB
Important settings:
value of $LANG: en_US.UTF-8
locale-coding-system: utf-8-unix
Major mode: Lisp Interaction
Minor modes in effect:
tooltip-mode: t
global-eldoc-mode: t
eldoc-mode: t
show-paren-mode: t
electric-indent-mode: t
mouse-wheel-mode: t
tool-bar-mode: t
menu-bar-mode: t
file-name-shadow-mode: t
global-font-lock-mode: t
font-lock-mode: t
blink-cursor-mode: t
auto-composition-mode: t
auto-encryption-mode: t
auto-compression-mode: t
line-number-mode: t
indent-tabs-mode: t
transient-mark-mode: t
Load-path shadows:
None found.
Features:
(shadow sort mail-extr emacsbug message rmc puny dired dired-loaddefs
rfc822 mml mml-sec epa derived epg rfc6068 epg-config gnus-util rmail
rmail-loaddefs auth-source cl-seq eieio eieio-core cl-macs
eieio-loaddefs password-cache json map text-property-search time-date
seq gv subr-x byte-opt bytecomp byte-compile cconv mm-decode mm-bodies
mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader cl-loaddefs
cl-lib sendmail rfc2047 rfc2045 ietf-drums mm-util mail-prsvr mail-utils
iso-transl tooltip eldoc paren electric uniquify ediff-hook vc-hooks
lisp-float-type elisp-mode mwheel term/ns-win ns-win ucs-normalize
mule-util term/common-win tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode lisp-mode prog-mode register
page tab-bar menu-bar rfn-eshadow isearch easymenu timer select
scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors
frame minibuffer cl-generic cham georgian utf-8-lang misc-lang
vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932
hebrew greek romanian slovak czech european ethiopic indian cyrillic
chinese composite emoji-zwj charscript charprop case-table epa-hook
jka-cmpr-hook help simple abbrev obarray cl-preloaded nadvice button
loaddefs faces cus-face macroexp files window text-properties overlay
sha1 md5 base64 format env code-pages mule custom widget
hashtable-print-readable backquote threads dbusbind kqueue cocoa ns
lcms2 multi-tty make-network-process emacs)
Memory information:
((conses 16 49678 8809)
(symbols 48 6572 1)
(strings 32 17870 1691)
(string-bytes 1 591830)
(vectors 16 12905)
(vector-slots 8 177066 9811)
(floats 8 21 51)
(intervals 56 191 0)
(buffers 992 10))
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#51105
; Package
emacs
.
(Sat, 09 Oct 2021 06:41:01 GMT)
Full text and
rfc822 format available.
Message #8 received at 51105 <at> debbugs.gnu.org (full text, mbox):
> Date: Sat, 09 Oct 2021 02:30:33 +0200
> From: Daniel Martín via "Bug reports for GNU Emacs,
> the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
>
> 2) The root cause of the issue may be that s->nchars is 0 when it
> shouldn't. Is there any legitimate scenario where the display engine
> may call this routine with s->nchars equal to 0? If so, what are those
> situations?
I think if the glyph string has composition glyphs, nchars can be
zero. What is the value of s->first_glyph->type in the case where it
happens?
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#51105
; Package
emacs
.
(Sat, 09 Oct 2021 10:07:01 GMT)
Full text and
rfc822 format available.
Message #11 received at 51105 <at> debbugs.gnu.org (full text, mbox):
Eli Zaretskii <eliz <at> gnu.org> writes:
>> Date: Sat, 09 Oct 2021 02:30:33 +0200
>> From: Daniel Martín via "Bug reports for GNU Emacs,
>> the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
>>
>> 2) The root cause of the issue may be that s->nchars is 0 when it
>> shouldn't. Is there any legitimate scenario where the display engine
>> may call this routine with s->nchars equal to 0? If so, what are those
>> situations?
>
> I think if the glyph string has composition glyphs, nchars can be
> zero. What is the value of s->first_glyph->type in the case where it
> happens?
Yep, it seems so:
(lldb) fr v s->first_glyph->type
(unsigned int:3) s->first_glyph->type = 1
I've found a 2006 commit that seemed to handle this particular pointer
arithmetic logic for when the type of the first glyph is STRETCH_GLYPH:
https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=825de9a1027073beaec38ab1572e9d954f8a1eb0
Now I think that the right thing to do may be to modify nsterm.m, switch
on the glyph type and, if the glyph type is COMPOSITE_GLYPH, call
composition_gstring_width to get the glyph metrics. Function
composition_gstring_width uses the values from fields s->cmp_from and
s->cmp_to, and would avoid the buffer overflow:
(lldb) fr v s->cmp_from
(int) s->cmp_from = 6
(lldb) fr v s->cmp_to
(int) s->cmp_to = 7
WDYT? I can prepare a patch of this type if you agree.
I'll try to get the sequence of codepoints from the glyph string in the
debugger, so we can have a reduced test case (ie. the exact string from
the Wikipedia's front page that causes the issue).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#51105
; Package
emacs
.
(Sat, 09 Oct 2021 11:44:01 GMT)
Full text and
rfc822 format available.
Message #14 received at 51105 <at> debbugs.gnu.org (full text, mbox):
> From: Daniel Martín <mardani29 <at> yahoo.es>
> Cc: 51105 <at> debbugs.gnu.org
> Date: Sat, 09 Oct 2021 12:06:36 +0200
>
> Now I think that the right thing to do may be to modify nsterm.m, switch
> on the glyph type and, if the glyph type is COMPOSITE_GLYPH, call
> composition_gstring_width to get the glyph metrics. Function
> composition_gstring_width uses the values from fields s->cmp_from and
> s->cmp_to, and would avoid the buffer overflow:
>
> (lldb) fr v s->cmp_from
> (int) s->cmp_from = 6
> (lldb) fr v s->cmp_to
> (int) s->cmp_to = 7
>
> WDYT? I can prepare a patch of this type if you agree.
SGTM, but I'd like to hear Alan's opinion as well, as I don't feel I
know enough about the NS display backend.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#51105
; Package
emacs
.
(Sat, 09 Oct 2021 13:58:01 GMT)
Full text and
rfc822 format available.
Message #17 received at 51105 <at> debbugs.gnu.org (full text, mbox):
On Sat, Oct 09, 2021 at 02:43:18PM +0300, Eli Zaretskii wrote:
> > From: Daniel Martín <mardani29 <at> yahoo.es>
> > Cc: 51105 <at> debbugs.gnu.org
> > Date: Sat, 09 Oct 2021 12:06:36 +0200
> >
> > Now I think that the right thing to do may be to modify nsterm.m, switch
> > on the glyph type and, if the glyph type is COMPOSITE_GLYPH, call
> > composition_gstring_width to get the glyph metrics. Function
> > composition_gstring_width uses the values from fields s->cmp_from and
> > s->cmp_to, and would avoid the buffer overflow:
> >
> > (lldb) fr v s->cmp_from
> > (int) s->cmp_from = 6
> > (lldb) fr v s->cmp_to
> > (int) s->cmp_to = 7
> >
> > WDYT? I can prepare a patch of this type if you agree.
>
> SGTM, but I'd like to hear Alan's opinion as well, as I don't feel I
> know enough about the NS display backend.
I don't know much about this part of the code, but it sounds good to
me too.
--
Alan Third
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#51105
; Package
emacs
.
(Sat, 09 Oct 2021 19:36:02 GMT)
Full text and
rfc822 format available.
Message #20 received at 51105 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Alan Third <alan <at> idiocy.org> writes:
> On Sat, Oct 09, 2021 at 02:43:18PM +0300, Eli Zaretskii wrote:
>> > From: Daniel Martín <mardani29 <at> yahoo.es>
>> > Cc: 51105 <at> debbugs.gnu.org
>> > Date: Sat, 09 Oct 2021 12:06:36 +0200
>> >
>> > Now I think that the right thing to do may be to modify nsterm.m, switch
>> > on the glyph type and, if the glyph type is COMPOSITE_GLYPH, call
>> > composition_gstring_width to get the glyph metrics. Function
>> > composition_gstring_width uses the values from fields s->cmp_from and
>> > s->cmp_to, and would avoid the buffer overflow:
>> >
>> > (lldb) fr v s->cmp_from
>> > (int) s->cmp_from = 6
>> > (lldb) fr v s->cmp_to
>> > (int) s->cmp_to = 7
>> >
>> > WDYT? I can prepare a patch of this type if you agree.
>>
>> SGTM, but I'd like to hear Alan's opinion as well, as I don't feel I
>> know enough about the NS display backend.
>
> I don't know much about this part of the code, but it sounds good to
> me too.
A reduced test case to reproduce the problem is to paste "العربية" in the
*scratch* buffer.
I've attached a patch that fixes the issue.
[0001-Fix-buffer-overflow-in-ns_compute_glyph_string_overh.patch (text/x-patch, attachment)]
[Message part 3 (text/plain, inline)]
Let me know if you like it and please install it on my behalf if so.
Thanks.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#51105
; Package
emacs
.
(Sat, 09 Oct 2021 19:43:02 GMT)
Full text and
rfc822 format available.
Message #23 received at submit <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Daniel Martín via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs <at> gnu.org> writes:
>
> A reduced test case to reproduce the problem is to paste "العربية" in the
> *scratch* buffer.
>
> I've attached a patch that fixes the issue.
>
>
>
> Let me know if you like it and please install it on my behalf if so.
> Thanks.
Sorry, there was an indentation problem in the previous patch. Here's
an updated one.
[0001-Fix-buffer-overflow-in-ns_compute_glyph_string_overh.patch (text/x-patch, attachment)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#51105
; Package
emacs
.
(Sat, 09 Oct 2021 19:43:02 GMT)
Full text and
rfc822 format available.
Added tag(s) patch.
Request was from
Stefan Kangas <stefan <at> marxist.se>
to
control <at> debbugs.gnu.org
.
(Mon, 11 Oct 2021 14:19:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#51105
; Package
emacs
.
(Fri, 05 Nov 2021 02:40:02 GMT)
Full text and
rfc822 format available.
Message #31 received at 51105 <at> debbugs.gnu.org (full text, mbox):
Daniel Martín <mardani29 <at> yahoo.es> writes:
> Sorry, there was an indentation problem in the previous patch. Here's
> an updated one.
It seemed like Alan agreed with the fix, and I tested it now on my M1
Apple laptop, and it didn't break anything obvious, so I've now pushed
Daniel's patch to the trunk.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
bug marked as fixed in version 29.1, send any further explanations to
51105 <at> debbugs.gnu.org and Daniel Martín <mardani29 <at> yahoo.es>
Request was from
Lars Ingebrigtsen <larsi <at> gnus.org>
to
control <at> debbugs.gnu.org
.
(Fri, 05 Nov 2021 02:40:03 GMT)
Full text and
rfc822 format available.
bug archived.
Request was from
Debbugs Internal Request <help-debbugs <at> gnu.org>
to
internal_control <at> debbugs.gnu.org
.
(Fri, 03 Dec 2021 12:24:05 GMT)
Full text and
rfc822 format available.
This bug report was last modified 2 years and 144 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.