diff options
author | Matt Barden <matt.barden@nexenta.com> | 2017-11-29 20:06:37 -0500 |
---|---|---|
committer | Dan McDonald <danmcd@joyent.com> | 2017-12-08 15:19:52 -0500 |
commit | e41ba543c907a7f890945c577bac3566017e4162 (patch) | |
tree | 3e2f7ee1b7e15ba6c80ccaded3f6574c5a48e645 /usr/src | |
parent | 281819e5f8b19cd8627541a22d261906fd190276 (diff) | |
download | illumos-gate-e41ba543c907a7f890945c577bac3566017e4162.tar.gz |
8868 /usr/xpg4/bin/grep dumps core in find_nl()
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src')
7 files changed, 107 insertions, 38 deletions
diff --git a/usr/src/cmd/grep_xpg4/grep.c b/usr/src/cmd/grep_xpg4/grep.c index 14156dd0cd..cb49a807c9 100644 --- a/usr/src/cmd/grep_xpg4/grep.c +++ b/usr/src/cmd/grep_xpg4/grep.c @@ -87,7 +87,7 @@ static int matched = 0; /* return of the grep() */ static int errors = 0; /* count of errors */ static uchar_t fgrep = 0; /* Invoked as fgrep */ static uchar_t egrep = 0; /* Invoked as egrep */ -static uchar_t nvflag = 1; /* Print matching lines */ +static boolean_t nvflag = B_TRUE; /* Print matching lines */ static uchar_t cflag; /* Count of matches */ static uchar_t iflag; /* Case insensitve matching */ static uchar_t Hflag; /* Precede lines by file name */ @@ -204,7 +204,7 @@ main(int argc, char **argv) unsigned long tval; switch (c) { case 'v': /* POSIX: negate matches */ - nvflag = 0; + nvflag = B_FALSE; break; case 'c': /* POSIX: write count */ @@ -344,9 +344,9 @@ main(int argc, char **argv) exit(2); } if (tval) { - if (!(conflag & BEFORE)) + if ((conflag & BEFORE) == 0) conblen = tval; - if (!(conflag & AFTER)) + if ((conflag & AFTER) == 0) conalen = tval; conflag = CONTEXT; } @@ -810,13 +810,14 @@ fixpatterns(void) * - no negating the output (nvflag) * - only one pattern (npatterns == 1) * - non zero length pattern (strlen(patterns->pattern) != 0) - * - no context required (!conflag) + * - no context required (conflag == 0) * * It's guaranteed patterns->pattern is still alive * when Fflag && !mblocale. */ use_bmg = Fflag && !mblocale && !iflag && !nflag && nvflag && - (npatterns == 1) && (strlen(patterns->pattern) != 0) && !conflag; + (npatterns == 1) && (strlen(patterns->pattern) != 0) && + conflag == 0; } /* @@ -908,6 +909,7 @@ grep(int fd, const char *fn) char *matchptr = NULL; int conaprnt = 0, conbprnt = 0, lastmatch = 0; boolean_t nearmatch; /* w/in N+1 of last match */ + boolean_t havematch = B_FALSE; /* have a match in context */ size_t prntlen; if (patterns == NULL) @@ -938,7 +940,7 @@ grep(int fd, const char *fn) } } - if (conflag && (conbuf == NULL)) { + if (conflag != 0 && (conbuf == NULL)) { conbuflen = BUFSIZE; if ((conbuf = malloc(BUFSIZE+1)) == NULL) { (void) fprintf(stderr, gettext("%s: out of memory\n"), @@ -956,7 +958,6 @@ grep(int fd, const char *fn) for (; ; ) { long count; off_t offset = 0; - int rv = REG_NOMATCH; char separate; boolean_t last_ctx = B_FALSE, eof = B_FALSE; @@ -965,8 +966,10 @@ grep(int fd, const char *fn) * If no data in the buffer, reset ptr */ ptr = prntbuf; - if (conptr == NULL) - conptrend = conptr = conbuf; + if (conflag != 0 && conptr == NULL) { + conptr = conbuf; + conptrend = conptr - 1; + } } if (ptr == prntbuf) { /* @@ -995,8 +998,9 @@ grep(int fd, const char *fn) if (data_len == 0) { /* end of file already reached */ - if (conflag) { - *conptrend = '\n'; + if (conflag != 0) { + if (conptrend >= conptr) + *conptrend = '\n'; last_ctx = B_TRUE; goto L_next_line; } else { @@ -1060,6 +1064,10 @@ L_start_process: * End of the chunk: ptr + data_len * Beginning of the line: ptr * End of the line: ptrend + * + * conptr: Beginning of the context. + * conptrend: If context is empty, conptr - 1 (invalid memory). + * Otherwise, Last newline in the context. */ if (use_bmg) { @@ -1172,7 +1180,6 @@ L_start_process: wcscmp(outline, pp->wpattern) == 0) { /* matched */ - rv = REG_OK; break; } } @@ -1181,7 +1188,6 @@ L_start_process: if (wcswcs(outline, pp->wpattern) != NULL) { /* matched */ - rv = REG_OK; break; } } @@ -1200,7 +1206,6 @@ L_start_process: if (fptr[0] == pp->pattern[0] && strcmp(fptr, pp->pattern) == 0) { /* matched */ - rv = REG_OK; break; } } @@ -1208,7 +1213,6 @@ L_start_process: for (pp = patterns; pp; pp = pp->next) { if (strstr(fptr, pp->pattern) != NULL) { /* matched */ - rv = REG_OK; break; } } @@ -1216,6 +1220,8 @@ L_start_process: } else { /* grep or egrep */ for (pp = patterns; pp; pp = pp->next) { + int rv; + rv = regexec(&pp->re, ptr, 0, NULL, 0); if (rv == REG_OK) { /* matched */ @@ -1271,11 +1277,12 @@ L_start_process: * logic. */ - if (!conflag) + if (conflag == 0) goto L_next_line; /* Do we have room to add this line to the context buffer? */ - if (line_len > conbuflen - (conptrend - conbuf)) { + if ((line_len + 1) > (conbuflen - + (conptrend >= conptr) ? conptrend - conbuf : 0)) { char *oldconbuf = conbuf; char *oldconptr = conptr; long tmp = matchptr - conptr; @@ -1301,15 +1308,14 @@ L_start_process: if (matchptr) matchptr = conptr + tmp; } - (void) memcpy((conptrend > conptr) ? - conptrend + 1 : conptrend, ptr, line_len); - conptrend += line_len + (conptrend > conptr); + (void) memcpy(conptrend + 1, ptr, line_len); + conptrend += line_len + 1; *conptrend = '\n'; - if (!nvflag == rv) { + if (nvflag == (pp != NULL)) { /* matched */ - if (lastmatch) { - if (conflag & AFTER) { + if (havematch) { + if ((conflag & AFTER) != 0) { conaprnt = 1; nextend = conptrend; conptrend = conptr + lastmatch; @@ -1329,11 +1335,12 @@ L_start_process: conbprnt = 1; lastmatch = conptrend - conptr; + havematch = B_TRUE; goto L_next_line; } - if (!lastmatch) { - if (conflag & BEFORE) { + if (!havematch) { + if ((conflag & BEFORE) != 0) { if (conbcnt >= conblen) { char *tmp = conptr; conptr = find_nl(conptr, @@ -1363,7 +1370,7 @@ L_next_line: if (!last_ctx && nvflag == (pp != NULL)) { matches++; if (!nextend) - matchptr = conflag ? conptrend : ptrend; + matchptr = (conflag != 0) ? conptrend : ptrend; } /* @@ -1375,7 +1382,7 @@ L_next_line: * either at the end of the data stream, or we've previously * declared that we want to print for a particular context. */ - if (lastmatch && (eof || conaprnt || conbprnt)) { + if (havematch && (eof || conaprnt || conbprnt)) { /* * We'd normally do this earlier, but we had to @@ -1385,13 +1392,13 @@ L_next_line: conptrend = nextend; prntlen = conptrend - conptr + 1; - prntptrend = prntptr = conptr; + prntptr = conptr; if (conmatches++ && nearmatch && !cflag) (void) fwrite("--\n", 1, 3, stdout); - } else if (!conflag && nvflag == (pp != NULL)) { + } else if (conflag == 0 && nvflag == (pp != NULL)) { *ptrend = '\n'; prntlen = line_len + 1; - prntptrend = prntptr = ptr; + prntptr = ptr; linenum = lineno; blkoffset = line_offset; } else if (eof) { @@ -1402,7 +1409,9 @@ L_next_line: goto L_skip_line; } - while ((prntptrend = find_nl(prntptrend+1, prntlen)) != NULL) { + prntptrend = prntptr - 1; + while ((prntptrend = find_nl(prntptrend + 1, + prntlen)) != NULL) { /* * GNU grep uses '-' for context lines and ':' for @@ -1468,7 +1477,7 @@ L_next_line: /* * Update context buffer and variables post-print */ - if (conflag) { + if (conflag != 0) { conptr = conbuf; conaprnt = conbprnt = 0; nearmatch = B_FALSE; @@ -1482,10 +1491,12 @@ L_next_line: matchptr = conptrend; linenum = lineno; lastmatch = conptrend - conptr; + havematch = B_TRUE; } else { - conptrend = conptr; + conptrend = conptr - 1; conacnt = 0; lastmatch = 0; + havematch = B_FALSE; } nextptr = nextend = NULL; } diff --git a/usr/src/test/util-tests/tests/grep_xpg4/files/gout63 b/usr/src/test/util-tests/tests/grep_xpg4/files/gout63 new file mode 100644 index 0000000000..ee091284ad --- /dev/null +++ b/usr/src/test/util-tests/tests/grep_xpg4/files/gout63 @@ -0,0 +1,4 @@ +1: +2: +3:a +4: diff --git a/usr/src/test/util-tests/tests/grep_xpg4/files/gout64 b/usr/src/test/util-tests/tests/grep_xpg4/files/gout64 new file mode 100644 index 0000000000..6b673e8843 --- /dev/null +++ b/usr/src/test/util-tests/tests/grep_xpg4/files/gout64 @@ -0,0 +1,2 @@ + +a diff --git a/usr/src/test/util-tests/tests/grep_xpg4/files/gout65 b/usr/src/test/util-tests/tests/grep_xpg4/files/gout65 new file mode 100644 index 0000000000..3b08f8d5c4 --- /dev/null +++ b/usr/src/test/util-tests/tests/grep_xpg4/files/gout65 @@ -0,0 +1,4 @@ + + +a + diff --git a/usr/src/test/util-tests/tests/grep_xpg4/files/gout66 b/usr/src/test/util-tests/tests/grep_xpg4/files/gout66 new file mode 100644 index 0000000000..3b08f8d5c4 --- /dev/null +++ b/usr/src/test/util-tests/tests/grep_xpg4/files/gout66 @@ -0,0 +1,4 @@ + + +a + diff --git a/usr/src/test/util-tests/tests/grep_xpg4/files/testnl b/usr/src/test/util-tests/tests/grep_xpg4/files/testnl new file mode 100644 index 0000000000..3b08f8d5c4 --- /dev/null +++ b/usr/src/test/util-tests/tests/grep_xpg4/files/testnl @@ -0,0 +1,4 @@ + + +a + diff --git a/usr/src/test/util-tests/tests/grep_xpg4/grep_test.ksh b/usr/src/test/util-tests/tests/grep_xpg4/grep_test.ksh index 4e5a4206af..a544bd789c 100644 --- a/usr/src/test/util-tests/tests/grep_xpg4/grep_test.ksh +++ b/usr/src/test/util-tests/tests/grep_xpg4/grep_test.ksh @@ -12,7 +12,7 @@ # # -# Copyright 2014 Nexenta Systems, Inc. All rights reserved. +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. # XGREP=${XGREP:=/usr/xpg4/bin/grep} @@ -93,13 +93,53 @@ cd $FILEDIR i=0 while read flags; do - print -n "grep $flags: " + print -n "test $i: grep $flags: " $XGREP $flags a test0 test1 test2 \ test3 test4 test5 test6 \ test7 > out - if [[ $? -ne 0 ]]; then - fail "failed on exit" + err="$?" + if [[ $err -ne 0 ]]; then + fail "failed on exit: $err" elif [ -n "$(diff out gout$i)" ]; then + print "$(diff out gout$i)" + fail "output is different" + fi + echo "passed" + ((i++)) +done < /tmp/flags + +FLAGS2="-nE" + +echo "$FLAGS2" > /tmp/flags + +while read flags; do + print -n "test $i: grep $flags: " + $XGREP $flags ".*" testnl > out + err="$?" + if [[ $err -ne 0 ]]; then + fail "failed on exit: $err" + elif [ -n "$(diff out gout$i)" ]; then + print "$(diff out gout$i)" + fail "output is different" + fi + echo "passed" + ((i++)) +done < /tmp/flags + +FLAGS3="-B 1 +-vA 1 +-vB 1" + +echo "$FLAGS3" > /tmp/flags + +while read flags; do + print -n "test $i: grep $flags: " + $XGREP $flags a testnl > out + err="$?" + if [[ $err -ne 0 ]]; then + fail "failed on exit: $err" + elif [ -n "$(diff out gout$i)" ]; then + print "$(diff out gout$i)" fail "output is different" fi echo "passed" |