aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2021-11-16 19:49:25 +0200
committerSergey Poznyakoff <gray@gnu.org>2021-11-16 19:49:25 +0200
commit203601fb06c13472b9069cc139329174b2d4d253 (patch)
tree4c23b29a96ef3536b03047b6f97895c22f2462ec /src
parent6331d5d6818db7923636f63d0e78c22ce6e0c15f (diff)
downloadgdbm-203601fb06c13472b9069cc139329174b2d4d253.tar.gz
gdbm-203601fb06c13472b9069cc139329174b2d4d253.tar.bz2
Fix memory leaks in gdbmshell
* configure.ac: Don't use $YACC and $LEX (undefined since f4c143fbdf). * src/gdbmshell.c (run_command): Free arglist if not saved to last_args. * src/gdbmtool.c (gdbmtool_init): Correctly report unrecognized long options. * src/gdbmtool.h (YY_LOCATION_PRINT): Define to locus_print. (locus_print): New proto. * src/gram.y: Define destructors for various symbols. * src/lex.l: Save source file names in a linked list. Don't free source name in input_context_pop, because yypush might refer to it via yyloc stack even after readinf eof (e.g. when printing location). The collected list is freed at program exit. (locus_print): New function. * src/parseopt.c (parseopt_free): New function. (parseopt_first): Call parseopt_free. (parseopt_next): Call parseopt_free, depending on the result. * src/var.c (variable) <freehook>: New member. (errormask_freehook): New function. Set it as freehook for errorexit and errormask. (variables_free): Call freehook, if defined.
Diffstat (limited to 'src')
-rw-r--r--src/gdbmshell.c2
-rw-r--r--src/gdbmtool.c8
-rw-r--r--src/gdbmtool.h32
-rw-r--r--src/gram.y9
-rw-r--r--src/lex.l70
-rw-r--r--src/parseopt.c16
-rw-r--r--src/var.c16
7 files changed, 112 insertions, 41 deletions
diff --git a/src/gdbmshell.c b/src/gdbmshell.c
index 0b3b7f0..45e3f9f 100644
--- a/src/gdbmshell.c
+++ b/src/gdbmshell.c
@@ -3084,6 +3084,7 @@ run_command (struct command *cmd, struct gdbmarglist *arglist)
break;
case GDBMSHELL_GDBM_ERR:
+ gdbmarglist_free (arglist);
if (variable_has_errno ("errorexit", gdbm_errno))
rc = 1;
else
@@ -3091,6 +3092,7 @@ run_command (struct command *cmd, struct gdbmarglist *arglist)
break;
default:
+ gdbmarglist_free (arglist);
rc = 0;
}
diff --git a/src/gdbmtool.c b/src/gdbmtool.c
index 512dd88..dfe7094 100644
--- a/src/gdbmtool.c
+++ b/src/gdbmtool.c
@@ -222,8 +222,12 @@ gdbmtool_init (void *data, instream_t *pinstr)
break;
default:
- terror (_("unknown option %c; try `%s -h' for more info"),
- optopt, progname);
+ if (optopt == 0)
+ terror (_("unknown option %s; try `%s -h' for more info"),
+ argv[optind-1], progname);
+ else
+ terror (_("unknown option %c; try `%s -h' for more info"),
+ optopt, progname);
exit (EXIT_USAGE);
}
diff --git a/src/gdbmtool.h b/src/gdbmtool.h
index 7462f8e..432e9a6 100644
--- a/src/gdbmtool.h
+++ b/src/gdbmtool.h
@@ -68,37 +68,9 @@ typedef struct locus gdbm_yyltype_t;
} \
while (0)
-#define YY_LOCATION_PRINT(File, Loc) \
- do \
- { \
- if ((Loc).beg.col == 0) \
- fprintf (File, "%s:%u", \
- (Loc).beg.file, \
- (Loc).beg.line); \
- else if (strcmp ((Loc).beg.file, (Loc).end.file)) \
- fprintf (File, "%s:%u.%u-%s:%u.%u", \
- (Loc).beg.file, \
- (Loc).beg.line, (Loc).beg.col, \
- (Loc).end.file, \
- (Loc).end.line, (Loc).end.col); \
- else if ((Loc).beg.line != (Loc).end.line) \
- fprintf (File, "%s:%u.%u-%u.%u", \
- (Loc).beg.file, \
- (Loc).beg.line, (Loc).beg.col, \
- (Loc).end.line, (Loc).end.col); \
- else if ((Loc).beg.col != (Loc).end.col) \
- fprintf (File, "%s:%u.%u-%u", \
- (Loc).beg.file, \
- (Loc).beg.line, (Loc).beg.col, \
- (Loc).end.col); \
- else \
- fprintf (File, "%s:%u.%u", \
- (Loc).beg.file, \
- (Loc).beg.line, \
- (Loc).beg.col); \
- } \
- while (0)
+#define YY_LOCATION_PRINT(File, Loc) locus_print (File, &(Loc))
+void locus_print (FILE *fp, struct locus const *loc);
void vlerror (struct locus *loc, const char *fmt, va_list ap);
void lerror (struct locus *loc, const char *fmt, ...)
GDBM_PRINTFLIKE (2, 3);
diff --git a/src/gram.y b/src/gram.y
index 561de89..baf72af 100644
--- a/src/gram.y
+++ b/src/gram.y
@@ -62,6 +62,15 @@ struct dsegm *dsdef[DS_MAX];
struct command *cmd;
}
+%destructor { gdbmarglist_free (&$$); } <arglist>
+%destructor { gdbmarg_free ($$); } <arg>
+%destructor { kvlist_free ($$.head); } <kvlist>
+%destructor { kvlist_free ($$); } <kvpair>
+%destructor { slist_free ($$.head); } <slist>
+%destructor { free ($$); } <string>
+%destructor { dsegm_list_free ($$); } <dsegm>
+%destructor { dsegm_list_free ($$.head); } <dsegmlist>
+
%%
input : /* empty */
diff --git a/src/lex.l b/src/lex.l
index b2d6539..00a641f 100644
--- a/src/lex.l
+++ b/src/lex.l
@@ -67,6 +67,37 @@ void string_addc (int c);
char *string_end (void);
int unescape (int c);
+struct file_name
+{
+ struct file_name *next;
+ char str[1];
+};
+
+static struct file_name *file_head;
+
+static void
+file_names_free (void)
+{
+ while (file_head)
+ {
+ struct file_name *next = file_head->next;
+ free (file_head);
+ file_head = next;
+ }
+}
+
+char *
+file_name_alloc (char const *s)
+{
+ struct file_name *f = emalloc (sizeof (*f) + strlen (s));
+ strcpy (f->str, s);
+ f->next = file_head;
+ if (!file_head)
+ atexit (file_names_free);
+ file_head = f;
+ return f->str;
+}
+
int
interactive (void)
{
@@ -123,7 +154,7 @@ input_context_push (instream_t input)
cp = ecalloc (1, sizeof (*cp));
cp->locus = yylloc;
- cp->point.file = estrdup (instream_name (input));
+ cp->point.file = file_name_alloc (instream_name (input));
cp->point.line = 1;
cp->point.col = 0;
@@ -149,8 +180,6 @@ input_context_pop (void)
if (!context_tos)
return 1;
instream_close (context_tos->input);
- free (context_tos->point.file);
- memset (&yylloc, 0, sizeof (yylloc));
cp = context_tos->parent;
free (context_tos);
context_tos = cp;
@@ -499,6 +528,39 @@ escape (int c)
}
return 0;
}
+
+void
+locus_print (FILE *fp, struct locus const *loc)
+{
+ if (loc->beg.file)
+ {
+ if (loc->beg.col == 0)
+ fprintf (fp, "%s:%u",
+ loc->beg.file,
+ loc->beg.line);
+ else if (strcmp (loc->beg.file, loc->end.file))
+ fprintf (fp, "%s:%u.%u-%s:%u.%u",
+ loc->beg.file,
+ loc->beg.line, loc->beg.col,
+ loc->end.file,
+ loc->end.line, loc->end.col);
+ else if (loc->beg.line != loc->end.line)
+ fprintf (fp, "%s:%u.%u-%u.%u",
+ loc->beg.file,
+ loc->beg.line, loc->beg.col,
+ loc->end.line, loc->end.col);
+ else if (loc->beg.col != loc->end.col)
+ fprintf (fp, "%s:%u.%u-%u",
+ loc->beg.file,
+ loc->beg.line, loc->beg.col,
+ loc->end.col);
+ else
+ fprintf (fp, "%s:%u.%u",
+ loc->beg.file,
+ loc->beg.line,
+ loc->beg.col);
+ }
+}
void
vlerror (struct locus *loc, const char *fmt, va_list ap)
@@ -679,4 +741,4 @@ make_prompt (void)
return ret;
}
-
+
diff --git a/src/parseopt.c b/src/parseopt.c
index efa12c8..42cef26 100644
--- a/src/parseopt.c
+++ b/src/parseopt.c
@@ -189,8 +189,8 @@ add_options (struct gdbm_option *options)
#endif
}
-int
-parseopt_first (int pc, char **pv, struct gdbm_option *opts)
+void
+parseopt_free (void)
{
free (option_tab);
option_tab = NULL;
@@ -202,6 +202,12 @@ parseopt_first (int pc, char **pv, struct gdbm_option *opts)
long_options = NULL;
long_option_count = long_option_max = 0;
#endif
+}
+
+int
+parseopt_first (int pc, char **pv, struct gdbm_option *opts)
+{
+ parseopt_free ();
add_options (opts);
add_options (parseopt_default_options);
opterr = 0;
@@ -570,7 +576,7 @@ handle_option (int c)
}
int
-parseopt_next ()
+parseopt_next (void)
{
int rc;
@@ -583,5 +589,9 @@ parseopt_next ()
#endif
}
while (handle_option (rc));
+
+ if (rc == EOF || rc == '?')
+ parseopt_free ();
+
return rc;
}
diff --git a/src/var.c b/src/var.c
index 7b8f3f6..792a42f 100644
--- a/src/var.c
+++ b/src/var.c
@@ -41,6 +41,7 @@ struct variable
void *data;
int (*sethook) (struct variable *, union value *);
int (*typeconv) (struct variable *, int, void **);
+ void (*freehook) (void *);
};
static int open_sethook (struct variable *, union value *);
@@ -53,6 +54,7 @@ static int coalesce_sethook (struct variable *var, union value *v);
static int cachesize_sethook (struct variable *var, union value *v);
static int errormask_sethook (struct variable *var, union value *v);
static int errormask_typeconv (struct variable *var, int type, void **retptr);
+static void errormask_freehook (void *);
static int errorexit_sethook (struct variable *var, union value *v);
static struct variable vartab[] = {
@@ -180,13 +182,15 @@ static struct variable vartab[] = {
.name = "errorexit",
.type = VART_STRING,
.sethook = errorexit_sethook,
- .typeconv = errormask_typeconv
+ .typeconv = errormask_typeconv,
+ .freehook = errormask_freehook
},
{
.name = "errormask",
.type = VART_STRING,
.sethook = errormask_sethook,
- .typeconv = errormask_typeconv
+ .typeconv = errormask_typeconv,
+ .freehook = errormask_freehook
},
{
.name = "timing",
@@ -510,6 +514,8 @@ variables_free (void)
if (vp->type == VART_STRING && (vp->flags & VARF_SET))
free (vp->v.string);
vp->v.string = NULL;
+ if (vp->freehook && vp->data)
+ vp->freehook (vp->data);
vp->flags &= ~VARF_SET;
}
}
@@ -809,6 +815,12 @@ errormask_typeconv (struct variable *var, int type, void **retptr)
return VAR_ERR_BADTYPE;
}
+static void
+errormask_freehook (void *data)
+{
+ free (data);
+}
+
static int
errorexit_sethook (struct variable *var, union value *v)
{

Return to:

Send suggestions and report system problems to the System administrator.