Fix memory leaks and bad references detected by valgrind
* add free_font_cache() * add css_free_colors() * add unload_ligatures() * add --free-all cmd line option to free memory upon exit for valgrind * tty.c: fix off by 3 size in qe_realloc. Should be typed * qe.c: fix invalid pointer reference upon destroying transient buffer
This commit is contained in:
parent
267af9e44b
commit
c5f56a0d5b
9 changed files with 118 additions and 8 deletions
1
buffer.c
1
buffer.c
|
|
@ -579,6 +579,7 @@ void eb_free(EditBuffer **bp)
|
|||
|
||||
eb_free_style_buffer(b);
|
||||
|
||||
qe_free(&b->saved_data);
|
||||
qe_free(bp);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -249,6 +249,14 @@ static QEFont dummy_font;
|
|||
static QEFont *font_cache[FONT_CACHE_SIZE];
|
||||
static int font_cache_timestamp = 0;
|
||||
|
||||
void free_font_cache(QEditScreen *s)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < FONT_CACHE_SIZE; i++) {
|
||||
close_font(s, &font_cache[i]);
|
||||
}
|
||||
}
|
||||
|
||||
QEFont *select_font(QEditScreen *s, int style, int size)
|
||||
{
|
||||
QEFont *fc;
|
||||
|
|
|
|||
|
|
@ -248,8 +248,8 @@ void fill_rectangle(QEditScreen *s,
|
|||
void set_clip_rectangle(QEditScreen *s, CSSRect *r);
|
||||
void push_clip_rectangle(QEditScreen *s, CSSRect *or, CSSRect *r);
|
||||
|
||||
void free_font_cache(QEditScreen *s);
|
||||
QEFont *select_font(QEditScreen *s, int style, int size);
|
||||
|
||||
static inline QEFont *lock_font(__unused__ QEditScreen *s, QEFont *font) {
|
||||
if (font && font->refcount)
|
||||
font->refcount++;
|
||||
|
|
|
|||
84
qe.c
84
qe.c
|
|
@ -72,6 +72,9 @@ static QEditScreen global_screen;
|
|||
static int screen_width = 0;
|
||||
static int screen_height = 0;
|
||||
static int no_init_file;
|
||||
#ifndef CONFIG_TINY
|
||||
static int free_everything;
|
||||
#endif
|
||||
static const char *user_option;
|
||||
|
||||
/* mode handling */
|
||||
|
|
@ -80,7 +83,6 @@ void qe_register_mode(ModeDef *m)
|
|||
{
|
||||
QEmacsState *qs = &qe_state;
|
||||
ModeDef **p;
|
||||
CmdDef *def;
|
||||
|
||||
/* register mode in mode list (at end) */
|
||||
p = &qs->first_mode;
|
||||
|
|
@ -107,6 +109,7 @@ void qe_register_mode(ModeDef *m)
|
|||
if (!(m->mode_flags & MODEF_NOCMD)) {
|
||||
char buf[64];
|
||||
int size;
|
||||
CmdDef *def;
|
||||
|
||||
/* lower case convert for C mode, Perl... */
|
||||
qe_strtolower(buf, sizeof(buf) - 10, m->name);
|
||||
|
|
@ -121,6 +124,7 @@ void qe_register_mode(ModeDef *m)
|
|||
def->sig = CMD_ESs;
|
||||
def->val = 0;
|
||||
def->action.ESs = do_set_mode;
|
||||
def[1].val = 1; /* flag as allocated for free-all */
|
||||
qe_register_cmd_table(def, NULL);
|
||||
}
|
||||
}
|
||||
|
|
@ -4155,7 +4159,7 @@ void do_define_kbd_macro(EditState *s, const char *name, const char *keys,
|
|||
def->sig = CMD_ESs;
|
||||
def->val = 0;
|
||||
def->action.ESs = do_execute_macro_keys;
|
||||
|
||||
def[1].val = 1; /* flag as allocated for free-all */
|
||||
qe_register_cmd_table(def, NULL);
|
||||
do_set_key(s, key_bind, name, 0);
|
||||
}
|
||||
|
|
@ -4549,6 +4553,7 @@ void switch_to_buffer(EditState *s, EditBuffer *b)
|
|||
EditBuffer *b1;
|
||||
EditState *e;
|
||||
ModeSavedData *saved_data, **psaved_data;
|
||||
int saved_data_allocated = 0;
|
||||
ModeDef *mode;
|
||||
|
||||
/* remove region hilite */
|
||||
|
|
@ -4572,14 +4577,16 @@ void switch_to_buffer(EditState *s, EditBuffer *b)
|
|||
* - otherwise, save the mode data in the buffer.
|
||||
* CG: Should free previous such data ?
|
||||
*/
|
||||
if (b1->flags & BF_TRANSIENT) {
|
||||
eb_free(&b1);
|
||||
} else {
|
||||
if (!(b1->flags & BF_TRANSIENT)) {
|
||||
qe_free(&b1->saved_data);
|
||||
b1->saved_data = s->mode->mode_save_data(s);
|
||||
}
|
||||
}
|
||||
/* now we can close the mode */
|
||||
edit_set_mode(s, NULL);
|
||||
if (b1->flags & BF_TRANSIENT) {
|
||||
eb_free(&b1);
|
||||
}
|
||||
}
|
||||
|
||||
/* now we can switch ! */
|
||||
|
|
@ -4595,6 +4602,7 @@ void switch_to_buffer(EditState *s, EditBuffer *b)
|
|||
if (e) {
|
||||
psaved_data = NULL;
|
||||
saved_data = e->mode->mode_save_data(e);
|
||||
saved_data_allocated = 1;
|
||||
} else {
|
||||
psaved_data = &b->saved_data;
|
||||
saved_data = *psaved_data;
|
||||
|
|
@ -4608,6 +4616,8 @@ void switch_to_buffer(EditState *s, EditBuffer *b)
|
|||
|
||||
/* open it ! */
|
||||
edit_set_mode_full(s, mode, saved_data, NULL);
|
||||
if (saved_data_allocated)
|
||||
qe_free(&saved_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4732,6 +4742,7 @@ void edit_close(EditState *s)
|
|||
if (qs->active_window == s)
|
||||
qs->active_window = qs->first_window;
|
||||
|
||||
qe_free(&s->mode_data);
|
||||
qe_free(&s->prompt);
|
||||
qe_free(&s->line_shadow);
|
||||
qe_free(&s);
|
||||
|
|
@ -5853,6 +5864,7 @@ static void quit_examine_buffers(QuitState *is)
|
|||
edit_display(&qe_state);
|
||||
dpy_flush(&global_screen);
|
||||
} else {
|
||||
qe_free(&is);
|
||||
url_exit();
|
||||
}
|
||||
}
|
||||
|
|
@ -7719,6 +7731,10 @@ static CmdOptionDef cmd_options[] = {
|
|||
{ .func_arg = set_user_option }},
|
||||
{ "version", "V", NULL, 0, "display version information and exit",
|
||||
{ .func_noarg = show_version }},
|
||||
#ifndef CONFIG_TINY
|
||||
{ "free-all", NULL, NULL, CMD_OPT_BOOL, "free all structures upon exit",
|
||||
{ .int_ptr = &free_everything }},
|
||||
#endif
|
||||
{ NULL, NULL, NULL, 0, NULL, { NULL }},
|
||||
};
|
||||
|
||||
|
|
@ -8040,7 +8056,65 @@ int main(int argc, char **argv)
|
|||
#ifdef CONFIG_ALL_KMAPS
|
||||
unload_input_methods();
|
||||
#endif
|
||||
#ifdef CONFIG_UNICODE_JOIN
|
||||
unload_ligatures();
|
||||
#endif
|
||||
#ifndef CONFIG_TINY
|
||||
if (free_everything) {
|
||||
/* free all structures for valgrind */
|
||||
QEmacsState *qs = &qe_state;
|
||||
|
||||
while (qs->input_methods) {
|
||||
InputMethod *p = qs->input_methods;
|
||||
qs->input_methods = p->next;
|
||||
if (p->data)
|
||||
qe_free(&p);
|
||||
}
|
||||
while (qs->first_window) {
|
||||
EditState *e = qs->first_window;
|
||||
edit_close(e);
|
||||
}
|
||||
while (qs->first_buffer) {
|
||||
EditBuffer *b = qs->first_buffer;
|
||||
eb_free(&b);
|
||||
}
|
||||
while (qs->first_cmd) {
|
||||
CmdDef *d = qs->first_cmd;
|
||||
CmdDef *d1 = d;
|
||||
while (d1->name)
|
||||
d1++;
|
||||
qs->first_cmd = d1->action.next;
|
||||
/* free xxx-mode commands and macros */
|
||||
if (d->name && !d[1].name && d[1].val) {
|
||||
qe_free((char **)&d->name);
|
||||
qe_free(&d);
|
||||
}
|
||||
}
|
||||
while (qs->first_key) {
|
||||
KeyDef *p = qs->first_key;
|
||||
qs->first_key = p->next;
|
||||
qe_free(&p);
|
||||
}
|
||||
while (qs->first_mode) {
|
||||
ModeDef *m = qs->first_mode;
|
||||
qs->first_mode = m->next;
|
||||
|
||||
while (m->first_key) {
|
||||
KeyDef *p = m->first_key;
|
||||
m->first_key = p->next;
|
||||
qe_free(&p);
|
||||
}
|
||||
}
|
||||
while (qs->first_completion) {
|
||||
CompletionEntry *cp = qs->first_completion;
|
||||
qs->first_completion = cp->next;
|
||||
qe_free(&cp);
|
||||
}
|
||||
css_free_colors();
|
||||
free_font_cache(&global_screen);
|
||||
}
|
||||
#endif
|
||||
dpy_close(&global_screen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
2
qe.h
2
qe.h
|
|
@ -315,6 +315,7 @@ int to_hex(int key);
|
|||
void color_completion(CompleteState *cp);
|
||||
int css_define_color(const char *name, const char *value);
|
||||
int css_get_color(QEColor *color_ptr, const char *p);
|
||||
void css_free_colors(void);
|
||||
int css_get_font_family(const char *str);
|
||||
void css_union_rect(CSSRect *a, const CSSRect *b);
|
||||
static inline int css_is_null_rect(const CSSRect *a) {
|
||||
|
|
@ -561,6 +562,7 @@ int unicode_to_glyphs(unsigned int *dst, unsigned int *char_to_glyph_pos,
|
|||
int dst_size, unsigned int *src, int src_size,
|
||||
int reverse);
|
||||
int load_ligatures(void);
|
||||
void unload_ligatures(void);
|
||||
|
||||
/* qe event handling */
|
||||
|
||||
|
|
|
|||
1
shell.c
1
shell.c
|
|
@ -1328,6 +1328,7 @@ static void shell_close(EditBuffer *b)
|
|||
while (waitpid(s->pid, &status, 0) != s->pid)
|
||||
continue;
|
||||
}
|
||||
set_pid_handler(s->pid, NULL, NULL);
|
||||
s->pid = -1;
|
||||
}
|
||||
if (s->pty_fd >= 0) {
|
||||
|
|
|
|||
9
tty.c
9
tty.c
|
|
@ -241,6 +241,8 @@ static int tty_term_init(QEditScreen *s,
|
|||
|
||||
static void tty_term_close(QEditScreen *s)
|
||||
{
|
||||
TTYState *ts = s->priv_data;
|
||||
|
||||
fcntl(fileno(s->STDIN), F_SETFL, 0);
|
||||
#if 0
|
||||
/* go to the last line */
|
||||
|
|
@ -258,6 +260,9 @@ static void tty_term_close(QEditScreen *s)
|
|||
);
|
||||
#endif
|
||||
fflush(s->STDOUT);
|
||||
|
||||
qe_free(&ts->screen);
|
||||
qe_free(&ts->line_updated);
|
||||
}
|
||||
|
||||
static void tty_term_exit(void)
|
||||
|
|
@ -290,12 +295,12 @@ static void tty_resize(__unused__ int sig)
|
|||
count = s->width * s->height;
|
||||
size = count * sizeof(TTYChar);
|
||||
/* screen buffer + shadow buffer + extra slot for loop guard */
|
||||
qe_realloc(&ts->screen, size * 2 + 1);
|
||||
qe_realloc(&ts->screen, size * 2 + sizeof(TTYChar));
|
||||
qe_realloc(&ts->line_updated, s->height);
|
||||
ts->screen_size = count;
|
||||
|
||||
/* Erase shadow buffer to impossible value */
|
||||
memset(ts->screen + count, 0xFF, size);
|
||||
memset(ts->screen + count, 0xFF, size + sizeof(TTYChar));
|
||||
/* Fill screen buffer with black spaces */
|
||||
tc = TTYCHAR_DEFAULT;
|
||||
for (i = 0; i < count; i++) {
|
||||
|
|
|
|||
|
|
@ -93,6 +93,13 @@ int load_ligatures(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
void unload_ligatures(void)
|
||||
{
|
||||
qe_free(&subst1);
|
||||
qe_free(&ligature2);
|
||||
qe_free(&ligature_long);
|
||||
}
|
||||
|
||||
static int find_ligature(int l1, int l2)
|
||||
{
|
||||
int a, b, m, v1, v2;
|
||||
|
|
|
|||
12
util.c
12
util.c
|
|
@ -1152,6 +1152,18 @@ int css_define_color(const char *name, const char *value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void css_free_colors(void)
|
||||
{
|
||||
if (qe_colors != default_colors) {
|
||||
while (nb_qe_colors > nb_default_colors) {
|
||||
nb_qe_colors--;
|
||||
qe_free((char **)&qe_colors[nb_qe_colors].name);
|
||||
}
|
||||
qe_free(&qe_colors);
|
||||
qe_colors = (ColorDef *)default_colors;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: make HTML parsing optional ? */
|
||||
int css_get_color(QEColor *color_ptr, const char *p)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue