Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 8 Sep 2016 06:53:18 +0000 (UTC)
From:      "Andrey A. Chernov" <ache@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r305582 - stable/11/lib/libc/stdio
Message-ID:  <201609080653.u886rIYa000418@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ache
Date: Thu Sep  8 06:53:18 2016
New Revision: 305582
URL: https://svnweb.freebsd.org/changeset/base/305582

Log:
  MFC r305406,r305409,r305412
  
  1) Fix errors handling.
  
  2) Prevent out of bounds access to ws[-1] (passed buffer) which happens
  when the first mb sequence is incomplete and there are not enougn chars in
  the read buffer. ws[-1] may lead to memory faults or false results, in
  case the memory here contains '\n'.
  
  3) Fix n == 1 case. Here should be no physical read (fill buffer) attempt
  (we read n - 1 chars with the room for NUL, see fgets()),
  and no NULL return.

Modified:
  stable/11/lib/libc/stdio/fgetws.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/lib/libc/stdio/fgetws.c
==============================================================================
--- stable/11/lib/libc/stdio/fgetws.c	Thu Sep  8 06:42:30 2016	(r305581)
+++ stable/11/lib/libc/stdio/fgetws.c	Thu Sep  8 06:53:18 2016	(r305582)
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
 wchar_t *
 fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale)
 {
+	int sret;
 	wchar_t *wsp;
 	size_t nconv;
 	const char *src;
@@ -56,23 +57,31 @@ fgetws_l(wchar_t * __restrict ws, int n,
 	ORIENT(fp, 1);
 
 	if (n <= 0) {
+		fp->_flags |= __SERR;
 		errno = EINVAL;
 		goto error;
 	}
 
+	wsp = ws;
+	if (n == 1)
+		goto ok;
+
 	if (fp->_r <= 0 && __srefill(fp))
-		/* EOF */
+		/* EOF or ferror */
 		goto error;
-	wsp = ws;
+
+	sret = 0;
 	do {
 		src = fp->_p;
 		nl = memchr(fp->_p, '\n', fp->_r);
 		nconv = l->__mbsnrtowcs(wsp, &src,
 		    nl != NULL ? (nl - fp->_p + 1) : fp->_r,
 		    n - 1, &fp->_mbstate);
-		if (nconv == (size_t)-1)
+		if (nconv == (size_t)-1) {
 			/* Conversion error */
+			fp->_flags |= __SERR;
 			goto error;
+		}
 		if (src == NULL) {
 			/*
 			 * We hit a null byte. Increment the character count,
@@ -88,23 +97,30 @@ fgetws_l(wchar_t * __restrict ws, int n,
 		fp->_p = (unsigned char *)src;
 		n -= nconv;
 		wsp += nconv;
-	} while (wsp[-1] != L'\n' && n > 1 && (fp->_r > 0 ||
-	    __srefill(fp) == 0));
-	if (wsp == ws)
-		/* EOF */
+	} while ((wsp == ws || wsp[-1] != L'\n') && n > 1 && (fp->_r > 0 ||
+	    (sret = __srefill(fp)) == 0));
+	if (sret && !__sfeof(fp))
+		/* ferror */
 		goto error;
-	if (!l->__mbsinit(&fp->_mbstate))
+	if (!l->__mbsinit(&fp->_mbstate)) {
 		/* Incomplete character */
+		fp->_flags |= __SERR;
+		errno = EILSEQ;
 		goto error;
+	}
+	if (wsp == ws)
+		/* EOF */
+		goto error;
+ok:
 	*wsp = L'\0';
 	FUNLOCKFILE(fp);
-
 	return (ws);
 
 error:
 	FUNLOCKFILE(fp);
 	return (NULL);
 }
+
 wchar_t *
 fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp)
 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201609080653.u886rIYa000418>