vim-patch:8.0.1088: occasional memory use after free

Problem:    Occasional memory use after free.
Solution:   Use the highlight table directly, don't keep a pointer.
414168d97f
This commit is contained in:
Jan Edmund Lazo 2018-07-25 23:56:08 -04:00
parent f0ca2283b0
commit 3e6d3bf3bd

View File

@ -6492,7 +6492,6 @@ void do_highlight(const char *line, const bool forceit, const bool init)
int attr; int attr;
int id; int id;
int idx; int idx;
struct hl_group *item;
struct hl_group item_before; struct hl_group item_before;
bool dodefault = false; bool dodefault = false;
bool doclear = false; bool doclear = false;
@ -6568,7 +6567,6 @@ void do_highlight(const char *line, const bool forceit, const bool init)
from_id = syn_check_group((const char_u *)from_start, from_id = syn_check_group((const char_u *)from_start,
(int)(from_end - from_start)); (int)(from_end - from_start));
item = &HL_TABLE()[from_id - 1];
if (strncmp(to_start, "NONE", 4) == 0) { if (strncmp(to_start, "NONE", 4) == 0) {
to_id = 0; to_id = 0;
} else { } else {
@ -6576,7 +6574,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
(int)(to_end - to_start)); (int)(to_end - to_start));
} }
if (from_id > 0 && (!init || item->sg_set == 0)) { if (from_id > 0 && (!init || HL_TABLE()[from_id - 1].sg_set == 0)) {
// Don't allow a link when there already is some highlighting // Don't allow a link when there already is some highlighting
// for the group, unless '!' is used // for the group, unless '!' is used
if (to_id > 0 && !forceit && !init if (to_id > 0 && !forceit && !init
@ -6584,15 +6582,15 @@ void do_highlight(const char *line, const bool forceit, const bool init)
if (sourcing_name == NULL && !dodefault) { if (sourcing_name == NULL && !dodefault) {
EMSG(_("E414: group has settings, highlight link ignored")); EMSG(_("E414: group has settings, highlight link ignored"));
} }
} else if (item->sg_link != to_id } else if (HL_TABLE()[from_id - 1].sg_link != to_id
|| item->sg_scriptID != current_SID || HL_TABLE()[from_id - 1].sg_scriptID != current_SID
|| item->sg_cleared) { || HL_TABLE()[from_id - 1].sg_cleared) {
if (!init) { if (!init) {
item->sg_set |= SG_LINK; HL_TABLE()[from_id - 1].sg_set |= SG_LINK;
} }
item->sg_link = to_id; HL_TABLE()[from_id - 1].sg_link = to_id;
item->sg_scriptID = current_SID; HL_TABLE()[from_id - 1].sg_scriptID = current_SID;
item->sg_cleared = false; HL_TABLE()[from_id - 1].sg_cleared = false;
redraw_all_later(SOME_VALID); redraw_all_later(SOME_VALID);
// Only call highlight changed() once after multiple changes // Only call highlight changed() once after multiple changes
@ -6629,7 +6627,6 @@ void do_highlight(const char *line, const bool forceit, const bool init)
return; return;
} }
idx = id - 1; // Index is ID minus one. idx = id - 1; // Index is ID minus one.
item = &HL_TABLE()[idx];
// Return if "default" was used and the group already has settings // Return if "default" was used and the group already has settings
if (dodefault && hl_has_settings(idx, true)) { if (dodefault && hl_has_settings(idx, true)) {
@ -6637,14 +6634,14 @@ void do_highlight(const char *line, const bool forceit, const bool init)
} }
// Make a copy so we can check if any attribute actually changed // Make a copy so we can check if any attribute actually changed
item_before = *item; item_before = HL_TABLE()[idx];
is_normal_group = (STRCMP(item->sg_name_u, "NORMAL") == 0); is_normal_group = (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0);
// Clear the highlighting for ":hi clear {group}" and ":hi clear". // Clear the highlighting for ":hi clear {group}" and ":hi clear".
if (doclear || (forceit && init)) { if (doclear || (forceit && init)) {
highlight_clear(idx); highlight_clear(idx);
if (!doclear) { if (!doclear) {
item->sg_set = 0; HL_TABLE()[idx].sg_set = 0;
} }
} }
@ -6670,9 +6667,9 @@ void do_highlight(const char *line, const bool forceit, const bool init)
linep = (const char *)skipwhite((const char_u *)linep); linep = (const char *)skipwhite((const char_u *)linep);
if (strcmp(key, "NONE") == 0) { if (strcmp(key, "NONE") == 0) {
if (!init || item->sg_set == 0) { if (!init || HL_TABLE()[idx].sg_set == 0) {
if (!init) { if (!init) {
item->sg_set |= SG_CTERM+SG_GUI; HL_TABLE()[idx].sg_set |= SG_CTERM+SG_GUI;
} }
highlight_clear(idx); highlight_clear(idx);
} }
@ -6741,34 +6738,34 @@ void do_highlight(const char *line, const bool forceit, const bool init)
break; break;
} }
if (*key == 'C') { if (*key == 'C') {
if (!init || !(item->sg_set & SG_CTERM)) { if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM)) {
if (!init) { if (!init) {
item->sg_set |= SG_CTERM; HL_TABLE()[idx].sg_set |= SG_CTERM;
} }
item->sg_cterm = attr; HL_TABLE()[idx].sg_cterm = attr;
item->sg_cterm_bold = false; HL_TABLE()[idx].sg_cterm_bold = false;
} }
} else if (*key == 'G') { } else if (*key == 'G') {
if (!init || !(item->sg_set & SG_GUI)) { if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
if (!init) { if (!init) {
item->sg_set |= SG_GUI; HL_TABLE()[idx].sg_set |= SG_GUI;
} }
item->sg_gui = attr; HL_TABLE()[idx].sg_gui = attr;
} }
} }
} else if (STRCMP(key, "FONT") == 0) { } else if (STRCMP(key, "FONT") == 0) {
// in non-GUI fonts are simply ignored // in non-GUI fonts are simply ignored
} else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0) { } else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0) {
if (!init || !(item->sg_set & SG_CTERM)) { if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM)) {
if (!init) { if (!init) {
item->sg_set |= SG_CTERM; HL_TABLE()[idx].sg_set |= SG_CTERM;
} }
/* When setting the foreground color, and previously the "bold" /* When setting the foreground color, and previously the "bold"
* flag was set for a light color, reset it now */ * flag was set for a light color, reset it now */
if (key[5] == 'F' && item->sg_cterm_bold) { if (key[5] == 'F' && HL_TABLE()[idx].sg_cterm_bold) {
item->sg_cterm &= ~HL_BOLD; HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
item->sg_cterm_bold = false; HL_TABLE()[idx].sg_cterm_bold = false;
} }
if (ascii_isdigit(*arg)) { if (ascii_isdigit(*arg)) {
@ -6811,21 +6808,21 @@ void do_highlight(const char *line, const bool forceit, const bool init)
// set/reset bold attribute to get light foreground // set/reset bold attribute to get light foreground
// colors (on some terminals, e.g. "linux") // colors (on some terminals, e.g. "linux")
if (bold == kTrue) { if (bold == kTrue) {
item->sg_cterm |= HL_BOLD; HL_TABLE()[idx].sg_cterm |= HL_BOLD;
item->sg_cterm_bold = true; HL_TABLE()[idx].sg_cterm_bold = true;
} else if (bold == kFalse) { } else if (bold == kFalse) {
item->sg_cterm &= ~HL_BOLD; HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
} }
} }
// Add one to the argument, to avoid zero. Zero is used for // Add one to the argument, to avoid zero. Zero is used for
// "NONE", then "color" is -1. // "NONE", then "color" is -1.
if (key[5] == 'F') { if (key[5] == 'F') {
item->sg_cterm_fg = color + 1; HL_TABLE()[idx].sg_cterm_fg = color + 1;
if (is_normal_group) { if (is_normal_group) {
cterm_normal_fg_color = color + 1; cterm_normal_fg_color = color + 1;
} }
} else { } else {
item->sg_cterm_bg = color + 1; HL_TABLE()[idx].sg_cterm_bg = color + 1;
if (is_normal_group) { if (is_normal_group) {
cterm_normal_bg_color = color + 1; cterm_normal_bg_color = color + 1;
if (!ui_rgb_attached()) { if (!ui_rgb_attached()) {
@ -6852,61 +6849,61 @@ void do_highlight(const char *line, const bool forceit, const bool init)
} }
} }
} else if (strcmp(key, "GUIFG") == 0) { } else if (strcmp(key, "GUIFG") == 0) {
if (!init || !(item->sg_set & SG_GUI)) { if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
if (!init) { if (!init) {
item->sg_set |= SG_GUI; HL_TABLE()[idx].sg_set |= SG_GUI;
} }
xfree(item->sg_rgb_fg_name); xfree(HL_TABLE()[idx].sg_rgb_fg_name);
if (strcmp(arg, "NONE")) { if (strcmp(arg, "NONE")) {
item->sg_rgb_fg_name = (char_u *)xstrdup((char *)arg); HL_TABLE()[idx].sg_rgb_fg_name = (char_u *)xstrdup((char *)arg);
item->sg_rgb_fg = name_to_color((const char_u *)arg); HL_TABLE()[idx].sg_rgb_fg = name_to_color((const char_u *)arg);
} else { } else {
item->sg_rgb_fg_name = NULL; HL_TABLE()[idx].sg_rgb_fg_name = NULL;
item->sg_rgb_fg = -1; HL_TABLE()[idx].sg_rgb_fg = -1;
} }
} }
if (is_normal_group) { if (is_normal_group) {
normal_fg = item->sg_rgb_fg; normal_fg = HL_TABLE()[idx].sg_rgb_fg;
} }
} else if (STRCMP(key, "GUIBG") == 0) { } else if (STRCMP(key, "GUIBG") == 0) {
if (!init || !(item->sg_set & SG_GUI)) { if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
if (!init) { if (!init) {
item->sg_set |= SG_GUI; HL_TABLE()[idx].sg_set |= SG_GUI;
} }
xfree(item->sg_rgb_bg_name); xfree(HL_TABLE()[idx].sg_rgb_bg_name);
if (STRCMP(arg, "NONE") != 0) { if (STRCMP(arg, "NONE") != 0) {
item->sg_rgb_bg_name = (char_u *)xstrdup((char *)arg); HL_TABLE()[idx].sg_rgb_bg_name = (char_u *)xstrdup((char *)arg);
item->sg_rgb_bg = name_to_color((const char_u *)arg); HL_TABLE()[idx].sg_rgb_bg = name_to_color((const char_u *)arg);
} else { } else {
item->sg_rgb_bg_name = NULL; HL_TABLE()[idx].sg_rgb_bg_name = NULL;
item->sg_rgb_bg = -1; HL_TABLE()[idx].sg_rgb_bg = -1;
} }
} }
if (is_normal_group) { if (is_normal_group) {
normal_bg = item->sg_rgb_bg; normal_bg = HL_TABLE()[idx].sg_rgb_bg;
} }
} else if (strcmp(key, "GUISP") == 0) { } else if (strcmp(key, "GUISP") == 0) {
if (!init || !(item->sg_set & SG_GUI)) { if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
if (!init) { if (!init) {
item->sg_set |= SG_GUI; HL_TABLE()[idx].sg_set |= SG_GUI;
} }
xfree(item->sg_rgb_sp_name); xfree(HL_TABLE()[idx].sg_rgb_sp_name);
if (strcmp(arg, "NONE") != 0) { if (strcmp(arg, "NONE") != 0) {
item->sg_rgb_sp_name = (char_u *)xstrdup((char *)arg); HL_TABLE()[idx].sg_rgb_sp_name = (char_u *)xstrdup((char *)arg);
item->sg_rgb_sp = name_to_color((const char_u *)arg); HL_TABLE()[idx].sg_rgb_sp = name_to_color((const char_u *)arg);
} else { } else {
item->sg_rgb_sp_name = NULL; HL_TABLE()[idx].sg_rgb_sp_name = NULL;
item->sg_rgb_sp = -1; HL_TABLE()[idx].sg_rgb_sp = -1;
} }
} }
if (is_normal_group) { if (is_normal_group) {
normal_sp = item->sg_rgb_sp; normal_sp = HL_TABLE()[idx].sg_rgb_sp;
} }
} else if (strcmp(key, "START") == 0 || strcmp(key, "STOP") == 0) { } else if (strcmp(key, "START") == 0 || strcmp(key, "STOP") == 0) {
// Ignored for now // Ignored for now
@ -6915,11 +6912,11 @@ void do_highlight(const char *line, const bool forceit, const bool init)
error = true; error = true;
break; break;
} }
item->sg_cleared = false; HL_TABLE()[idx].sg_cleared = false;
// When highlighting has been given for a group, don't link it. // When highlighting has been given for a group, don't link it.
if (!init || !(item->sg_set & SG_LINK)) { if (!init || !(HL_TABLE()[idx].sg_set & SG_LINK)) {
item->sg_link = 0; HL_TABLE()[idx].sg_link = 0;
} }
// Continue with next argument. // Continue with next argument.
@ -6945,20 +6942,19 @@ void do_highlight(const char *line, const bool forceit, const bool init)
// redraw below will still handle usages of guibg=fg etc. // redraw below will still handle usages of guibg=fg etc.
ui_default_colors_set(); ui_default_colors_set();
} }
item = &HL_TABLE()[idx];
did_highlight_changed = true; did_highlight_changed = true;
redraw_all_later(NOT_VALID); redraw_all_later(NOT_VALID);
} else { } else {
set_hl_attr(idx); set_hl_attr(idx);
} }
item->sg_scriptID = current_SID; HL_TABLE()[idx].sg_scriptID = current_SID;
} }
xfree(key); xfree(key);
xfree(arg); xfree(arg);
// Only call highlight_changed() once, after a sequence of highlight // Only call highlight_changed() once, after a sequence of highlight
// commands, and only if an attribute actually changed // commands, and only if an attribute actually changed
if (memcmp(item, &item_before, sizeof(item_before)) != 0 if (memcmp(&HL_TABLE()[idx], &item_before, sizeof(item_before)) != 0
&& !did_highlight_changed) { && !did_highlight_changed) {
redraw_all_later(NOT_VALID); redraw_all_later(NOT_VALID);
need_highlight_changed = true; need_highlight_changed = true;