diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2004-11-21 19:57:17 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2004-11-21 19:57:17 +0000 |
commit | ec178bd6d49a002242bba0d0eaba9c8104c724ff (patch) | |
tree | beae973512e7618e7d615596a378c2ba1e1a0801 | |
parent | 70207ab18d1da41062d1527b0c5af927514b001f (diff) |
Fix some core dumps on malformed format strings. From KAMADA Ken'ichi
in NetBSD PR 28157 with extras, joint work with pat@. ok pat@ deraadt@
-rw-r--r-- | usr.bin/hexdump/parse.c | 62 |
1 files changed, 39 insertions, 23 deletions
diff --git a/usr.bin/hexdump/parse.c b/usr.bin/hexdump/parse.c index 0fbdc9b7e51..a4ec066befd 100644 --- a/usr.bin/hexdump/parse.c +++ b/usr.bin/hexdump/parse.c @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.c,v 1.13 2003/06/12 20:58:09 deraadt Exp $ */ +/* $OpenBSD: parse.c,v 1.14 2004/11/21 19:57:16 otto Exp $ */ /* $NetBSD: parse.c,v 1.12 2001/12/07 13:37:39 bjh21 Exp $ */ /* @@ -32,7 +32,7 @@ #ifndef lint /*static char sccsid[] = "from: @(#)parse.c 5.6 (Berkeley) 3/9/91";*/ -static char rcsid[] = "$OpenBSD: parse.c,v 1.13 2003/06/12 20:58:09 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: parse.c,v 1.14 2004/11/21 19:57:16 otto Exp $"; #endif /* not lint */ #include <sys/types.h> @@ -170,7 +170,7 @@ size(FS *fs) * skip any special chars -- save precision in * case it's a %s format. */ - while (strchr(spec + 1, *++fmt)); + while (*++fmt && strchr(spec + 1, *fmt)); if (*fmt == '.' && isdigit((unsigned char)*++fmt)) { prec = atoi(fmt); while (isdigit((unsigned char)*++fmt)); @@ -244,10 +244,10 @@ rewrite(FS *fs) if (fu->bcnt) { sokay = USEBCNT; /* Skip to conversion character. */ - for (++p1; strchr(spec, *p1); ++p1); + for (++p1; *p1 && strchr(spec, *p1); ++p1); } else { /* Skip any special chars, field width. */ - while (strchr(spec + 1, *++p1)); + while (*++p1 && strchr(spec + 1, *p1)); if (*p1 == '.' && isdigit((unsigned char)*++p1)) { sokay = USEPREC; @@ -258,7 +258,7 @@ rewrite(FS *fs) sokay = NOTOKAY; } - p2 = p1 + 1; /* Set end pointer. */ + p2 = *p1 ? p1 + 1 : p1; /* Set end pointer. */ cs[0] = *p1; /* Set conversion string. */ cs[1] = '\0'; @@ -280,11 +280,13 @@ rewrite(FS *fs) } break; case 'd': case 'i': - pr->flags = F_INT; - goto isint; case 'o': case 'u': case 'x': case 'X': - pr->flags = F_UINT; -isint: cs[2] = '\0'; + if (cs[0] == 'd' || cs[0] == 'i') + pr->flags = F_INT; + else + pr->flags = F_UINT; + + cs[2] = '\0'; cs[1] = cs[0]; cs[0] = 'q'; switch(fu->bcnt) { @@ -349,22 +351,26 @@ isint: cs[2] = '\0'; cs[2] = '\0'; break; default: - p1[3] = '\0'; + if (p1[2]) + p1[3] = '\0'; badconv(p1); } break; case 'c': - pr->flags = F_C; - /* cs[0] = 'c'; set in conv_c */ - goto isint2; case 'p': - pr->flags = F_P; - cs[0] = 'c'; - goto isint2; case 'u': - pr->flags = F_U; - /* cs[0] = 'c'; set in conv_u */ -isint2: switch(fu->bcnt) { + if (p1[1] == 'c') { + pr->flags = F_C; + /* cs[0] = 'c'; set in conv_c */ + } else if (p1[1] == 'p') { + pr->flags = F_P; + cs[0] = 'c'; + } else { + pr->flags = F_U; + /* cs[0] = 'c'; set in conv_u */ + } + + switch(fu->bcnt) { case 0: case 1: pr->bcnt = 1; break; @@ -374,12 +380,14 @@ isint2: switch(fu->bcnt) { } break; default: - p1[2] = '\0'; + if (p1[1]) + p1[2] = '\0'; badconv(p1); } break; default: - p1[1] = '\0'; + if (cs[0]) + p1[1] = '\0'; badconv(p1); } @@ -423,6 +431,8 @@ isint2: switch(fu->bcnt) { !(fu->flags&F_SETREP) && fu->bcnt) fu->reps += (blocksize - fs->bcnt) / fu->bcnt; if (fu->reps > 1) { + if (!fu->nextpr) + break; for (pr = fu->nextpr;; pr = pr->nextpr) if (!pr->nextpr) break; @@ -453,8 +463,12 @@ escape(char *p1) *p2 = *p1; break; } - if (*p1 == '\\') + if (*p1 == '\\') { switch(*++p1) { + case '\0': + *p2++ = '\\'; + *p2 = '\0'; + return; /* incomplete escape sequence */ case 'a': /* *p2 = '\a'; */ *p2 = '\007'; @@ -481,6 +495,8 @@ escape(char *p1) *p2 = *p1; break; } + } else + *p2 = *p1; } } |