OpenCoverage

striconv.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/coreutils/src/lib/striconv.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/* Charset conversion.-
2 Copyright (C) 2001-2007, 2010-2018 Free Software Foundation, Inc.-
3 Written by Bruno Haible and Simon Josefsson.-
4-
5 This program is free software; you can redistribute it and/or modify-
6 it under the terms of the GNU General Public License as published by-
7 the Free Software Foundation; either version 3, or (at your option)-
8 any later version.-
9-
10 This program is distributed in the hope that it will be useful,-
11 but WITHOUT ANY WARRANTY; without even the implied warranty of-
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the-
13 GNU General Public License for more details.-
14-
15 You should have received a copy of the GNU General Public License-
16 along with this program; if not, see <https://www.gnu.org/licenses/>. */-
17-
18#include <config.h>-
19-
20/* Specification. */-
21#include "striconv.h"-
22-
23#include <errno.h>-
24#include <stdlib.h>-
25#include <string.h>-
26-
27#if HAVE_ICONV-
28# include <iconv.h>-
29/* Get MB_LEN_MAX, CHAR_BIT. */-
30# include <limits.h>-
31#endif-
32-
33#include "c-strcase.h"-
34-
35#ifndef SIZE_MAX-
36# define SIZE_MAX ((size_t) -1)-
37#endif-
38-
39-
40#if HAVE_ICONV-
41-
42int-
43mem_cd_iconv (const char *src, size_t srclen, iconv_t cd,-
44 char **resultp, size_t *lengthp)-
45{-
46# define tmpbufsize 4096-
47 size_t length;-
48 char *result;-
49-
50 /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */-
51# if defined _LIBICONV_VERSION \-
52 || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \-
53 || defined __sun)-
54 /* Set to the initial state. */-
55 iconv (cd, NULL, NULL, NULL, NULL);-
56# endif-
57-
58 /* Determine the length we need. */-
59 {-
60 size_t count = 0;-
61 /* The alignment is needed when converting e.g. to glibc's WCHAR_T or-
62 libiconv's UCS-4-INTERNAL encoding. */-
63 union { unsigned int align; char buf[tmpbufsize]; } tmp;-
64# define tmpbuf tmp.buf-
65 const char *inptr = src;-
66 size_t insize = srclen;-
67-
68 while (insize > 0)
insize > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
69 {-
70 char *outptr = tmpbuf;-
71 size_t outsize = tmpbufsize;-
72 size_t res = iconv (cd,-
73 (ICONV_CONST char **) &inptr, &insize,-
74 &outptr, &outsize);-
75-
76 if (res == (size_t)(-1))
res == (size_t)(-1)Description
TRUEnever evaluated
FALSEnever evaluated
0
77 {-
78 if (errno == E2BIG)
(*__errno_location ()) == 7Description
TRUEnever evaluated
FALSEnever evaluated
0
79 ;
never executed: ;
0
80 else if (errno == EINVAL)
(*__errno_location ()) == 22Description
TRUEnever evaluated
FALSEnever evaluated
0
81 break;
never executed: break;
0
82 else-
83 return -1;
never executed: return -1;
0
84 }-
85# if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__)-
86 /* Irix iconv() inserts a NUL byte if it cannot convert.-
87 NetBSD iconv() inserts a question mark if it cannot convert.-
88 Only GNU libiconv and GNU libc are known to prefer to fail rather-
89 than doing a lossy conversion. */-
90 else if (res > 0)-
91 {-
92 errno = EILSEQ;-
93 return -1;-
94 }-
95# endif-
96 count += outptr - tmpbuf;-
97 }
never executed: end of block
0
98 /* Avoid glibc-2.1 bug and Solaris 2.7 bug. */-
99# if defined _LIBICONV_VERSION \-
100 || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \-
101 || defined __sun)-
102 {-
103 char *outptr = tmpbuf;-
104 size_t outsize = tmpbufsize;-
105 size_t res = iconv (cd, NULL, NULL, &outptr, &outsize);-
106-
107 if (res == (size_t)(-1))
res == (size_t)(-1)Description
TRUEnever evaluated
FALSEnever evaluated
0
108 return -1;
never executed: return -1;
0
109 count += outptr - tmpbuf;-
110 }-
111# endif-
112 length = count;-
113# undef tmpbuf-
114 }-
115-
116 if (length == 0)
length == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
117 {-
118 *lengthp = 0;-
119 return 0;
never executed: return 0;
0
120 }-
121 if (*resultp != NULL && *lengthp >= length)
*resultp != ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
*lengthp >= lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
122 result = *resultp;
never executed: result = *resultp;
0
123 else-
124 {-
125 result = (char *) malloc (length);-
126 if (result == NULL)
result == ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
127 {-
128 errno = ENOMEM;-
129 return -1;
never executed: return -1;
0
130 }-
131 }
never executed: end of block
0
132-
133 /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */-
134# if defined _LIBICONV_VERSION \-
135 || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \-
136 || defined __sun)-
137 /* Return to the initial state. */-
138 iconv (cd, NULL, NULL, NULL, NULL);-
139# endif-
140-
141 /* Do the conversion for real. */-
142 {-
143 const char *inptr = src;-
144 size_t insize = srclen;-
145 char *outptr = result;-
146 size_t outsize = length;-
147-
148 while (insize > 0)
insize > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
149 {-
150 size_t res = iconv (cd,-
151 (ICONV_CONST char **) &inptr, &insize,-
152 &outptr, &outsize);-
153-
154 if (res == (size_t)(-1))
res == (size_t)(-1)Description
TRUEnever evaluated
FALSEnever evaluated
0
155 {-
156 if (errno == EINVAL)
(*__errno_location ()) == 22Description
TRUEnever evaluated
FALSEnever evaluated
0
157 break;
never executed: break;
0
158 else-
159 goto fail;
never executed: goto fail;
0
160 }-
161# if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__)-
162 /* Irix iconv() inserts a NUL byte if it cannot convert.-
163 NetBSD iconv() inserts a question mark if it cannot convert.-
164 Only GNU libiconv and GNU libc are known to prefer to fail rather-
165 than doing a lossy conversion. */-
166 else if (res > 0)-
167 {-
168 errno = EILSEQ;-
169 goto fail;-
170 }-
171# endif-
172 }
never executed: end of block
0
173 /* Avoid glibc-2.1 bug and Solaris 2.7 bug. */-
174# if defined _LIBICONV_VERSION \-
175 || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \-
176 || defined __sun)-
177 {-
178 size_t res = iconv (cd, NULL, NULL, &outptr, &outsize);-
179-
180 if (res == (size_t)(-1))
res == (size_t)(-1)Description
TRUEnever evaluated
FALSEnever evaluated
0
181 goto fail;
never executed: goto fail;
0
182 }-
183# endif-
184 if (outsize != 0)
outsize != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
185 abort ();
never executed: abort ();
0
186 }-
187-
188 *resultp = result;-
189 *lengthp = length;-
190-
191 return 0;
never executed: return 0;
0
192-
193 fail:-
194 {-
195 if (result != *resultp)
result != *resultpDescription
TRUEnever evaluated
FALSEnever evaluated
0
196 {-
197 int saved_errno = errno;-
198 free (result);-
199 errno = saved_errno;-
200 }
never executed: end of block
0
201 return -1;
never executed: return -1;
0
202 }-
203# undef tmpbufsize-
204}-
205-
206char *-
207str_cd_iconv (const char *src, iconv_t cd)-
208{-
209 /* For most encodings, a trailing NUL byte in the input will be converted-
210 to a trailing NUL byte in the output. But not for UTF-7. So that this-
211 function is usable for UTF-7, we have to exclude the NUL byte from the-
212 conversion and add it by hand afterwards. */-
213# if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__)-
214 /* Irix iconv() inserts a NUL byte if it cannot convert.-
215 NetBSD iconv() inserts a question mark if it cannot convert.-
216 Only GNU libiconv and GNU libc are known to prefer to fail rather-
217 than doing a lossy conversion. For other iconv() implementations,-
218 we have to look at the number of irreversible conversions returned;-
219 but this information is lost when iconv() returns for an E2BIG reason.-
220 Therefore we cannot use the second, faster algorithm. */-
221-
222 char *result = NULL;-
223 size_t length = 0;-
224 int retval = mem_cd_iconv (src, strlen (src), cd, &result, &length);-
225 char *final_result;-
226-
227 if (retval < 0)-
228 {-
229 if (result != NULL)-
230 abort ();-
231 return NULL;-
232 }-
233-
234 /* Add the terminating NUL byte. */-
235 final_result =-
236 (result != NULL ? realloc (result, length + 1) : malloc (length + 1));-
237 if (final_result == NULL)-
238 {-
239 free (result);-
240 errno = ENOMEM;-
241 return NULL;-
242 }-
243 final_result[length] = '\0';-
244-
245 return final_result;-
246-
247# else-
248 /* This algorithm is likely faster than the one above. But it may produce-
249 iconv() returns for an E2BIG reason, when the output size guess is too-
250 small. Therefore it can only be used when we don't need the number of-
251 irreversible conversions performed. */-
252 char *result;-
253 size_t result_size;-
254 size_t length;-
255 const char *inptr = src;-
256 size_t inbytes_remaining = strlen (src);-
257-
258 /* Make a guess for the worst-case output size, in order to avoid a-
259 realloc. It's OK if the guess is wrong as long as it is not zero and-
260 doesn't lead to an integer overflow. */-
261 result_size = inbytes_remaining;-
262 {-
263 size_t approx_sqrt_SIZE_MAX = SIZE_MAX >> (sizeof (size_t) * CHAR_BIT / 2);-
264 if (result_size <= approx_sqrt_SIZE_MAX / MB_LEN_MAX)
result_size <=..._SIZE_MAX / 16Description
TRUEevaluated 30 times by 2 tests
Evaluated by:
  • factor
  • ptx
FALSEnever evaluated
0-30
265 result_size *= MB_LEN_MAX;
executed 30 times by 2 tests: result_size *= 16 ;
Executed by:
  • factor
  • ptx
30
266 }-
267 result_size += 1; /* for the terminating NUL */-
268-
269 result = (char *) malloc (result_size);-
270 if (result == NULL)
result == ((void *)0)Description
TRUEnever evaluated
FALSEevaluated 30 times by 2 tests
Evaluated by:
  • factor
  • ptx
0-30
271 {-
272 errno = ENOMEM;-
273 return NULL;
never executed: return ((void *)0) ;
0
274 }-
275-
276 /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */-
277# if defined _LIBICONV_VERSION \-
278 || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \-
279 || defined __sun)-
280 /* Set to the initial state. */-
281 iconv (cd, NULL, NULL, NULL, NULL);-
282# endif-
283-
284 /* Do the conversion. */-
285 {-
286 char *outptr = result;-
287 size_t outbytes_remaining = result_size - 1;-
288-
289 for (;;)-
290 {-
291 /* Here inptr + inbytes_remaining = src + strlen (src),-
292 outptr + outbytes_remaining = result + result_size - 1. */-
293 size_t res = iconv (cd,-
294 (ICONV_CONST char **) &inptr, &inbytes_remaining,-
295 &outptr, &outbytes_remaining);-
296-
297 if (res == (size_t)(-1))
res == (size_t)(-1)Description
TRUEevaluated 15 times by 2 tests
Evaluated by:
  • factor
  • ptx
FALSEevaluated 15 times by 2 tests
Evaluated by:
  • factor
  • ptx
15
298 {-
299 if (errno == EINVAL)
(*__errno_location ()) == 22Description
TRUEnever evaluated
FALSEevaluated 15 times by 2 tests
Evaluated by:
  • factor
  • ptx
0-15
300 break;
never executed: break;
0
301 else if (errno == E2BIG)
(*__errno_location ()) == 7Description
TRUEnever evaluated
FALSEevaluated 15 times by 2 tests
Evaluated by:
  • factor
  • ptx
0-15
302 {-
303 size_t used = outptr - result;-
304 size_t newsize = result_size * 2;-
305 char *newresult;-
306-
307 if (!(newsize > result_size))
!(newsize > result_size)Description
TRUEnever evaluated
FALSEnever evaluated
0
308 {-
309 errno = ENOMEM;-
310 goto failed;
never executed: goto failed;
0
311 }-
312 newresult = (char *) realloc (result, newsize);-
313 if (newresult == NULL)
newresult == ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
314 {-
315 errno = ENOMEM;-
316 goto failed;
never executed: goto failed;
0
317 }-
318 result = newresult;-
319 result_size = newsize;-
320 outptr = result + used;-
321 outbytes_remaining = result_size - 1 - used;-
322 }
never executed: end of block
0
323 else-
324 goto failed;
executed 15 times by 2 tests: goto failed;
Executed by:
  • factor
  • ptx
15
325 }-
326 else-
327 break;
executed 15 times by 2 tests: break;
Executed by:
  • factor
  • ptx
15
328 }-
329 /* Avoid glibc-2.1 bug and Solaris 2.7 bug. */-
330# if defined _LIBICONV_VERSION \-
331 || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \-
332 || defined __sun)-
333 for (;;)-
334 {-
335 /* Here outptr + outbytes_remaining = result + result_size - 1. */-
336 size_t res = iconv (cd, NULL, NULL, &outptr, &outbytes_remaining);-
337-
338 if (res == (size_t)(-1))
res == (size_t)(-1)Description
TRUEnever evaluated
FALSEevaluated 15 times by 2 tests
Evaluated by:
  • factor
  • ptx
0-15
339 {-
340 if (errno == E2BIG)
(*__errno_location ()) == 7Description
TRUEnever evaluated
FALSEnever evaluated
0
341 {-
342 size_t used = outptr - result;-
343 size_t newsize = result_size * 2;-
344 char *newresult;-
345-
346 if (!(newsize > result_size))
!(newsize > result_size)Description
TRUEnever evaluated
FALSEnever evaluated
0
347 {-
348 errno = ENOMEM;-
349 goto failed;
never executed: goto failed;
0
350 }-
351 newresult = (char *) realloc (result, newsize);-
352 if (newresult == NULL)
newresult == ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
353 {-
354 errno = ENOMEM;-
355 goto failed;
never executed: goto failed;
0
356 }-
357 result = newresult;-
358 result_size = newsize;-
359 outptr = result + used;-
360 outbytes_remaining = result_size - 1 - used;-
361 }
never executed: end of block
0
362 else-
363 goto failed;
never executed: goto failed;
0
364 }-
365 else-
366 break;
executed 15 times by 2 tests: break;
Executed by:
  • factor
  • ptx
15
367 }-
368# endif-
369-
370 /* Add the terminating NUL byte. */-
371 *outptr++ = '\0';-
372-
373 length = outptr - result;-
374 }-
375-
376 /* Give away unused memory. */-
377 if (length < result_size)
length < result_sizeDescription
TRUEevaluated 15 times by 2 tests
Evaluated by:
  • factor
  • ptx
