Subject: lib/18269: wc(r)tomb()'s behavior is out of the standard, ISO-C/SUS.
To: None <gnats-bugs@gnats.netbsd.org>
From: wurlitzer@infoseek.jp <wurlitzer@infoseek.jp>
List: netbsd-bugs
Date: 09/12/2002 05:05:56
>Number: 18269
>Category: lib
>Synopsis: wc(r)tomb()'s behavior is out of the standard, ISO-C/SUS.
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Sep 11 16:16:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator: wurlitzer@infoseek.jp
>Release: NetBSD 1.6_RC1
>Organization:
--
wurlitzer@infoseek.jp <wurlitzer@infoseek.jp>
>Environment:
System: NetBSD fly 1.6_RC1 NetBSD 1.6_RC1 (FLY) #0: Mon Aug 26 11:56:35 JST 2002 root@fly:/usr/src/sys/arch/i386/compile/FLY i386
Architecture: i386
Machine: i386
libc version: libc.so.12.83 lib{BIG5,EUC,EUCTW,ISO2022,MSKanji,UTF8}.so.4.0
>Description:
1) wcrtomb() problems
ISO-C/SUS says,
size_t wcrtomb(const char *s, wchar_t wc, mbstate_t *state);
if 's' is a null pointer, the wcrtomb() function is equivalent to the call
wcrtomb(buf, L'\0', ps), where buf is an internal buffer.
but NetBSD libc doesn't check whether 's' is a null pointer or not.
as a result, Segmentation fault caused when feeding 's' as NULL,
2) wctomb() problems.
ISO-C/SUS says,
int wctomb(char *s, wchar_t wc);
A call with s as a null pointer causes this function to return a
non-zero value if encodings have state dependency, and 0 otherwise.
but NetBSD libc force to convert 'wc' by using an internal buffer,
and return (size_t) 1.
>How-To-Repeat:
compile and run following simple test code.
-- test.c start --
#include <locale.h>
#include <wchar.h>
int main(void) {
size_t len1;
int len2;
mbstate_t s;
setlocale (LC_CTYPE, "ja_JP.eucJP");
memset(&s, 0, sizeof(s));
/* len1 expected to be 1 (glibc does),
but NetBSD may throws Segmentation fault */
len1 = wcrtomb(NULL, 0, &s);
printf("%d\n", len1);
/* len2 expected to be 0 (glibc does),
but NetBSD may returns 1 */
len2 = wctomb(NULL, 0);
printf("%d\n", len2);
return 0;
}
-- test.c end --
>Fix:
1) wcrtomb
Index: citrus_euc.c
===================================================================
RCS file: /home/cvs/NetBSD/basesrc/lib/libc/citrus/modules/citrus_euc.c,v
retrieving revision 1.5
diff -u -r1.5 citrus_euc.c
--- citrus_euc.c 2002/03/28 10:53:48 1.5
+++ citrus_euc.c 2002/09/10 07:43:54
@@ -300,10 +300,16 @@
{
wchar_t m, nm;
int cs, i;
+ char buf[MB_LEN_MAX];
+ if (s == NULL) {
+ _citrus_EUC_init_state(ei, psenc);
+ s = buf;
+ wchar = (wchar_t)0;
+ }
+
_DIAGASSERT(ei != NULL);
_DIAGASSERT(nresult != 0);
- _DIAGASSERT(s != NULL);
m = wc & ei->mask;
nm = wc & ~m;
2) wctomb
Index: citrus_ctype_template.h
===================================================================
RCS file: /home/cvs/NetBSD/basesrc/lib/libc/citrus/citrus_ctype_template.h,v
retrieving revision 1.13.2.1
diff -u -r1.13.2.1 citrus_ctype_template.h
--- citrus_ctype_template.h 2002/05/24 21:55:23 1.13.2.1
+++ citrus_ctype_template.h 2002/09/11 17:29:52
@@ -606,12 +606,15 @@
{
size_t nr;
int err = 0;
- char s0[MB_LEN_MAX];
_DIAGASSERT(cl != NULL);
- if (s==NULL)
- s = s0;
+ if (s==NULL) {
+ _FUNCNAME(init_state)(_CEI_TO_EI(_TO_CEI(cl)),
+ &_CEI_TO_STATE(_TO_CEI(cl), wctomb));
+ *nresult = _ENCODING_IS_STATE_DEPENDENT :
+ return 0;
+ }
err = _FUNCNAME(wcrtomb_priv)(cl, s,
_ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl))),
>Release-Note:
>Audit-Trail:
>Unformatted: