The initial patch does not pass the following test case. Have re-worked
the patch and attached it to the incident, and I am also attaching it
here. It passes all collate tests.
Here is the second test case:
$ cat ../../tests/localization/t.cpp; nice make t.cpp && ./t af_ZA.utf8;
echo $?
#include <iostream>
#include <locale>
#include <string>
int
main (int argc, char** argv)
{
std::locale loc (argv [1]);
const std::collate< char >& fac =
std::use_facet< std::collate< char > > (loc);
char const buf [] = "a\0\0b";
std::string s = fac.transform (buf, buf + sizeof buf - 1);
size_t i = 0;
for (; i < s.size () && 0 == s [i]; ++i) ;
return !(i == 2);
}
1
On 10/10/12 08:25, Liviu Nicoara wrote:
2012-10-10 Liviu Nicoara <lnico...@apache.org>
* src/collate.cpp (__rw_strnxfrm): preserved embedded NULs
Index: src/collate.cpp
===================================================================
--- src/collate.cpp (revision 1397825)
+++ src/collate.cpp (working copy)
@@ -480,113 +480,103 @@
{
_STD::string res;
- char buf [256];
- char *pbuf = buf;
-
+ char buf [256], *pbuf = buf, *psrc = buf;
size_t bufsize = sizeof buf;
- char *psrc = buf;
while (nchars) {
- // using a C-style cast instead of static_cast to avoid
- // a gcc 2.95.2 bug causing an error on some platforms:
- // static_cast from `void *' to `const char *'
- const char* const last = (const char*)memchr (src, '\0', nchars);
-
- if (0 == last) {
-
- // no NUL found in the initial portion of the source string
- // that fits into the local temporary buffer; copy as many
- // characters as fit into the buffer
+ if (src [0]) {
- if (bufsize <= nchars) {
- if (pbuf != buf)
- delete[] pbuf;
- pbuf = new char [nchars + 1];
+ // using a C-style cast instead of static_cast to avoid
+ // a gcc 2.95.2 bug causing an error on some platforms:
+ // static_cast from `void *' to `const char *'
+ const char* const last = (const char*)memchr (src, '\0', nchars);
+
+ if (0 == last) {
+ // no NUL found in the initial portion of the source string
+ // that fits into the local temporary buffer; copy as many
+ // characters as fit into the buffer
+
+ if (bufsize <= nchars) {
+ if (pbuf != buf)
+ delete[] pbuf;
+ pbuf = new char [nchars + 1];
+ }
+
+ psrc = pbuf;
+ memcpy (psrc, src, nchars);
+
+ // append a terminating NUL and decrement the number
+ // of characters that remain to be processed
+ psrc [nchars] = '\0';
+ src += nchars;
+ nchars = 0;
+ }
+ else {
+ // terminating NUL found in the source buffer
+ nchars -= (last - src) + 1;
+ psrc = _RWSTD_CONST_CAST (char*, src);
+ src += (last - src) + 1;
}
- psrc = pbuf;
- memcpy (psrc, src, nchars);
+#ifdef _RWSTD_OS_SUNOS
+ // Solaris 10u5 on AMD64 overwrites memory past the end of
+ // just_in_case_buf[8], to avoid this, pass a null pointer
+ char* const just_in_case_buf = 0;
+#else
+ // provide a destination buffer to strxfrm() in case
+ // it's buggy (such as MSVC's) and tries to write to
+ // the buffer even if it's 0
+ char just_in_case_buf [8];
+#endif // _RWSTD_OS_SUNOS
- // append a terminating NUL and decrement the number
- // of characters that remain to be processed
- psrc [nchars] = '\0';
- src += nchars;
- nchars = 0;
- }
- else {
+ const size_t dst_size = strxfrm (just_in_case_buf, psrc, 0);
- // terminating NUL found in the source buffer
- nchars -= (last - src) + 1;
- psrc = _RWSTD_CONST_CAST (char*, src);
- src += (last - src) + 1;
- }
+ // check for strxfrm() errors
+ if (0 == (dst_size << 1)) {
+ if (pbuf != buf)
+ delete[] pbuf;
-#ifdef _RWSTD_OS_SUNOS
- // Solaris 10u5 on AMD64 overwrites memory past the end of
- // just_in_case_buf[8], to avoid this, pass a null pointer
- char* const just_in_case_buf = 0;
-#else
- // provide a destination buffer to strxfrm() in case
- // it's buggy (such as MSVC's) and tries to write to
- // the buffer even if it's 0
- char just_in_case_buf [8];
-#endif
-
- const size_t dst_size = strxfrm (just_in_case_buf, psrc, 0);
-
- // check for strxfrm() errors
- if (0 == (dst_size << 1)) {
- if (pbuf != buf)
- delete[] pbuf;
+ return _STD::string ();
+ }
- return _STD::string ();
- }
+ size_t res_size = res.size ();
- size_t res_size = res.size ();
+ _TRY {
+ // resize the result string to fit itself plus the result
+ // of the transformation including the terminating NUL
+ // appended by strxfrm()
+ res.resize (res_size + dst_size + 1);
+ }
+ _CATCH (...) {
+ if (pbuf != buf)
+ delete[] pbuf;
+ _RETHROW;
+ }
- _TRY {
- // resize the result string to fit itself plus the result
- // of the transformation including the terminatin NUL
- // appended by strxfrm()
- res.resize (res_size + dst_size + 1);
- }
- _CATCH (...) {
- if (pbuf != buf)
- delete[] pbuf;
- _RETHROW;
+ strxfrm (&res [0] + res_size, psrc, dst_size + 1);
}
+ else {
- // transfor the source string up to the terminating NUL
- size_t xfrm_size =
- strxfrm (&res [0] + res_size, psrc, dst_size + 1);
+ // count and append the consecutive NULs embedded in the
+ // input string
-#if defined _MSC_VER && _MSC_VER < 1400
- // compute the correct value that should have been returned from
- // strxfrm() after the transformation has completed (MSVC strxfrm()
- // returns a bogus result; see PR #29935)
- xfrm_size = strlen (&res [0] + res_size);
-#endif // MSVC < 8.0
-
- // increment the size of the result string by the number
- // of transformed characters excluding the terminating NUL
- // if strxfrm() transforms the empty string into the empty
- // string, keep the terminating NUL, otherwise drop it
- res_size += xfrm_size + (last && !*psrc && !xfrm_size);
+ size_t i = 0;
+ for (; i < nchars && 0 == src [i]; ++i) ;
- _TRY {
- res.resize (res_size);
- }
- _CATCH (...) {
- if (pbuf != buf)
- delete[] pbuf;
- _RETHROW;
+ res.resize (res.size () + i);
+
+ nchars -= i;
+ src += i;
}
}
if (pbuf != buf)
delete[] pbuf;
+ if (!res.empty ())
+ res.resize (res.size () - 1);
+
return res;
}