From owner-svn-src-head@FreeBSD.ORG Mon Apr 30 01:08:19 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1498E106566B; Mon, 30 Apr 2012 01:08:19 +0000 (UTC) (envelope-from das@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id EA69E8FC08; Mon, 30 Apr 2012 01:08:18 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q3U18Ifc041046; Mon, 30 Apr 2012 01:08:18 GMT (envelope-from das@svn.freebsd.org) Received: (from das@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q3U18IKb041043; Mon, 30 Apr 2012 01:08:18 GMT (envelope-from das@svn.freebsd.org) Message-Id: <201204300108.q3U18IKb041043@svn.freebsd.org> From: David Schultz Date: Mon, 30 Apr 2012 01:08:18 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r234825 - head/lib/libc/stdio X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 30 Apr 2012 01:08:19 -0000 Author: das Date: Mon Apr 30 01:08:18 2012 New Revision: 234825 URL: http://svn.freebsd.org/changeset/base/234825 Log: Fix a bug in *wscanf's handling of non-wide %s, %c, and %[ conversions. Both the specification and the documentation say the width is interpreted as the max number of wide characters to read, but the implementation was interpreting it as the number of bytes to convert. (See also r105317.) This change has security implications for any applications that depend on the buggy behavior, but the impact in practice is probably nil. Any such application would already be buggy on other platforms that get the semantics right. Also, these conversions are rarely used; %ls, %lc, and %l[ are more appropriate. Modified: head/lib/libc/stdio/vfwscanf.c Modified: head/lib/libc/stdio/vfwscanf.c ============================================================================== --- head/lib/libc/stdio/vfwscanf.c Mon Apr 30 00:54:10 2012 (r234824) +++ head/lib/libc/stdio/vfwscanf.c Mon Apr 30 01:08:18 2012 (r234825) @@ -144,29 +144,16 @@ convert_char(FILE *fp, char * __restrict size_t nconv; wint_t wi; int n; - char mbbuf[MB_LEN_MAX]; n = 0; mbs = initial_mbs; - while (width != 0 && (wi = __fgetwc(fp, locale)) != WEOF) { - if (width >= MB_CUR_MAX && mbp != SUPPRESS_PTR) { + while (width-- != 0 && (wi = __fgetwc(fp, locale)) != WEOF) { + if (mbp != SUPPRESS_PTR) { nconv = wcrtomb(mbp, wi, &mbs); if (nconv == (size_t)-1) return (-1); - } else { - nconv = wcrtomb(mbbuf, wi, &mbs); - if (nconv == (size_t)-1) - return (-1); - if (nconv > width) { - __ungetwc(wi, fp, locale); - break; - } - if (mbp != SUPPRESS_PTR) - memcpy(mbp, mbbuf, nconv); - } - if (mbp != SUPPRESS_PTR) mbp += nconv; - width -= nconv; + } n++; } if (n == 0) @@ -199,28 +186,17 @@ convert_ccl(FILE *fp, char * __restrict size_t nconv; wint_t wi; int n; - char mbbuf[MB_LEN_MAX]; n = 0; mbs = initial_mbs; while ((wi = __fgetwc(fp, locale)) != WEOF && - width != 0 && inccl(ccl, wi)) { - if (width >= MB_CUR_MAX && mbp != SUPPRESS_PTR) { + width-- != 0 && inccl(ccl, wi)) { + if (mbp != SUPPRESS_PTR) { nconv = wcrtomb(mbp, wi, &mbs); if (nconv == (size_t)-1) return (-1); - } else { - nconv = wcrtomb(mbbuf, wi, &mbs); - if (nconv == (size_t)-1) - return (-1); - if (nconv > width) - break; - if (mbp != SUPPRESS_PTR) - memcpy(mbp, mbbuf, nconv); - } - if (mbp != SUPPRESS_PTR) mbp += nconv; - width -= nconv; + } n++; } if (wi != WEOF) @@ -267,28 +243,17 @@ convert_string(FILE *fp, char * __restri size_t nconv; wint_t wi; int nread; - char mbbuf[MB_LEN_MAX]; mbs = initial_mbs; nread = 0; - while ((wi = __fgetwc(fp, locale)) != WEOF && width != 0 && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && !iswspace(wi)) { - if (width >= MB_CUR_MAX && mbp != SUPPRESS_PTR) { + if (mbp != SUPPRESS_PTR) { nconv = wcrtomb(mbp, wi, &mbs); if (nconv == (size_t)-1) return (-1); - } else { - nconv = wcrtomb(mbbuf, wi, &mbs); - if (nconv == (size_t)-1) - return (-1); - if (nconv > width) - break; - if (mbp != SUPPRESS_PTR) - memcpy(mbp, mbbuf, nconv); - } - if (mbp != SUPPRESS_PTR) mbp += nconv; - width -= nconv; + } nread++; } if (wi != WEOF)