From 61af4bbb2ae5a4eefc4c4243135747bbdb0f0684 Mon Sep 17 00:00:00 2001 From: Carlos O'Donell Date: Thu, 21 May 2020 17:50:53 -0400 Subject: mbstowcs: Document, test, and fix null pointer dst semantics (Bug 25219) The function mbstowcs, by an XSI extension to POSIX, accepts a null pointer for the destination wchar_t array. This API behaviour allows you to use the function to compute the length of the required wchar_t array i.e. does the conversion without storing it and returns the number of wide characters required. We remove the __write_only__ markup for the first argument because it is not true since the destination may be a null pointer, and so the length argument may not apply. We remove the markup otherwise the new test case cannot be compiled with -Werror=nonnull. We add a new test case for mbstowcs which exercises the destination is a null pointer behaviour which we have now explicitly documented. The mbsrtowcs and mbsnrtowcs behave similarly, and mbsrtowcs is documented as doing this in C11, even if the standard doesn't come out and call out this specific use case. We add one note to each of mbsrtowcs and mbsnrtowcs to call out that they support a null pointer for the destination. The wcsrtombs function behaves similarly but in the other way around and allows you to use a null destination pointer to compute how many bytes you would need to convert the wide character input. We document this particular case also, but leave wcsnrtombs as a references to wcsrtombs, so the reader must still read the details of the semantics for wcsrtombs. --- wcsmbs/Makefile | 2 +- wcsmbs/tst-mbstowcs.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 wcsmbs/tst-mbstowcs.c (limited to 'wcsmbs') diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile index f02167fa58..e638e45522 100644 --- a/wcsmbs/Makefile +++ b/wcsmbs/Makefile @@ -52,7 +52,7 @@ tests := tst-wcstof wcsmbs-tst1 tst-wcsnlen tst-btowc tst-mbrtowc \ tst-c16c32-1 wcsatcliff tst-wcstol-locale tst-wcstod-nan-locale \ tst-wcstod-round test-char-types tst-fgetwc-after-eof \ tst-wcstod-nan-sign tst-c16-surrogate tst-c32-state \ - $(addprefix test-,$(strop-tests)) + $(addprefix test-,$(strop-tests)) tst-mbstowcs include ../Rules diff --git a/wcsmbs/tst-mbstowcs.c b/wcsmbs/tst-mbstowcs.c new file mode 100644 index 0000000000..b48891553e --- /dev/null +++ b/wcsmbs/tst-mbstowcs.c @@ -0,0 +1,50 @@ +/* Test basic mbstowcs including wstring == NULL (Bug 25219). + Copyright (C) 2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +static int +do_test (void) +{ + char string[] = { '1', '2', '3' , '4', '5', '\0' }; + size_t len = strlen (string); + wchar_t wstring[] = { L'1', L'2', L'3', L'4', L'5', L'\0' }; +#define NUM_WCHAR 6 + wchar_t wout[NUM_WCHAR]; + size_t result; + + /* The input ASCII string in the C/POSIX locale must convert + to the matching WSTRING. */ + result = mbstowcs (wout, string, NUM_WCHAR); + TEST_VERIFY (result == (NUM_WCHAR - 1)); + TEST_COMPARE_BLOB (wstring, sizeof (wchar_t) * (NUM_WCHAR - 1), + wout, sizeof (wchar_t) * result); + + /* The input ASCII string in the C/POSIX locale must be the + same length when using mbstowcs to compute the length of + the string required in the conversion. Using mbstowcs + in this way is an XSI extension to POSIX. */ + result = mbstowcs (NULL, string, len); + TEST_VERIFY (result == len); + + return 0; +} + +#include -- cgit 1.4.1