mirror of
https://github.com/neovim/neovim.git
synced 2025-09-10 13:28:19 +00:00
ga_growsize should be >= 1
I know it could be 0 sometimes. Running the tests with `assert(gap->ga_growsize > 0)` in ga_grow() crashes nvim while running the tests. - Add a setter for ga_growsize that checks whether the value passed is >=1 (log in case it's not) - log when ga_grow() tries to use a ga_growsize that's not >=1 - use GA_EMPTY_INIT_VALUE is many places
This commit is contained in:

committed by
Justin M. Keyes

parent
d723e7fd61
commit
be3a4b6ca8
@@ -2790,7 +2790,7 @@ char_u *getsourceline(int c, void *cookie, int indent)
|
|||||||
/* Adjust the growsize to the current length to speed up
|
/* Adjust the growsize to the current length to speed up
|
||||||
* concatenating many lines. */
|
* concatenating many lines. */
|
||||||
if (ga.ga_len > 400) {
|
if (ga.ga_len > 400) {
|
||||||
ga.ga_growsize = (ga.ga_len > 8000) ? 8000 : ga.ga_len;
|
ga_set_growsize(&ga, (ga.ga_len > 8000) ? 8000 : ga.ga_len);
|
||||||
}
|
}
|
||||||
ga_concat(&ga, p + 1);
|
ga_concat(&ga, p + 1);
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
|
#include "nvim/log.h"
|
||||||
#include "nvim/misc2.h"
|
#include "nvim/misc2.h"
|
||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/path.h"
|
#include "nvim/path.h"
|
||||||
@@ -52,7 +53,21 @@ void ga_init(garray_T *gap, int itemsize, int growsize)
|
|||||||
gap->ga_maxlen = 0;
|
gap->ga_maxlen = 0;
|
||||||
gap->ga_len = 0;
|
gap->ga_len = 0;
|
||||||
gap->ga_itemsize = itemsize;
|
gap->ga_itemsize = itemsize;
|
||||||
gap->ga_growsize = growsize;
|
ga_set_growsize(gap, growsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A setter for the growsize that guarantees it will be at least 1.
|
||||||
|
///
|
||||||
|
/// @param gap
|
||||||
|
/// @param growsize
|
||||||
|
void ga_set_growsize(garray_T *gap, int growsize)
|
||||||
|
{
|
||||||
|
if (growsize < 1) {
|
||||||
|
WLOG("trying to set an invalid ga_growsize: %d", growsize);
|
||||||
|
gap->ga_growsize = 1;
|
||||||
|
} else {
|
||||||
|
gap->ga_growsize = growsize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make room in growing array "gap" for at least "n" items.
|
/// Make room in growing array "gap" for at least "n" items.
|
||||||
@@ -66,17 +81,24 @@ void ga_grow(garray_T *gap, int n)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the garray grows by at least growsize (do we have a MIN macro somewhere?)
|
if (gap->ga_growsize < 1) {
|
||||||
n = (n < gap->ga_growsize) ? gap->ga_growsize : n;
|
WLOG("ga_growsize(%d) is less than 1", gap->ga_growsize);
|
||||||
|
}
|
||||||
|
|
||||||
size_t new_size = (size_t)(gap->ga_itemsize * (gap->ga_len + n));
|
// the garray grows by at least growsize
|
||||||
|
if (n < gap->ga_growsize) {
|
||||||
|
n = gap->ga_growsize;
|
||||||
|
}
|
||||||
|
int new_maxlen = gap->ga_len + n;
|
||||||
|
|
||||||
|
size_t new_size = (size_t)(gap->ga_itemsize * new_maxlen);
|
||||||
size_t old_size = (size_t)(gap->ga_itemsize * gap->ga_maxlen);
|
size_t old_size = (size_t)(gap->ga_itemsize * gap->ga_maxlen);
|
||||||
|
|
||||||
// reallocate and clear the new memory
|
// reallocate and clear the new memory
|
||||||
char_u *pp = xrealloc(gap->ga_data, new_size);
|
char *pp = xrealloc(gap->ga_data, new_size);
|
||||||
memset(pp + old_size, 0, new_size - old_size);
|
memset(pp + old_size, 0, new_size - old_size);
|
||||||
|
|
||||||
gap->ga_maxlen = gap->ga_len + n;
|
gap->ga_maxlen = new_maxlen;
|
||||||
gap->ga_data = pp;
|
gap->ga_data = pp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@ typedef struct growarray {
|
|||||||
void *ga_data; // pointer to the first item
|
void *ga_data; // pointer to the first item
|
||||||
} garray_T;
|
} garray_T;
|
||||||
|
|
||||||
#define GA_EMPTY_INIT_VALUE { 0, 0, 0, 0, NULL }
|
#define GA_EMPTY_INIT_VALUE { 0, 0, 0, 1, NULL }
|
||||||
|
|
||||||
#define GA_EMPTY(ga_ptr) ((ga_ptr)->ga_len <= 0)
|
#define GA_EMPTY(ga_ptr) ((ga_ptr)->ga_len <= 0)
|
||||||
|
|
||||||
|
@@ -969,7 +969,7 @@ EXTERN int need_cursor_line_redraw INIT(= FALSE);
|
|||||||
/* Grow array to collect error messages in until they can be displayed. */
|
/* Grow array to collect error messages in until they can be displayed. */
|
||||||
EXTERN garray_T error_ga
|
EXTERN garray_T error_ga
|
||||||
# ifdef DO_INIT
|
# ifdef DO_INIT
|
||||||
= {0, 0, 0, 0, NULL}
|
= GA_EMPTY_INIT_VALUE
|
||||||
# endif
|
# endif
|
||||||
;
|
;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1285,7 +1285,7 @@ static int prt_collate;
|
|||||||
* Buffers used when generating PostScript output
|
* Buffers used when generating PostScript output
|
||||||
*/
|
*/
|
||||||
static char_u prt_line_buffer[257];
|
static char_u prt_line_buffer[257];
|
||||||
static garray_T prt_ps_buffer;
|
static garray_T prt_ps_buffer = GA_EMPTY_INIT_VALUE;
|
||||||
|
|
||||||
static int prt_do_conv;
|
static int prt_do_conv;
|
||||||
static vimconv_T prt_conv;
|
static vimconv_T prt_conv;
|
||||||
|
@@ -1434,7 +1434,7 @@ typedef struct {
|
|||||||
char_u *to; /* translated name */
|
char_u *to; /* translated name */
|
||||||
} menutrans_T;
|
} menutrans_T;
|
||||||
|
|
||||||
static garray_T menutrans_ga = {0, 0, 0, 0, NULL};
|
static garray_T menutrans_ga = GA_EMPTY_INIT_VALUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ":menutrans".
|
* ":menutrans".
|
||||||
|
@@ -2257,8 +2257,8 @@ void mch_errmsg(char *str)
|
|||||||
emsg_on_display = FALSE;
|
emsg_on_display = FALSE;
|
||||||
|
|
||||||
len = (int)STRLEN(str) + 1;
|
len = (int)STRLEN(str) + 1;
|
||||||
if (error_ga.ga_growsize == 0) {
|
if (error_ga.ga_data == NULL) {
|
||||||
error_ga.ga_growsize = 80;
|
ga_set_growsize(&error_ga, 80);
|
||||||
error_ga.ga_itemsize = 1;
|
error_ga.ga_itemsize = 1;
|
||||||
}
|
}
|
||||||
ga_grow(&error_ga, len);
|
ga_grow(&error_ga, len);
|
||||||
|
@@ -58,7 +58,7 @@
|
|||||||
# include "misc1.c.generated.h"
|
# include "misc1.c.generated.h"
|
||||||
#endif
|
#endif
|
||||||
/* All user names (for ~user completion as done by shell). */
|
/* All user names (for ~user completion as done by shell). */
|
||||||
static garray_T ga_users;
|
static garray_T ga_users = GA_EMPTY_INIT_VALUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* open_line: Add a new line below or above the current line.
|
* open_line: Add a new line below or above the current line.
|
||||||
|
@@ -7499,7 +7499,7 @@ typedef struct {
|
|||||||
int to;
|
int to;
|
||||||
} langmap_entry_T;
|
} langmap_entry_T;
|
||||||
|
|
||||||
static garray_T langmap_mapga;
|
static garray_T langmap_mapga = GA_EMPTY_INIT_VALUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Search for an entry in "langmap_mapga" for "from". If found set the "to"
|
* Search for an entry in "langmap_mapga" for "from". If found set the "to"
|
||||||
|
@@ -3180,8 +3180,8 @@ static int reg_line_lbr; /* "\n" in string is line break */
|
|||||||
* or regbehind_T.
|
* or regbehind_T.
|
||||||
* "backpos_T" is a table with backpos_T for BACK
|
* "backpos_T" is a table with backpos_T for BACK
|
||||||
*/
|
*/
|
||||||
static garray_T regstack = {0, 0, 0, 0, NULL};
|
static garray_T regstack = GA_EMPTY_INIT_VALUE;
|
||||||
static garray_T backpos = {0, 0, 0, 0, NULL};
|
static garray_T backpos = GA_EMPTY_INIT_VALUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Both for regstack and backpos tables we use the following strategy of
|
* Both for regstack and backpos tables we use the following strategy of
|
||||||
@@ -3319,13 +3319,13 @@ static long bt_regexec_both(char_u *line,
|
|||||||
* onto the regstack. */
|
* onto the regstack. */
|
||||||
ga_init(®stack, 1, REGSTACK_INITIAL);
|
ga_init(®stack, 1, REGSTACK_INITIAL);
|
||||||
ga_grow(®stack, REGSTACK_INITIAL);
|
ga_grow(®stack, REGSTACK_INITIAL);
|
||||||
regstack.ga_growsize = REGSTACK_INITIAL * 8;
|
ga_set_growsize(®stack, REGSTACK_INITIAL * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backpos.ga_data == NULL) {
|
if (backpos.ga_data == NULL) {
|
||||||
ga_init(&backpos, sizeof(backpos_T), BACKPOS_INITIAL);
|
ga_init(&backpos, sizeof(backpos_T), BACKPOS_INITIAL);
|
||||||
ga_grow(&backpos, BACKPOS_INITIAL);
|
ga_grow(&backpos, BACKPOS_INITIAL);
|
||||||
backpos.ga_growsize = BACKPOS_INITIAL * 8;
|
ga_set_growsize(&backpos, BACKPOS_INITIAL * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (REG_MULTI) {
|
if (REG_MULTI) {
|
||||||
|
@@ -75,7 +75,8 @@ struct hl_group {
|
|||||||
#define SG_GUI 4 /* gui has been set */
|
#define SG_GUI 4 /* gui has been set */
|
||||||
#define SG_LINK 8 /* link has been set */
|
#define SG_LINK 8 /* link has been set */
|
||||||
|
|
||||||
static garray_T highlight_ga; /* highlight groups for 'highlight' option */
|
// highlight groups for 'highlight' option
|
||||||
|
static garray_T highlight_ga = GA_EMPTY_INIT_VALUE;
|
||||||
|
|
||||||
#define HL_TABLE() ((struct hl_group *)((highlight_ga.ga_data)))
|
#define HL_TABLE() ((struct hl_group *)((highlight_ga.ga_data)))
|
||||||
|
|
||||||
@@ -360,7 +361,7 @@ static int current_state_stored = 0; /* TRUE if stored current state
|
|||||||
* after setting current_finished */
|
* after setting current_finished */
|
||||||
static int current_finished = 0; /* current line has been finished */
|
static int current_finished = 0; /* current line has been finished */
|
||||||
static garray_T current_state /* current stack of state_items */
|
static garray_T current_state /* current stack of state_items */
|
||||||
= {0, 0, 0, 0, NULL};
|
= GA_EMPTY_INIT_VALUE;
|
||||||
static short *current_next_list = NULL; /* when non-zero, nextgroup list */
|
static short *current_next_list = NULL; /* when non-zero, nextgroup list */
|
||||||
static int current_next_flags = 0; /* flags for current_next_list */
|
static int current_next_flags = 0; /* flags for current_next_list */
|
||||||
static int current_line_id = 0; /* unique number for current line */
|
static int current_line_id = 0; /* unique number for current line */
|
||||||
@@ -1452,7 +1453,7 @@ static void invalidate_current_state(void)
|
|||||||
static void validate_current_state(void)
|
static void validate_current_state(void)
|
||||||
{
|
{
|
||||||
current_state.ga_itemsize = sizeof(stateitem_T);
|
current_state.ga_itemsize = sizeof(stateitem_T);
|
||||||
current_state.ga_growsize = 3;
|
ga_set_growsize(¤t_state, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -4746,7 +4747,7 @@ static int syn_add_cluster(char_u *name)
|
|||||||
*/
|
*/
|
||||||
if (curwin->w_s->b_syn_clusters.ga_data == NULL) {
|
if (curwin->w_s->b_syn_clusters.ga_data == NULL) {
|
||||||
curwin->w_s->b_syn_clusters.ga_itemsize = sizeof(syn_cluster_T);
|
curwin->w_s->b_syn_clusters.ga_itemsize = sizeof(syn_cluster_T);
|
||||||
curwin->w_s->b_syn_clusters.ga_growsize = 10;
|
ga_set_growsize(&curwin->w_s->b_syn_clusters, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = curwin->w_s->b_syn_clusters.ga_len;
|
int len = curwin->w_s->b_syn_clusters.ga_len;
|
||||||
@@ -4846,7 +4847,7 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing)
|
|||||||
static void init_syn_patterns(void)
|
static void init_syn_patterns(void)
|
||||||
{
|
{
|
||||||
curwin->w_s->b_syn_patterns.ga_itemsize = sizeof(synpat_T);
|
curwin->w_s->b_syn_patterns.ga_itemsize = sizeof(synpat_T);
|
||||||
curwin->w_s->b_syn_patterns.ga_growsize = 10;
|
ga_set_growsize(&curwin->w_s->b_syn_patterns, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -6731,11 +6732,11 @@ static void highlight_clear(int idx)
|
|||||||
* Note that this table is used by ALL buffers. This is required because the
|
* Note that this table is used by ALL buffers. This is required because the
|
||||||
* GUI can redraw at any time for any buffer.
|
* GUI can redraw at any time for any buffer.
|
||||||
*/
|
*/
|
||||||
static garray_T term_attr_table = {0, 0, 0, 0, NULL};
|
static garray_T term_attr_table = GA_EMPTY_INIT_VALUE;
|
||||||
|
|
||||||
#define TERM_ATTR_ENTRY(idx) ((attrentry_T *)term_attr_table.ga_data)[idx]
|
#define TERM_ATTR_ENTRY(idx) ((attrentry_T *)term_attr_table.ga_data)[idx]
|
||||||
|
|
||||||
static garray_T cterm_attr_table = {0, 0, 0, 0, NULL};
|
static garray_T cterm_attr_table = GA_EMPTY_INIT_VALUE;
|
||||||
|
|
||||||
#define CTERM_ATTR_ENTRY(idx) ((attrentry_T *)cterm_attr_table.ga_data)[idx]
|
#define CTERM_ATTR_ENTRY(idx) ((attrentry_T *)cterm_attr_table.ga_data)[idx]
|
||||||
|
|
||||||
@@ -6755,7 +6756,7 @@ static int get_attr_entry(garray_T *table, attrentry_T *aep)
|
|||||||
* Init the table, in case it wasn't done yet.
|
* Init the table, in case it wasn't done yet.
|
||||||
*/
|
*/
|
||||||
table->ga_itemsize = sizeof(attrentry_T);
|
table->ga_itemsize = sizeof(attrentry_T);
|
||||||
table->ga_growsize = 7;
|
ga_set_growsize(table, 7);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to find an entry with the same specifications.
|
* Try to find an entry with the same specifications.
|
||||||
@@ -7311,7 +7312,7 @@ static int syn_add_group(char_u *name)
|
|||||||
*/
|
*/
|
||||||
if (highlight_ga.ga_data == NULL) {
|
if (highlight_ga.ga_data == NULL) {
|
||||||
highlight_ga.ga_itemsize = sizeof(struct hl_group);
|
highlight_ga.ga_itemsize = sizeof(struct hl_group);
|
||||||
highlight_ga.ga_growsize = 10;
|
ga_set_growsize(&highlight_ga, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (highlight_ga.ga_len >= MAX_HL_ID) {
|
if (highlight_ga.ga_len >= MAX_HL_ID) {
|
||||||
|
Reference in New Issue
Block a user