POSIX doesn't specify behavior for wcsrtombs and mbsrtowcs when the
source parameter is NULL.
http://pubs.opengroup.org/onlinepubs/009695399/functions/mbsrtowcs.html
http://pubs.opengroup.org/onlinepubs/009695399/functions/wcsrtombs.html

However segfaulting in such cases, as happens with this example,  
IMHO, is not desirable.

------- nullsrc.c

#include <locale.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>

int main() {
        char *msrc = NULL;
        char mdst[100];
        wchar_t *wsrc = NULL;
        wchar_t wdst[100];
        size_t s;
        mbstate_t mbst;

        bzero(&mbst, sizeof(mbst));
        mbsinit(&mbst);

        s = wcsrtombs(mdst, (const wchar_t **)&wsrc, 5, &mbst);
        printf("fixed wcsrtombs without encoding\n");
        s = mbsrtowcs(wdst, (const char **)&msrc, 5, &mbst);
        printf("fixed mbsrtowcs without encoding\n");

        setlocale(LC_ALL, "POSIX.UTF-8");
        s = wcsrtombs(mdst, (const wchar_t **)&wsrc, 5, &mbst);
        printf("fixed wcsrtombs with UTF-8\n");
        s = mbsrtowcs(wdst, (const char **)&msrc, 5, &mbst);
        printf("fixed mbsrtowcs with UTF-8\n");

        return 0;
}
---

cc -g -o nullsrc nullsrc.c
gdb nullsrc
...
(gdb) run
Starting program: /home/vtamara/tmp/nullsrc 

Program received signal SIGSEGV, Segmentation fault.
_citrus_none_ctype_wcsnrtombs (dst=0x7f7ffffbee90 "",
src=0x7f7ffffbee80, nwc=18446744073709551615, len=5,
pspriv=0x7f7ffffbee00)
    at /usr/src/lib/libc/citrus/citrus_none.c:155
155                     wchar_t wc = (*src)[i];

---

The attached patch solves this by setting errno in EINVAL and 
returning (size_t)-1 when the source parameter is NULL or points
to NULL, also includes this information in the man page.


-- 
Dios, gracias por tu amor infinito.
--  
  Vladimir Támara Patiño.  http://vtamara.pasosdeJesus.org/
  http://www.pasosdejesus.org/dominio_publico_colombia.html

diff -u src56-orig/lib/libc/citrus/citrus_none.c 
src/lib/libc/citrus/citrus_none.c
--- src56-orig/lib/libc/citrus/citrus_none.c    Thu Mar  7 13:12:31 2013
+++ src/lib/libc/citrus/citrus_none.c   Wed Oct  1 12:45:17 2014
@@ -93,6 +93,10 @@
        /* dst may be NULL */
        /* pspriv appears to be unused */
 
+       if (src == NULL || *src == NULL) {
+               errno = EINVAL;
+               return ((size_t)-1);
+       }
        if (dst == NULL)
                return strnlen(*src, nmc);
 
@@ -138,6 +142,10 @@
        /* dst may be NULL */
        /* pspriv appears to be unused */
 
+       if (src == NULL || *src == NULL) {
+               errno = EINVAL;
+               return ((size_t)-1);
+       }
        if (dst == NULL) {
                for (i = 0; i < nwc; i++) {
                        wchar_t wc = (*src)[i];
diff -u src56-orig/lib/libc/citrus/citrus_utf8.c 
src/lib/libc/citrus/citrus_utf8.c
--- src56-orig/lib/libc/citrus/citrus_utf8.c    Fri Sep 19 13:07:15 2014
+++ src/lib/libc/citrus/citrus_utf8.c   Wed Oct  1 12:44:01 2014
@@ -194,6 +194,10 @@
 
        us = (struct _utf8_state *)pspriv;
 
+       if (src == NULL || *src == NULL) {
+               errno = EINVAL;
+                return ((size_t)-1);
+        }
        if (dst == NULL) {
                /*
                 * The fast path in the loop below is not safe if an ASCII
@@ -346,6 +350,10 @@
                return ((size_t)-1);
        }
 
+       if (src == NULL || *src == NULL) {
+               errno = EINVAL;
+                return ((size_t)-1);
+        }
        if (dst == NULL) {
                for (i = o = 0; i < nwc; i++, o += r) {
                        wchar_t wc = (*src)[i];
diff -u src56-orig/lib/libc/locale/mbsrtowcs.3 src/lib/libc/locale/mbsrtowcs.3
--- src56-orig/lib/libc/locale/mbsrtowcs.3      Tue Jun  4 22:39:22 2013
+++ src/lib/libc/locale/mbsrtowcs.3     Wed Oct  1 13:34:47 2014
@@ -151,8 +151,8 @@
 is a null pointer, the value returned is the number of elements to contain
 the whole string converted, except for a terminating null wide character.
 .It (size_t)-1
-The array indirectly pointed to by
 .Fa src
+is NULL or points to NULL or to an array that
 contains a byte sequence forming invalid character.
 In this case,
 .Va errno
@@ -167,9 +167,8 @@
 functions may return the following errors:
 .Bl -tag -width Er
 .It Bq Er EILSEQ
-The pointer pointed to by
 .Fa src
-points to an invalid or incomplete multibyte character.
+is NULL or points to NULL or to an invalid or incomplete multibyte character.
 .It Bq Er EINVAL
 .Fa ps
 points to an invalid or uninitialized mbstate_t object.
diff -u src56-orig/lib/libc/locale/wcsrtombs.3 src/lib/libc/locale/wcsrtombs.3
--- src56-orig/lib/libc/locale/wcsrtombs.3      Tue Jun  4 22:39:22 2013
+++ src/lib/libc/locale/wcsrtombs.3     Wed Oct  1 13:37:31 2014
@@ -153,7 +153,7 @@
 will not be null-terminated.
 .It (size_t)-1
 .Fa src
-points to the string containing invalid wide character.
+is NULL or points to NULL or to a string containing invalid wide character.
 In this case,
 .Va errno
 is set to indicate the error.
@@ -168,7 +168,7 @@
 .Bl -tag -width Er
 .It Bq Er EILSEQ
 .Fa src
-points to the string containing an invalid wide character.
+is NULL or points to NULL or to a string containing an invalid wide character.
 .It Bq Er EINVAL
 .Fa ps
 points to an invalid or uninitialized mbstate_t object.

Reply via email to