diff options
| author | Eli Zaretskii | 2025-02-15 13:15:36 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2025-02-15 13:15:36 +0200 |
| commit | 0f768b8843bcdbbfa1c64aeee64d2de7d62c0d13 (patch) | |
| tree | 169e8c187e3df855363bf1e5ddaa4cff7b4c07c3 | |
| parent | c37e7cef42877e8222872ee6e00ecd8ab833d56b (diff) | |
| download | emacs-0f768b8843bcdbbfa1c64aeee64d2de7d62c0d13.tar.gz emacs-0f768b8843bcdbbfa1c64aeee64d2de7d62c0d13.zip | |
Prevent buffer overflow in line-numbering code
* src/xdisp.c (maybe_produce_line_number): Limit the value of
'display-line-numbers-width' to what can be shown in the window,
and set dimension of the lnum_buf[] accordingly. (Bug#75969)
| -rw-r--r-- | src/xdisp.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index c9bcafe57fd..0de5aee86dd 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -25008,7 +25008,6 @@ maybe_produce_line_number (struct it *it) | |||
| 25008 | 25008 | ||
| 25009 | /* Produce the glyphs for the line number. */ | 25009 | /* Produce the glyphs for the line number. */ |
| 25010 | struct it tem_it; | 25010 | struct it tem_it; |
| 25011 | char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1]; | ||
| 25012 | bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE; | 25011 | bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE; |
| 25013 | ptrdiff_t lnum_offset = -1; /* to produce 1-based line numbers */ | 25012 | ptrdiff_t lnum_offset = -1; /* to produce 1-based line numbers */ |
| 25014 | int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID); | 25013 | int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID); |
| @@ -25037,7 +25036,17 @@ maybe_produce_line_number (struct it *it) | |||
| 25037 | if (!it->lnum_width) | 25036 | if (!it->lnum_width) |
| 25038 | { | 25037 | { |
| 25039 | if (FIXNATP (Vdisplay_line_numbers_width)) | 25038 | if (FIXNATP (Vdisplay_line_numbers_width)) |
| 25040 | it->lnum_width = XFIXNAT (Vdisplay_line_numbers_width); | 25039 | { |
| 25040 | EMACS_INT lnum_width = XFIXNAT (Vdisplay_line_numbers_width); | ||
| 25041 | /* Limit the width to show at least 1 text character. */ | ||
| 25042 | int lnum_width_limit | ||
| 25043 | = (it->last_visible_x - it->first_visible_x) | ||
| 25044 | / FRAME_COLUMN_WIDTH (it->f) | ||
| 25045 | - 5 /* leave space for a few characters */ | ||
| 25046 | - 2; /* two spaces around the number */ | ||
| 25047 | it->lnum_width | ||
| 25048 | = clip_to_bounds (1, lnum_width, lnum_width_limit); | ||
| 25049 | } | ||
| 25041 | 25050 | ||
| 25042 | /* Max line number to be displayed cannot be more than the one | 25051 | /* Max line number to be displayed cannot be more than the one |
| 25043 | corresponding to the last row of the desired matrix. */ | 25052 | corresponding to the last row of the desired matrix. */ |
| @@ -25057,6 +25066,8 @@ maybe_produce_line_number (struct it *it) | |||
| 25057 | it->lnum_width = max (it->lnum_width, log10 (max_lnum) + 1); | 25066 | it->lnum_width = max (it->lnum_width, log10 (max_lnum) + 1); |
| 25058 | eassert (it->lnum_width > 0); | 25067 | eassert (it->lnum_width > 0); |
| 25059 | } | 25068 | } |
| 25069 | /* Extra +2 for the two blanks we add before and after the number. */ | ||
| 25070 | char *lnum_buf = alloca (it->lnum_width + 2 + 1); | ||
| 25060 | if (EQ (Vdisplay_line_numbers, Qrelative)) | 25071 | if (EQ (Vdisplay_line_numbers, Qrelative)) |
| 25061 | lnum_offset = it->pt_lnum; | 25072 | lnum_offset = it->pt_lnum; |
| 25062 | else if (EQ (Vdisplay_line_numbers, Qvisual)) | 25073 | else if (EQ (Vdisplay_line_numbers, Qvisual)) |