From owner-svn-src-all@FreeBSD.ORG Tue Apr 7 18:06:47 2015 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 6D3B5FD; Tue, 7 Apr 2015 18:06:47 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 586D2C44; Tue, 7 Apr 2015 18:06:47 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t37I6lxb065013; Tue, 7 Apr 2015 18:06:47 GMT (envelope-from pfg@FreeBSD.org) Received: (from pfg@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t37I6lxo065011; Tue, 7 Apr 2015 18:06:47 GMT (envelope-from pfg@FreeBSD.org) Message-Id: <201504071806.t37I6lxo065011@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: pfg set sender to pfg@FreeBSD.org using -f From: "Pedro F. Giffuni" Date: Tue, 7 Apr 2015 18:06:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r281216 - head/usr.bin/patch X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 Apr 2015 18:06:47 -0000 Author: pfg Date: Tue Apr 7 18:06:46 2015 New Revision: 281216 URL: https://svnweb.freebsd.org/changeset/base/281216 Log: patch: Bring small updates from OpenBSD Prevent null pointer dereference on empty input files when diff requires a specific version. Fix division by zero for files with long lines (> 1024) in Plan B mode by supporting arbitrarily long lines. Obtained from: OpenBSD (CVS Rev 1.41, 1.42) MFC after: 1 week Modified: head/usr.bin/patch/inp.c Modified: head/usr.bin/patch/inp.c ============================================================================== --- head/usr.bin/patch/inp.c Tue Apr 7 18:04:18 2015 (r281215) +++ head/usr.bin/patch/inp.c Tue Apr 7 18:06:46 2015 (r281216) @@ -57,8 +57,9 @@ static char empty_line[] = { '\0' }; static int tifd = -1; /* plan b virtual string array */ static char *tibuf[2]; /* plan b buffers */ static LINENUM tiline[2] = {-1, -1}; /* 1st line in each buffer */ -static LINENUM lines_per_buf; /* how many lines per buffer */ -static int tireclen; /* length of records in tmp file */ +static size_t lines_per_buf; /* how many lines per buffer */ +static size_t tibuflen; /* plan b buffer length */ +static size_t tireclen; /* length of records in tmp file */ static bool rev_in_string(const char *); static bool reallocate_lines(size_t *); @@ -319,7 +320,7 @@ plan_a(const char *filename) /* now check for revision, if any */ if (revision != NULL) { - if (!rev_in_string(i_womp)) { + if (i_womp == NULL || !rev_in_string(i_womp)) { if (force) { if (verbose) say("Warning: this file doesn't appear " @@ -349,8 +350,8 @@ static void plan_b(const char *filename) { FILE *ifp; - size_t i = 0, j, maxlen = 1; - char *p; + size_t i = 0, j, len, maxlen = 1; + char *lbuf = NULL, *p; bool found_revision = (revision == NULL); using_plan_a = false; @@ -359,15 +360,28 @@ plan_b(const char *filename) unlink(TMPINNAME); if ((tifd = open(TMPINNAME, O_EXCL | O_CREAT | O_WRONLY, 0666)) < 0) pfatal("can't open file %s", TMPINNAME); - while (fgets(buf, buf_size, ifp) != NULL) { - if (revision != NULL && !found_revision && rev_in_string(buf)) + while ((p = fgetln(ifp, &len)) != NULL) { + if (p[len - 1] == '\n') + p[len - 1] = '\0'; + else { + /* EOF without EOL, copy and add the NUL */ + if ((lbuf = malloc(len + 1)) == NULL) + fatal("out of memory\n"); + memcpy(lbuf, p, len); + lbuf[len] = '\0'; + p = lbuf; + + last_line_missing_eol = true; + len++; + } + if (revision != NULL && !found_revision && rev_in_string(p)) found_revision = true; - if ((i = strlen(buf)) > maxlen) - maxlen = i; /* find longest line */ + if (len > maxlen) + maxlen = len; /* find longest line */ } - last_line_missing_eol = i > 0 && buf[i - 1] != '\n'; - if (last_line_missing_eol && maxlen == i) - maxlen++; + free(lbuf); + if (ferror(ifp)) + pfatal("can't read file %s", filename); if (revision != NULL) { if (!found_revision) { @@ -392,23 +406,26 @@ plan_b(const char *filename) revision); } fseek(ifp, 0L, SEEK_SET); /* rewind file */ - lines_per_buf = BUFFERSIZE / maxlen; tireclen = maxlen; - tibuf[0] = malloc(BUFFERSIZE + 1); + tibuflen = maxlen > BUFFERSIZE ? maxlen : BUFFERSIZE; + lines_per_buf = tibuflen / maxlen; + tibuf[0] = malloc(tibuflen + 1); if (tibuf[0] == NULL) fatal("out of memory\n"); - tibuf[1] = malloc(BUFFERSIZE + 1); + tibuf[1] = malloc(tibuflen + 1); if (tibuf[1] == NULL) fatal("out of memory\n"); for (i = 1;; i++) { p = tibuf[0] + maxlen * (i % lines_per_buf); if (i % lines_per_buf == 0) /* new block */ - if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE) + if (write(tifd, tibuf[0], tibuflen) != + (ssize_t) tibuflen) pfatal("can't write temp file"); if (fgets(p, maxlen + 1, ifp) == NULL) { input_lines = i - 1; if (i % lines_per_buf != 0) - if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE) + if (write(tifd, tibuf[0], tibuflen) != + (ssize_t) tibuflen) pfatal("can't write temp file"); break; } @@ -450,10 +467,11 @@ ifetch(LINENUM line, int whichbuf) tiline[whichbuf] = baseline; if (lseek(tifd, (off_t) (baseline / lines_per_buf * - BUFFERSIZE), SEEK_SET) < 0) + tibuflen), SEEK_SET) < 0) pfatal("cannot seek in the temporary input file"); - if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0) + if (read(tifd, tibuf[whichbuf], tibuflen) != + (ssize_t) tibuflen) pfatal("error reading tmp file %s", TMPINNAME); } return tibuf[whichbuf] + (tireclen * offline);