FALSEnever evaluated
0-15
378 {-
379 char *smaller_result = (char *) realloc (result, length);-
380-
381 if (smaller_result != NULL)
smaller_result != ((void *)0)Description
TRUEevaluated 15 times by 2 tests
Evaluated by:
  • factor
  • ptx
FALSEnever evaluated
0-15
382 result = smaller_result;
executed 15 times by 2 tests: result = smaller_result;
Executed by:
  • factor
  • ptx
15
383 }
executed 15 times by 2 tests: end of block
Executed by:
  • factor
  • ptx
15
384-
385 return result;
executed 15 times by 2 tests: return result;
Executed by:
  • factor
  • ptx
15
386-
387 failed:-
388 {-
389 int saved_errno = errno;-
390 free (result);-
391 errno = saved_errno;-
392 return NULL;
executed 15 times by 2 tests: return ((void *)0) ;
Executed by:
  • factor
  • ptx
15
393 }-
394-
395# endif-
396}-
397-
398#endif-
399-
400char *-
401str_iconv (const char *src, const char *from_codeset, const char *to_codeset)-
402{-
403 if (*src == '\0' || c_strcasecmp (from_codeset, to_codeset) == 0)
*src == '\0'Description
TRUEnever evaluated
FALSEevaluated 30 times by 2 tests
Evaluated by:
  • factor
  • ptx
c_strcasecmp (..._codeset) == 0Description
TRUEnever evaluated
FALSEevaluated 30 times by 2 tests
Evaluated by:
  • factor
  • ptx
0-30
404 {-
405 char *result = strdup (src);
never executed: __retval = (char *) memcpy (__retval, src , __len);
__retval != ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
((const char *... ))[0] == '\0'Description
TRUEnever evaluated
FALSEnever evaluated
__builtin_constant_p ( src )Description
TRUEnever evaluated
FALSEnever evaluated
((size_t)(cons...)( src ) == 1)Description
TRUEnever evaluated
FALSEnever evaluated
0
406-
407 if (result == NULL)
result == ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
408 errno = ENOMEM;
never executed: (*__errno_location ()) = 12 ;
0
409 return result;
never executed: return result;
0
410 }-
411 else-
412 {-
413#if HAVE_ICONV-
414 iconv_t cd;-
415 char *result;-
416-
417 /* Avoid glibc-2.1 bug with EUC-KR. */-
418# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \-
419 && !defined _LIBICONV_VERSION-
420 if (c_strcasecmp (from_codeset, "EUC-KR") == 0-
421 || c_strcasecmp (to_codeset, "EUC-KR") == 0)-
422 {-
423 errno = EINVAL;-
424 return NULL;-
425 }-
426# endif-
427 cd = iconv_open (to_codeset, from_codeset);-
428 if (cd == (iconv_t) -1)
cd == (iconv_t) -1Description
TRUEnever evaluated
FALSEevaluated 30 times by 2 tests
Evaluated by:
  • factor
  • ptx
0-30
429 return NULL;
never executed: return ((void *)0) ;
0
430-
431 result = str_cd_iconv (src, cd);-
432-
433 if (result == NULL)
result == ((void *)0)Description
TRUEevaluated 15 times by 2 tests
Evaluated by:
  • factor
  • ptx
FALSEevaluated 15 times by 2 tests
Evaluated by:
  • factor
  • ptx
15
434 {-
435 /* Close cd, but preserve the errno from str_cd_iconv. */-
436 int saved_errno = errno;-
437 iconv_close (cd);-
438 errno = saved_errno;-
439 }
executed 15 times by 2 tests: end of block
Executed by:
  • factor
  • ptx
15
440 else-
441 {-
442 if (iconv_close (cd) < 0)
iconv_close (cd) < 0Description
TRUEnever evaluated
FALSEevaluated 15 times by 2 tests
Evaluated by:
  • factor
  • ptx
0-15
443 {-
444 /* Return NULL, but free the allocated memory, and while doing-
445 that, preserve the errno from iconv_close. */-
446 int saved_errno = errno;-
447 free (result);-
448 errno = saved_errno;-
449 return NULL;
never executed: return ((void *)0) ;
0
450 }-
451 }
executed 15 times by 2 tests: end of block
Executed by:
  • factor
  • ptx
15
452 return result;
executed 30 times by 2 tests: return result;
Executed by:
  • factor
  • ptx
30
453#else-
454 /* This is a different error code than if iconv_open existed but didn't-
455 support from_codeset and to_codeset, so that the caller can emit-
456 an error message such as-
457 "iconv() is not supported. Installing GNU libiconv and-
458 then reinstalling this package would fix this." */-
459 errno = ENOSYS;-
460 return NULL;-
461#endif-
462 }-
463}-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.1.2