LCOV - code coverage report
Current view: top level - lib/util/charset - convert_string.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 184 221 83.3 %
Date: 2021-09-23 10:06:22 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Character set conversion Extensions
       4             :    Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001
       5             :    Copyright (C) Andrew Tridgell 2001-2011
       6             :    Copyright (C) Andrew Bartlett 2011
       7             :    Copyright (C) Simo Sorce 2001
       8             :    Copyright (C) Martin Pool 2003
       9             : 
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             : 
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : 
      23             : */
      24             : #include "replace.h"
      25             : #include "system/iconv.h"
      26             : #include "charset.h"
      27             : #include "lib/util/debug.h"
      28             : #include "lib/util/fault.h"
      29             : 
      30             : /**
      31             :  * @file
      32             :  *
      33             :  * @brief Character-set conversion routines built on our iconv.
      34             :  *
      35             :  * @note Samba's internal character set (at least in the 3.0 series)
      36             :  * is always the same as the one for the Unix filesystem.  It is
      37             :  * <b>not</b> necessarily UTF-8 and may be different on machines that
      38             :  * need i18n filenames to be compatible with Unix software.  It does
      39             :  * have to be a superset of ASCII.  All multibyte sequences must start
      40             :  * with a byte with the high bit set.
      41             :  *
      42             :  * @sa lib/iconv.c
      43             :  */
      44             : 
      45             : 
      46             : /**
      47             :  * Convert string from one encoding to another, making error checking etc
      48             :  * Slow path version - uses (slow) iconv.
      49             :  *
      50             :  * @param src pointer to source string (multibyte or singlebyte)
      51             :  * @param srclen length of the source string in bytes
      52             :  * @param dest pointer to destination string (multibyte or singlebyte)
      53             :  * @param destlen maximal length allowed for string
      54             :  * @param converted size is the number of bytes occupied in the destination
      55             :  *
      56             :  * @returns false and sets errno on fail, true on success.
      57             :  *
      58             :  * Ensure the srclen contains the terminating zero.
      59             :  *
      60             :  **/
      61             : 
      62       38397 : static bool convert_string_internal(struct smb_iconv_handle *ic,
      63             :                                     charset_t from, charset_t to,
      64             :                                     void const *src, size_t srclen,
      65             :                                     void *dest, size_t destlen, size_t *converted_size)
      66             : {
      67             :         size_t i_len, o_len;
      68             :         size_t retval;
      69       38397 :         const char* inbuf = (const char*)src;
      70       38397 :         char* outbuf = (char*)dest;
      71             :         smb_iconv_t descriptor;
      72             : 
      73       38397 :         descriptor = get_conv_handle(ic, from, to);
      74             : 
      75       38397 :         if (srclen == (size_t)-1) {
      76          75 :                 if (from == CH_UTF16LE || from == CH_UTF16BE) {
      77          30 :                         srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2;
      78             :                 } else {
      79          45 :                         srclen = strlen((const char *)src)+1;
      80             :                 }
      81             :         }
      82             : 
      83             : 
      84       38397 :         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
      85           0 :                 errno = EINVAL;
      86           0 :                 return false;
      87             :         }
      88             : 
      89       38397 :         i_len=srclen;
      90       38397 :         o_len=destlen;
      91             : 
      92       38397 :         retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
      93       38397 :         *converted_size = destlen-o_len;
      94             : 
      95       38397 :         return (retval != (size_t)-1);
      96             : }
      97             : 
      98             : /**
      99             :  * Convert string from one encoding to another, making error checking etc
     100             :  * Fast path version - handles ASCII first.
     101             :  *
     102             :  * @param src pointer to source string (multibyte or singlebyte)
     103             :  * @param srclen length of the source string in bytes, or -1 for nul terminated.
     104             :  * @param dest pointer to destination string (multibyte or singlebyte)
     105             :  * @param destlen maximal length allowed for string - *NEVER* -1.
     106             :  * @param converted size is the number of bytes occupied in the destination
     107             :  *
     108             :  * @returns false and sets errno on fail, true on success.
     109             :  *
     110             :  * Ensure the srclen contains the terminating zero.
     111             :  *
     112             :  * This function has been hand-tuned to provide a fast path.
     113             :  * Don't change unless you really know what you are doing. JRA.
     114             :  **/
     115             : 
     116    10179432 : bool convert_string_error_handle(struct smb_iconv_handle *ic,
     117             :                                  charset_t from, charset_t to,
     118             :                                  void const *src, size_t srclen,
     119             :                                  void *dest, size_t destlen,
     120             :                                  size_t *converted_size)
     121             : {
     122             :         /*
     123             :          * NB. We deliberately don't do a strlen here if srclen == -1.
     124             :          * This is very expensive over millions of calls and is taken
     125             :          * care of in the slow path in convert_string_internal. JRA.
     126             :          */
     127             : 
     128             : #ifdef DEVELOPER
     129    10179432 :         SMB_ASSERT(destlen != (size_t)-1);
     130             : #endif
     131             : 
     132    10179432 :         if (srclen == 0) {
     133      883153 :                 *converted_size = 0;
     134      883153 :                 return true;
     135             :         }
     136             : 
     137     9296279 :         if (from != CH_UTF16LE && from != CH_UTF16BE && to != CH_UTF16LE && to != CH_UTF16BE) {
     138     4191028 :                 const unsigned char *p = (const unsigned char *)src;
     139     4191028 :                 unsigned char *q = (unsigned char *)dest;
     140     4191028 :                 size_t slen = srclen;
     141     4191028 :                 size_t dlen = destlen;
     142     4191028 :                 unsigned char lastp = '\0';
     143     4191028 :                 size_t retval = 0;
     144             : 
     145             :                 /* If all characters are ascii, fast path here. */
     146   212761659 :                 while (slen && dlen) {
     147   204988006 :                         if ((lastp = *p) <= 0x7f) {
     148   204985437 :                                 *q++ = *p++;
     149   204985437 :                                 if (slen != (size_t)-1) {
     150   204207409 :                                         slen--;
     151             :                                 }
     152   204985437 :                                 dlen--;
     153   204985437 :                                 retval++;
     154   204985437 :                                 if (!lastp)
     155      143812 :                                         break;
     156             :                         } else {
     157             : #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
     158             :                                 goto general_case;
     159             : #else
     160        2569 :                                 bool ret = convert_string_internal(ic, from, to, p, slen, q, dlen, converted_size);
     161        2569 :                                 *converted_size += retval;
     162        2569 :                                 return ret;
     163             : #endif
     164             :                         }
     165             :                 }
     166             : 
     167     4312126 :                 *converted_size = retval;
     168             : 
     169     4312126 :                 if (!dlen) {
     170             :                         /* Even if we fast path we should note if we ran out of room. */
     171      299332 :                         if (((slen != (size_t)-1) && slen) ||
     172        9230 :                                         ((slen == (size_t)-1) && lastp)) {
     173        7818 :                                 errno = E2BIG;
     174        7818 :                                 return false;
     175             :                         }
     176             :                 }
     177     4180967 :                 return true;
     178     4981584 :         } else if (from == CH_UTF16LE && to != CH_UTF16LE) {
     179          65 :                 const unsigned char *p = (const unsigned char *)src;
     180          65 :                 unsigned char *q = (unsigned char *)dest;
     181          65 :                 size_t retval = 0;
     182          65 :                 size_t slen = srclen;
     183          65 :                 size_t dlen = destlen;
     184          65 :                 unsigned char lastp = '\0';
     185             : #ifndef BROKEN_UNICODE_COMPOSE_CHARACTERS
     186             :                 bool ret;
     187             : #endif
     188             : 
     189          65 :                 if (slen == (size_t)-1) {
     190        3866 :                         while (dlen &&
     191        3846 :                                ((lastp = *p) <= 0x7f) && (p[1] == 0)) {
     192        1906 :                                 *q++ = *p;
     193        1906 :                                 p += 2;
     194        1906 :                                 dlen--;
     195        1906 :                                 retval++;
     196        1906 :                                 if (!lastp)
     197           0 :                                         break;
     198             :                         }
     199          38 :                         if (lastp != 0) goto slow_path;
     200             :                 } else {
     201        1022 :                         while (slen >= 2 && dlen &&
     202        1009 :                                (*p <= 0x7f) && (p[1] == 0)) {
     203         489 :                                 *q++ = *p;
     204         489 :                                 slen -= 2;
     205         489 :                                 p += 2;
     206         489 :                                 dlen--;
     207         489 :                                 retval++;
     208             :                         }
     209          27 :                         if (slen != 0) goto slow_path;
     210             :                 }
     211             : 
     212          10 :                 *converted_size = retval;
     213             : 
     214          10 :                 if (!dlen) {
     215             :                         /* Even if we fast path we should note if we ran out of room. */
     216           4 :                         if (((slen != (size_t)-1) && slen) ||
     217           2 :                                         ((slen == (size_t)-1) && lastp)) {
     218           0 :                                 errno = E2BIG;
     219           0 :                                 return false;
     220             :                         }
     221             :                 }
     222           0 :                 return true;
     223             : 
     224          55 :         slow_path:
     225             :                 /* come here when we hit a character we can't deal
     226             :                  * with in the fast path
     227             :                  */
     228             : #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
     229             :                 goto general_case;
     230             : #else
     231          55 :                 ret = convert_string_internal(ic, from, to, p, slen, q, dlen, converted_size);
     232          55 :                 *converted_size += retval;
     233          55 :                 return ret;
     234             : #endif
     235             : 
     236     4981519 :         } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
     237     4892919 :                 const unsigned char *p = (const unsigned char *)src;
     238     4892919 :                 unsigned char *q = (unsigned char *)dest;
     239     4892919 :                 size_t retval = 0;
     240     4892919 :                 size_t slen = srclen;
     241     4892919 :                 size_t dlen = destlen;
     242     4892919 :                 unsigned char lastp = '\0';
     243             : 
     244             :                 /* If all characters are ascii, fast path here. */
     245   263152421 :                 while (slen && (dlen >= 1)) {
     246   254278970 :                         if (dlen >=2 && (lastp = *p) <= 0x7F) {
     247   254278231 :                                 *q++ = *p++;
     248   254278231 :                                 *q++ = '\0';
     249   254278231 :                                 if (slen != (size_t)-1) {
     250   252071396 :                                         slen--;
     251             :                                 }
     252   254278231 :                                 dlen -= 2;
     253   254278231 :                                 retval += 2;
     254   491657523 :                                 if (!lastp)
     255      467269 :                                         break;
     256             :                         } else {
     257             : #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
     258             :                                 goto general_case;
     259             : #else
     260         739 :                                 bool ret = convert_string_internal(ic, from, to, p, slen, q, dlen, converted_size);
     261         739 :                                 *converted_size += retval;
     262         739 :                                 return ret;
     263             : #endif
     264             :                         }
     265             :                 }
     266             : 
     267     4945746 :                 *converted_size = retval;
     268             : 
     269     4945746 :                 if (!dlen) {
     270             :                         /* Even if we fast path we should note if we ran out of room. */
     271      807308 :                         if (((slen != (size_t)-1) && slen) ||
     272       36308 :                                         ((slen == (size_t)-1) && lastp)) {
     273           4 :                                 errno = E2BIG;
     274           4 :                                 return false;
     275             :                         }
     276             :                 }
     277     4892210 :                 return true;
     278             :         }
     279             : 
     280             : #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
     281             :   general_case:
     282             : #endif
     283       35034 :         return convert_string_internal(ic, from, to, src, srclen, dest, destlen, converted_size);
     284             : }
     285             : 
     286    10075952 : bool convert_string_handle(struct smb_iconv_handle *ic,
     287             :                            charset_t from, charset_t to,
     288             :                            void const *src, size_t srclen,
     289             :                            void *dest, size_t destlen,
     290             :                            size_t *converted_size)
     291             : {
     292    10075952 :         bool ret = convert_string_error_handle(ic, from, to, src, srclen, dest, destlen, converted_size);
     293             : 
     294    10075952 :         if(ret==false) {
     295          60 :                 const char *reason="unknown error";
     296          60 :                 switch(errno) {
     297          20 :                         case EINVAL:
     298          20 :                                 reason="Incomplete multibyte sequence";
     299          20 :                                 DBG_NOTICE("Conversion error: %s\n",
     300             :                                          reason);
     301          20 :                                 break;
     302          20 :                         case E2BIG:
     303             :                         {
     304          20 :                                 reason="No more room";
     305          20 :                                 if (from == CH_UNIX) {
     306          20 :                                         DBG_NOTICE("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u error: %s\n",
     307             :                                                    charset_name(ic, from), charset_name(ic, to),
     308             :                                                    (unsigned int)srclen, (unsigned int)destlen, reason);
     309             :                                 } else {
     310           0 :                                         DBG_NOTICE("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u error: %s\n",
     311             :                                                    charset_name(ic, from), charset_name(ic, to),
     312             :                                                    (unsigned int)srclen, (unsigned int)destlen, reason);
     313             :                                 }
     314          20 :                                 break;
     315             :                         }
     316          20 :                         case EILSEQ:
     317          20 :                                 reason="Illegal multibyte sequence";
     318          20 :                                 DBG_NOTICE("convert_string_internal: Conversion error: %s\n",
     319             :                                            reason);
     320          20 :                                 break;
     321           0 :                         default:
     322           0 :                                 DBG_ERR("convert_string_internal: Conversion error: %s\n",
     323             :                                         reason);
     324           0 :                                 break;
     325             :                 }
     326             :                 /* smb_panic(reason); */
     327     8825844 :         }
     328    10075952 :         return ret;
     329             : }
     330             : 
     331             : 
     332             : /**
     333             :  * Convert between character sets, allocating a new buffer using talloc for the result.
     334             :  *
     335             :  * @param srclen length of source buffer.
     336             :  * @param dest always set at least to NULL
     337             :  * @parm converted_size set to the number of bytes occupied by the string in
     338             :  * the destination on success.
     339             :  * @note -1 is not accepted for srclen.
     340             :  *
     341             :  * @return true if new buffer was correctly allocated, and string was
     342             :  * converted.
     343             :  *
     344             :  * Ensure the srclen contains the terminating zero.
     345             :  *
     346             :  * I hate the goto's in this function. It's emberrassing.....
     347             :  * There has to be a cleaner way to do this. JRA.
     348             :  */
     349   198703376 : bool convert_string_talloc_handle(TALLOC_CTX *ctx, struct smb_iconv_handle *ic,
     350             :                                   charset_t from, charset_t to,
     351             :                                   void const *src, size_t srclen, void *dst,
     352             :                                   size_t *converted_size)
     353             : 
     354             : {
     355             :         size_t i_len, o_len, destlen;
     356             :         size_t retval;
     357   198703376 :         const char *inbuf = NULL;
     358   198703376 :         char *outbuf = NULL, *ob = NULL;
     359             :         smb_iconv_t descriptor;
     360   198703376 :         void **dest = (void **)dst;
     361             : 
     362   198703376 :         *dest = NULL;
     363   198703376 :         if (converted_size != NULL) {
     364   198703368 :                 *converted_size = 0;
     365             :         }
     366             : 
     367   198703376 :         if (src == NULL || srclen == (size_t)-1) {
     368           0 :                 errno = EINVAL;
     369           0 :                 return false;
     370             :         }
     371             : 
     372   198703376 :         if (srclen == 0) {
     373             :                 /* We really should treat this as an error, but
     374             :                    there are too many callers that need this to
     375             :                    return a NULL terminated string in the correct
     376             :                    character set. */
     377       17525 :                 if (to == CH_UTF16LE|| to == CH_UTF16BE || to == CH_UTF16MUNGED) {
     378       13181 :                         destlen = 2;
     379             :                 } else {
     380        4344 :                         destlen = 1;
     381             :                 }
     382       17525 :                 ob = talloc_zero_array(ctx, char, destlen);
     383       17525 :                 if (ob == NULL) {
     384           0 :                         DBG_ERR("Could not talloc destination buffer.\n");
     385           0 :                         errno = ENOMEM;
     386           0 :                         return false;
     387             :                 }
     388       17525 :                 if (converted_size != NULL) {
     389       17525 :                         *converted_size = destlen;
     390             :                 }
     391       17525 :                 *dest = ob;
     392       17525 :                 return true;
     393             :         }
     394             : 
     395   198685851 :         descriptor = get_conv_handle(ic, from, to);
     396             : 
     397   198685851 :         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
     398           0 :                 DEBUG(0,("convert_string_talloc: Conversion not supported.\n"));
     399           0 :                 errno = EOPNOTSUPP;
     400           0 :                 return false;
     401             :         }
     402             : 
     403   198685851 :         if (srclen >= (SIZE_MAX - 2) / 3) {
     404           0 :                 DBG_ERR("convert_string_talloc: "
     405             :                         "srclen is %zu, destlen would wrap!\n",
     406             :                         srclen);
     407           0 :                 errno = EOPNOTSUPP;
     408           0 :                 return false;
     409             :         }
     410   198685851 :         destlen = srclen * 3;
     411             : 
     412             :         /* +2 is for ucs2 null termination. */
     413   198685851 :         ob = talloc_realloc(ctx, ob, char, destlen + 2);
     414             : 
     415   198685851 :         if (!ob) {
     416           0 :                 DEBUG(0, ("convert_string_talloc: realloc failed!\n"));
     417           0 :                 errno = ENOMEM;
     418           0 :                 return false;
     419             :         }
     420   198685851 :         outbuf = ob;
     421   198685851 :         i_len = srclen;
     422   198685851 :         o_len = destlen;
     423   198685851 :         inbuf = (const char *)src;
     424             : 
     425   198685851 :         retval = smb_iconv(descriptor,
     426             :                            &inbuf, &i_len,
     427             :                            &outbuf, &o_len);
     428   198685851 :         if(retval == (size_t)-1)                {
     429          59 :                 const char *reason="unknown error";
     430          59 :                 switch(errno) {
     431          20 :                         case EINVAL:
     432          20 :                                 reason="Incomplete multibyte sequence";
     433          20 :                                 DBG_NOTICE("Conversion error: %s\n",
     434             :                                            reason);
     435          20 :                                 break;
     436           0 :                         case E2BIG:
     437           0 :                                 reason = "output buffer is too small";
     438           0 :                                 DBG_ERR("Conversion error: %s\n",
     439             :                                         reason);
     440           0 :                                 break;
     441          39 :                         case EILSEQ:
     442          39 :                                 reason="Illegal multibyte sequence";
     443          39 :                                 DBG_NOTICE("Conversion error: %s\n",
     444             :                                            reason);
     445          15 :                                 break;
     446           0 :                         default:
     447           0 :                                 DBG_ERR("Conversion error: %s\n",
     448             :                                         reason);
     449           0 :                                 break;
     450             :                 }
     451             :                 /* smb_panic(reason); */
     452          59 :                 TALLOC_FREE(ob);
     453          59 :                 return false;
     454             :         }
     455             : 
     456   198685792 :         destlen = destlen - o_len;
     457             :         /* Don't shrink unless we're reclaiming a lot of
     458             :          * space. This is in the hot codepath and these
     459             :          * reallocs *cost*. JRA.
     460             :          */
     461   198685792 :         if (o_len > 1024) {
     462             :                 /* We're shrinking here so we know the +2 is safe from wrap. */
     463      404314 :                 ob = talloc_realloc(ctx,ob, char, destlen + 2);
     464             :         }
     465             : 
     466   198685792 :         if (destlen && !ob) {
     467           0 :                 DEBUG(0, ("convert_string_talloc: out of memory!\n"));
     468           0 :                 errno = ENOMEM;
     469           0 :                 return false;
     470             :         }
     471             : 
     472   198685792 :         *dest = ob;
     473             : 
     474             :         /* Must ucs2 null terminate in the extra space we allocated. */
     475   198685792 :         ob[destlen] = '\0';
     476   198685792 :         ob[destlen+1] = '\0';
     477             : 
     478             :         /* Ensure we can never return a *converted_size of zero. */
     479   198685792 :         if (destlen == 0) {
     480             :                 /* As we're now returning false on a bad smb_iconv call,
     481             :                    this should never happen. But be safe anyway. */
     482           0 :                 if (to == CH_UTF16LE|| to == CH_UTF16BE || to == CH_UTF16MUNGED) {
     483           0 :                         destlen = 2;
     484             :                 } else {
     485           0 :                         destlen = 1;
     486             :                 }
     487             :         }
     488             : 
     489   198685792 :         if (converted_size != NULL) {
     490   198685784 :                 *converted_size = destlen;
     491             :         }
     492   195940774 :         return true;
     493             : }
     494             : 
     495             : /**
     496             :  * Convert string from one encoding to another, making error checking etc
     497             :  *
     498             :  * @param src pointer to source string (multibyte or singlebyte)
     499             :  * @param srclen length of the source string in bytes
     500             :  * @param dest pointer to destination string (multibyte or singlebyte)
     501             :  * @param destlen maximal length allowed for string
     502             :  * @param converted_size the number of bytes occupied in the destination
     503             :  *
     504             :  * @returns true on success, false on fail.
     505             :  **/
     506    10075952 : _PUBLIC_ bool convert_string(charset_t from, charset_t to,
     507             :                                void const *src, size_t srclen,
     508             :                                void *dest, size_t destlen,
     509             :                                size_t *converted_size)
     510             : {
     511    10075952 :         return convert_string_handle(get_iconv_handle(), from, to,
     512             :                                         src, srclen,
     513             :                                         dest, destlen, converted_size);
     514             : }
     515             : 
     516             : /**
     517             :  * Convert string from one encoding to another, making error checking etc
     518             :  *
     519             :  * @param src pointer to source string (multibyte or singlebyte)
     520             :  * @param srclen length of the source string in bytes
     521             :  * @param dest pointer to destination string (multibyte or singlebyte)
     522             :  * @param destlen maximal length allowed for string
     523             :  * @param converted_size the number of bytes occupied in the destination
     524             :  *
     525             :  * @returns true on success, false on fail.
     526             :  **/
     527      103369 : _PUBLIC_ bool convert_string_error(charset_t from, charset_t to,
     528             :                                    void const *src, size_t srclen,
     529             :                                    void *dest, size_t destlen,
     530             :                                    size_t *converted_size)
     531             : {
     532      103369 :         return convert_string_error_handle(get_iconv_handle(), from, to,
     533             :                                            src, srclen,
     534             :                                            dest, destlen, converted_size);
     535             : }
     536             : 
     537             : /**
     538             :  * Convert between character sets, allocating a new buffer using talloc for the result.
     539             :  *
     540             :  * @param srclen length of source buffer.
     541             :  * @param dest always set at least to NULL
     542             :  * @param converted_size Size in bytes of the converted string
     543             :  * @note -1 is not accepted for srclen.
     544             :  *
     545             :  * @returns boolean indication whether the conversion succeeded
     546             :  **/
     547             : 
     548   198703033 : _PUBLIC_ bool convert_string_talloc(TALLOC_CTX *ctx,
     549             :                                     charset_t from, charset_t to,
     550             :                                     void const *src, size_t srclen,
     551             :                                     void *dest, size_t *converted_size)
     552             : {
     553   198703033 :         return convert_string_talloc_handle(ctx, get_iconv_handle(),
     554             :                                                  from, to, src, srclen, dest,
     555             :                                                  converted_size);
     556             : }

Generated by: LCOV version 1.13