Date: Sat, 14 Sep 2013 23:20:20 GMT From: Henry Hu <henry.hu.sh@gmail.com> To: freebsd-gnats-submit@FreeBSD.org Subject: misc/182102: bug in libiconv_none prevents MPD from starting Message-ID: <201309142320.r8ENKKjV097551@oldred.freebsd.org> Resent-Message-ID: <201309142330.r8ENU0gg010330@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 182102 >Category: misc >Synopsis: bug in libiconv_none prevents MPD from starting >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sat Sep 14 23:30:00 UTC 2013 >Closed-Date: >Last-Modified: >Originator: Henry Hu >Release: FreeBSD 10-CURRENT >Organization: Columbia University >Environment: FreeBSD pepsi 10.0-CURRENT FreeBSD 10.0-CURRENT #1 r255532M: Sat Sep 14 17:30:47 PDT 2013 root@pepsi:/usr/obj/usr/src/sys/MYKERNEL amd64 >Description: Recently I updated to latest -CURRENT which enables WITH_ICONV. Then I found MPD(audio/musicpd) failed to start. It says: path: invalid filesystem charset: UTF-8 MPD now uses the system iconv. I found the call in MPD to g_convert() failed. After some tracing, I found that the iconv() call is not working properly. Here is the test program: #include <stdio.h> #include <iconv.h> int main() { iconv_t cd = iconv_open("UTF-8", "UTF-8"); char *inbuf = " "; char *inp = inbuf; size_t inl = 1; char outbuf[100]; char *outp = outbuf; size_t oul = 1; printf("%p %d %p %d\n", inp, inl, outp, oul); int ret = iconv(cd, &inp, &inl, &outp, &oul); printf("%d %p %d %p %d\n", ret, inp, inl, outp, oul); } This essentially loads the iconv_none module, because the input and output encodings are the same. If you run it, you get something like this: 0x40094c 1 0x7fffffffd4d0 1 0 0x40094c 0 0x7fffffffd4d0 0 However, according to iconv()'s manpage, after iconv(): *src Pointer to the byte just after the last character fetched. *srcleft Number of remaining bytes in the source buffer. *dst Pointer to the byte just after the last character stored. *dstleft Number of remainder bytes in the destination buffer. So both src (inp) and dst (outp) should move forward, but they stay the same. This makes g_convert() think that the conversion is not completed and there are partial inputs. In /usr/src/lib/libiconv_modules/iconv_none/citrus_iconv_none.c, we have: static int /*ARGSUSED*/ _citrus_iconv_none_iconv_convert(struct _citrus_iconv * __restrict ci __unused, char * __restrict * __restrict in, size_t * __restrict inbytes, char * __restrict * __restrict out, size_t * __restrict outbytes, uint32_t flags __unused, size_t * __restrict invalids) { .... memcpy(*out, *in, len); in += len; *inbytes -= len; out += len; *outbytes -= len; *invalids = 0; .... Here, the function attempted to move the in & out pointers forward. However, now it just moves the local copy. It should do *in += len; .. *out += len; instead. After applying the patch, it works correctly, and MPD starts. Please fix this. >How-To-Repeat: Compile and run this: #include <stdio.h> #include <iconv.h> int main() { iconv_t cd = iconv_open("UTF-8", "UTF-8"); char *inbuf = " "; char *inp = inbuf; size_t inl = 1; char outbuf[100]; char *outp = outbuf; size_t oul = 1; printf("%p %d %p %d\n", inp, inl, outp, oul); int ret = iconv(cd, &inp, &inl, &outp, &oul); printf("%d %p %d %p %d\n", ret, inp, inl, outp, oul); } And observe that the input & output pointers of iconv() are not increased. >Fix: Patch attached. Patch attached with submission follows: Index: lib/libiconv_modules/iconv_none/citrus_iconv_none.c =================================================================== --- lib/libiconv_modules/iconv_none/citrus_iconv_none.c (版本 255575) +++ lib/libiconv_modules/iconv_none/citrus_iconv_none.c (工作副本) @@ -115,9 +115,9 @@ len = *outbytes; } memcpy(*out, *in, len); - in += len; + *in += len; *inbytes -= len; - out += len; + *out += len; *outbytes -= len; *invalids = 0; if (e2big) >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201309142320.r8ENKKjV097551>