[PATCH] Everybody loves iconv!


Subject: [PATCH] Everybody loves iconv!
From: David Mandelin (mandelin@cs.wisc.edu)
Date: Tue Aug 28 2001 - 15:07:40 CDT


Fix for crash in UT_convert. Mea culpa:

A little while ago, I suggested restructuring UT_convert so that the try
block would enclose only the code that throws an exception. Looks like
someone (Dom?) followed my suggestion. Whoops. The suggestion was...bad.
The thing that throws an exception is the ctor for auto_iconv, so the
lifetime of the auto_iconv object is constrained to the try block. The
conversion descriptor thus gets cleaned up before iconv() is called.

Index: af/util/xp/ut_iconv.cpp
===================================================================
RCS file: /cvsroot/abi/src/af/util/xp/ut_iconv.cpp,v
retrieving revision 1.15
diff -u -r1.15 ut_iconv.cpp
--- af/util/xp/ut_iconv.cpp 2001/08/27 19:06:29 1.15
+++ af/util/xp/ut_iconv.cpp 2001/08/28 20:02:22
@@ -214,108 +214,108 @@
           {
             auto_iconv converter(from_codeset, to_codeset);
             cd = converter.getHandle();
- }
- UT_CATCH(UT_CATCH_ANY)
- {
- bytes_read = 0;
- bytes_written = 0;
- return NULL;
- }
- UT_END_CATCH
 
- if (len < 0)
- {
- len = strlen(str);
- }
-
- const char* p = str;
- size_t inbytes_remaining = len;
-
- /* Due to a GLIBC bug, round outbuf_size up to a multiple of 4 */
- /* + 1 for nul in case len == 1 */
- size_t outbuf_size = ((len + 3) & ~3) + 15;
- size_t outbytes_remaining = outbuf_size - 1; /* -1 for nul */
-
- char* pDest = (char*)malloc(outbuf_size);
- char* outp = pDest;
-
- bool have_error = false;
- bool bAgain = true;
-
- while (bAgain)
- {
- size_t err = UT_iconv(cd,
- &p,
- &inbytes_remaining,
- &outp, &outbytes_remaining);
-
- if (err == (size_t) -1)
+ if (len < 0)
+ {
+ len = strlen(str);
+ }
+
+ const char* p = str;
+ size_t inbytes_remaining = len;
+
+ /* Due to a GLIBC bug, round outbuf_size up to a multiple of 4 */
+ /* + 1 for nul in case len == 1 */
+ size_t outbuf_size = ((len + 3) & ~3) + 15;
+ size_t outbytes_remaining = outbuf_size - 1; /* -1 for nul */
+
+ char* pDest = (char*)malloc(outbuf_size);
+ char* outp = pDest;
+
+ bool have_error = false;
+ bool bAgain = true;
+
+ while (bAgain)
               {
- switch (errno)
+ size_t err = UT_iconv(cd,
+ &p,
+ &inbytes_remaining,
+ &outp, &outbytes_remaining);
+
+ if (err == (size_t) -1)
                   {
- case EINVAL:
- /* Incomplete text, do not report an error */
- bAgain = false;
- break;
- case E2BIG:
- {
- size_t used = outp - pDest;
-
- /* glibc's iconv can return E2BIG even if there is space
- * remaining if an internal buffer is exhausted. The
- * folllowing is a heuristic to catch this. The 16 is
- * pretty arbitrary.
- */
- if (used + 16 > outbuf_size)
+ switch (errno)
+ {
+ case EINVAL:
+ /* Incomplete text, do not report an error */
+ bAgain = false;
+ break;
+ case E2BIG:
                         {
- outbuf_size = outbuf_size + 15;
- pDest = (char*)realloc(pDest, outbuf_size);
-
- outp = pDest + used;
- outbytes_remaining = outbuf_size - used - 1; /* -1 for nul */
+ size_t used = outp - pDest;
+
+ /* glibc's iconv can return E2BIG even if there is space
+ * remaining if an internal buffer is exhausted. The
+ * folllowing is a heuristic to catch this. The 16 is
+ * pretty arbitrary.
+ */
+ if (used + 16 > outbuf_size)
+ {
+ outbuf_size = outbuf_size + 15;
+ pDest = (char*)realloc(pDest, outbuf_size);
+
+ outp = pDest + used;
+ outbytes_remaining = outbuf_size - used - 1; /* -1 for nul */
+ }
+
+ bAgain = true;
+ break;
                         }
-
- bAgain = true;
- break;
- }
- default:
- have_error = true;
+ default:
+ have_error = true;
+ bAgain = false;
+ break;
+ }
+ }
+ else
+ {
                     bAgain = false;
- break;
                   }
- }
- else
+ }
+
+ *outp = '\0';
+
+ const size_t nNewLen = p - str;
+
+ if (bytes_read_arg)
               {
- bAgain = false;
+ bytes_read = nNewLen;
               }
- }
-
- *outp = '\0';
-
- const size_t nNewLen = p - str;
-
- if (bytes_read_arg)
- {
- bytes_read = nNewLen;
- }
- else
- {
- if (nNewLen != len)
+ else
               {
- have_error = true;
+ if (nNewLen != len)
+ {
+ have_error = true;
+ }
               }
+
+ bytes_written = outp - pDest; /* Doesn't include '\0' */
+
+ if (have_error && pDest)
+ {
+ free(pDest);
+ }
+
+ if (have_error)
+ return NULL;
+
+ return pDest;
           }
-
- bytes_written = outp - pDest; /* Doesn't include '\0' */
-
- if (have_error && pDest)
+ UT_CATCH(UT_CATCH_ANY)
           {
- free(pDest);
+ bytes_read = 0;
+ bytes_written = 0;
+ return NULL;
           }
-
- if (have_error)
- return NULL;
-
- return pDest;
+ UT_END_CATCH
 }
 



This archive was generated by hypermail 2b25 : Tue Aug 28 2001 - 15:07:42 CDT