diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2012-01-05 21:46:16 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2012-01-05 21:46:16 +0000 |
commit | e7734894cb54fea075311bd05348f9d256f45d95 (patch) | |
tree | ff82f6cdc3534cccbaae3d5e62d530a7475f3cc3 /usr.bin | |
parent | dd36afb6a78cfffb1b4c5b9dcf200262bd4ada41 (diff) |
When iterating a TAILQ list replacing elements,
get a pointer to the next element before freeing the previous one,
do not access free'd pointers. Problem found the hard way
by fgsch@ running "man -a x" with malloc.conf -> S on amd64.
ok deraadt@
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/man/man.c | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/usr.bin/man/man.c b/usr.bin/man/man.c index f833d35c6c8..56143bdda25 100644 --- a/usr.bin/man/man.c +++ b/usr.bin/man/man.c @@ -1,8 +1,8 @@ -/* $OpenBSD: man.c,v 1.43 2011/07/07 04:24:35 schwarze Exp $ */ +/* $OpenBSD: man.c,v 1.44 2012/01/05 21:46:15 schwarze Exp $ */ /* $NetBSD: man.c,v 1.7 1995/09/28 06:05:34 tls Exp $ */ /* - * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2010, 2011, 2012 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -443,7 +443,7 @@ manual(char *page, TAG *tag, glob_t *pg) /* Expand the search path. */ if (f_all != f_where) { e_tag = tag == NULL ? NULL : TAILQ_FIRST(&tag->list); - for (; e_tag != NULL; e_tag = TAILQ_NEXT(e_tag, q)) { + while (e_tag != NULL) { if (glob(e_tag->s, GLOB_BRACE | GLOB_NOSORT, NULL, pg)) { /* No GLOB_NOMATCH here due to {arch,}. */ @@ -451,17 +451,18 @@ manual(char *page, TAG *tag, glob_t *pg) (void)cleanup(0); exit(1); } - ep = e_tag; for (cnt = 0; cnt < pg->gl_pathc; cnt++) { - if ((e_tag = malloc(sizeof(ENTRY))) == NULL || - (e_tag->s = strdup(pg->gl_pathv[cnt])) == + if ((ep = malloc(sizeof(ENTRY))) == NULL || + (ep->s = strdup(pg->gl_pathv[cnt])) == NULL) { warn(NULL); (void)cleanup(0); exit(1); } - TAILQ_INSERT_BEFORE(ep, e_tag, q); + TAILQ_INSERT_BEFORE(e_tag, ep, q); } + ep = e_tag; + e_tag = TAILQ_NEXT(e_tag, q); free(ep->s); TAILQ_REMOVE(&tag->list, ep, q); free(ep); |