allow add_mime to fail

add_mime nows allocate dinamically copies of the passed strings, so
that we can actually free what we parse from the config file.

This matters a lot especially with lengthy `types' block: strings that
reach the internal mapping are never free'd, so every manual addition
is leaked.
This commit is contained in:
Omar Polo 2022-04-08 13:44:49 +00:00
parent aa6b8cf8ac
commit d8d170aa5e
4 changed files with 61 additions and 22 deletions

4
gmid.c
View File

@ -251,7 +251,8 @@ static int
listener_main(struct imsgbuf *ibuf)
{
drop_priv();
load_default_mime(&conf.mime);
if (load_default_mime(&conf.mime) == -1)
fatal("load_default_mime: %s", strerror(errno));
load_vhosts();
loop(ctx, sock4, sock6, ibuf);
return 0;
@ -286,6 +287,7 @@ free_config(void)
v = conf.verbose;
free_mime(&conf.mime);
free(conf.chroot);
free(conf.user);
memset(&conf, 0, sizeof(conf));

9
gmid.h
View File

@ -176,8 +176,8 @@ struct vhost {
};
struct etm { /* extension to mime */
const char *mime;
const char *ext;
char *mime;
char *ext;
};
struct mime {
@ -353,9 +353,10 @@ int logger_main(int, struct imsgbuf*);
/* mime.c */
void init_mime(struct mime*);
void add_mime(struct mime*, const char*, const char*);
void load_default_mime(struct mime*);
int add_mime(struct mime*, const char*, const char*);
int load_default_mime(struct mime*);
const char *mime(struct vhost*, const char*);
void free_mime(struct mime *);
/* server.c */
extern int shutting_down;

59
mime.c
View File

@ -32,30 +32,44 @@ init_mime(struct mime *mime)
}
/* register mime for the given extension */
void
int
add_mime(struct mime *mime, const char *mt, const char *ext)
{
size_t oldcap;
char *mimetype, *extension;
struct etm *t;
size_t newcap;
if (mime->len == mime->cap) {
oldcap = mime->cap;
mime->cap *= 1.5;
mime->t = recallocarray(mime->t, oldcap, mime->cap,
newcap = mime->cap * 1.5;
t = recallocarray(mime->t, mime->cap, newcap,
sizeof(struct etm));
if (mime->t == NULL)
err(1, "recallocarray");
if (t == NULL)
return -1;
mime->t = t;
mime->cap = newcap;
}
mime->t[mime->len].mime = mt;
mime->t[mime->len].ext = ext;
if ((mimetype = strdup(mt)) == NULL)
return -1;
if ((extension = strdup(ext)) == NULL) {
free(mimetype);
return -1;
}
mime->t[mime->len].mime = mimetype;
mime->t[mime->len].ext = extension;
mime->len++;
return 0;
}
/* load a default set of common mime-extension associations */
void
int
load_default_mime(struct mime *mime)
{
const struct etm *i, m[] = {
const struct mapping {
const char *mime;
const char *ext;
} m[] = {
{"application/pdf", "pdf"},
{"image/gif", "gif"},
{"image/jpeg", "jpg"},
@ -71,10 +85,14 @@ load_default_mime(struct mime *mime)
{"text/x-patch", "patch"},
{"text/xml", "xml"},
{NULL, NULL}
};
}, *i;
for (i = m; i->mime != NULL; ++i)
add_mime(mime, i->mime, i->ext);
for (i = m; i->mime != NULL; ++i) {
if (add_mime(mime, i->mime, i->ext) == -1)
return -1;
}
return 0;
}
static const char *
@ -110,3 +128,16 @@ mime(struct vhost *host, const char *path)
return def;
}
void
free_mime(struct mime *m)
{
struct etm *t;
for (t = m->t; t->mime != NULL; ++t) {
free(t->mime);
free(t->ext);
}
free(m->t);
}

11
parse.y
View File

@ -219,13 +219,15 @@ option : CHROOT string { conf.chroot = $2; }
yywarn("`mime MIME EXT' is deprecated and will be "
"removed in a future version, please use the new "
"`types' block.");
add_mime(&conf.mime, $2, $3);
if (add_mime(&conf.mime, $2, $3) == -1)
err(1, "add_mime");
}
| MAP string TOEXT string {
yywarn("`map mime to-ext' is deprecated and will be "
"removed in a future version, please use the new "
"`types' block.");
add_mime(&conf.mime, $2, $4);
if (add_mime(&conf.mime, $2, $4) == -1)
err(1, "add_mime");
}
| PORT NUM { conf.port = check_port_num($2); }
| PREFORK NUM { conf.prefork = check_prefork_num($2); }
@ -488,7 +490,10 @@ medianames_l : medianames_l medianamesl
| medianamesl
;
medianamesl : numberstring { add_mime(&conf.mime, current_media, $1); }
medianamesl : numberstring {
if (add_mime(&conf.mime, current_media, $1) == -1)
err(1, "add_mime");
}
;
nl : '\n' optnl