Date: Thu, 30 Mar 2000 19:03:47 +0200 (CEST) From: mikko@dynas.se To: FreeBSD-gnats-submit@freebsd.org Subject: bin/17694: wcstombs() and mbstowcs() unable to handle NULL argument Message-ID: <200003301703.TAA00862@mt.dynas.se>
next in thread | raw e-mail | index | archive | help
>Number: 17694 >Category: bin >Synopsis: wcstombs(), mbstowcs() not complying with standard >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Mar 30 09:50:01 PST 2000 >Closed-Date: >Last-Modified: >Originator: Mikko Työläjärvi >Release: FreeBSD 5.0-CURRENT i386 >Organization: >Environment: FreeBSD 4.0 and 5.x >Description: Looks like these two functions are supposed to be able to take a NULL destination pointer (the first one), in which case they should return the length required to do the actual copy. Stubled across this whilst porting code that made use of this feature to figure out how much memory to allocate. C.f. Solaris man-pages (e.g. at docs.sun.com) and "Single UNIX Specification" at <http://www.opengroup.org/onlinepubs/007908799/xsh/mbstowcs.html> "If s is a null pointer, wcstombs() returns the length required to convert the entire array regardless of the value of n, but no values are stored. function returns the number of bytes required for the character array." ["s" is the output string] and "If pwcs is a null pointer, mbstowcs() returns the length required to convert the entire array regardless of the value of n, but no values are stored." ["pwcs" is the output string] >How-To-Repeat: #include <stdlib.h> #include <locale.h> int main(int argc, char **argv) { int len; setlocale(LC_ALL, "C"); len = mbstowcs(NULL, "SE", 0); printf("len = %d (should be 2)\n", len); } >Fix: Suggested patch (actually somewhat tested with different arguments, but not in real multibyte locales, and relies on all flavours of sputrune being able to handle NULL args): --- ansi.c.org Thu Mar 30 18:45:34 2000 +++ ansi.c Thu Mar 30 18:44:57 2000 @@ -103,16 +103,22 @@ size_t n; { char const *e; + wchar_t wc; int cnt = 0; - if (!pwcs || !s) + if (!s) return (-1); - while (n-- > 0) { - *pwcs = sgetrune(s, MB_LEN_MAX, &e); - if (*pwcs == _INVALID_RUNE) + for (;;) { + wc = sgetrune(s, MB_LEN_MAX, &e); + if (wc == _INVALID_RUNE) return (-1); - if (*pwcs++ == 0) + if (pwcs) { + if (n-- <= 0) + break; + *pwcs++ = wc; + } + if (wc == 0) break; s = e; ++cnt; @@ -129,23 +135,27 @@ char *e; int cnt, nb; - if (!pwcs || !s || n > INT_MAX) + if (!pwcs || n > INT_MAX) return (-1); - nb = n; cnt = 0; - while (nb > 0) { + for (;;) { if (*pwcs == 0) { - *s = 0; + if (s) + *s = 0; break; } - if (!sputrune(*pwcs++, s, nb, &e)) + if (!(nb = sputrune(*pwcs++, s, nb, &e))) return (-1); /* encoding error */ if (!e) /* too long */ return (cnt); - cnt += e - s; - nb -= e - s; - s = e; + cnt += nb; + n -= nb; + if (s) { + if (n <= 0) + break; + s = e; + } } return (cnt); } >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200003301703.TAA00862>