Coverage Report

Created: 2026-02-14 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/lib/str-iconv.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2010-2016 Free Software Foundation, Inc.
3
 * Copyright (C) 2015-2016 Red Hat, Inc.
4
 *
5
 * Author: Nikos Mavrogiannopoulos
6
 *
7
 * This file is part of GnuTLS.
8
 *
9
 * The GnuTLS is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public License
11
 * as published by the Free Software Foundation; either version 2.1 of
12
 * the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
21
 *
22
 */
23
24
#include "config.h"
25
#include "system.h"
26
#include "gnutls_int.h"
27
#include "errors.h"
28
29
#include <sys/socket.h>
30
#include <errno.h>
31
#include <sys/stat.h>
32
#include <sys/types.h>
33
#include <unistr.h>
34
#include <uninorm.h>
35
#include "num.h"
36
37
static void change_u16_endianness(uint8_t *dst, const uint8_t *src,
38
          unsigned size, unsigned be)
39
37.2k
{
40
37.2k
  unsigned convert = 0;
41
37.2k
  unsigned i;
42
37.2k
  uint8_t tmp;
43
44
#ifdef WORDS_BIGENDIAN
45
  if (!be)
46
    convert = 1;
47
#else
48
37.2k
  if (be)
49
37.2k
    convert = 1;
50
37.2k
#endif
51
52
  /* convert to LE */
53
37.2k
  if (convert) {
54
237k
    for (i = 0; i < size; i += 2) {
55
200k
      tmp = src[i];
56
200k
      dst[i] = src[1 + i];
57
200k
      dst[1 + i] = tmp;
58
200k
    }
59
37.2k
  } else {
60
0
    if (dst != src)
61
0
      memcpy(dst, src, size);
62
0
  }
63
37.2k
}
64
65
int _gnutls_ucs2_to_utf8(const void *data, size_t size, gnutls_datum_t *output,
66
       unsigned be)
67
26.9k
{
68
26.9k
  int ret;
69
26.9k
  size_t dstlen;
70
26.9k
  void *src;
71
26.9k
  uint8_t *tmp_dst = NULL;
72
26.9k
  uint8_t *dst = NULL;
73
74
26.9k
  if (size > 2 && ((uint8_t *)data)[size - 1] == 0 &&
75
7.81k
      ((uint8_t *)data)[size - 2] == 0) {
76
2.76k
    size -= 2;
77
2.76k
  }
78
79
26.9k
  if (size == 0)
80
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
81
82
26.9k
  src = gnutls_malloc(size + 2);
83
26.9k
  if (src == NULL)
84
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
85
86
  /* convert to LE if needed */
87
26.9k
  change_u16_endianness(src, data, size, be);
88
89
26.9k
  dstlen = 0;
90
26.9k
  tmp_dst = u16_to_u8((uint16_t *)src, size / 2, NULL, &dstlen);
91
26.9k
  if (tmp_dst == NULL) {
92
8.73k
    ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
93
8.73k
    goto fail;
94
8.73k
  }
95
96
18.1k
  dst = gnutls_malloc(dstlen + 1);
97
18.1k
  if (dst == NULL) {
98
0
    gnutls_assert();
99
0
    ret = GNUTLS_E_MEMORY_ERROR;
100
0
    goto fail;
101
0
  }
102
103
18.1k
  memcpy(dst, tmp_dst, dstlen);
104
18.1k
  dst[dstlen] = 0;
105
106
18.1k
  output->data = (void *)dst;
107
18.1k
  output->size = dstlen;
108
109
18.1k
  ret = 0;
110
18.1k
  goto cleanup;
111
112
8.73k
fail:
113
8.73k
  gnutls_free(dst);
114
115
26.9k
cleanup:
116
26.9k
  gnutls_free(src);
117
26.9k
  free(tmp_dst);
118
119
26.9k
  return ret;
120
8.73k
}
121
122
int _gnutls_utf8_to_ucs2(const void *data, size_t size, gnutls_datum_t *output,
123
       unsigned be)
124
10.3k
{
125
10.3k
  int ret;
126
10.3k
  size_t dstlen, nrm_size = 0, tmp_size = 0;
127
10.3k
  uint16_t *tmp_dst = NULL;
128
10.3k
  uint16_t *nrm_dst = NULL;
129
10.3k
  uint8_t *dst = NULL;
130
131
10.3k
  if (size == 0)
132
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
133
134
10.3k
  tmp_dst = u8_to_u16(data, size, NULL, &tmp_size);
135
10.3k
  if (tmp_dst == NULL)
136
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
137
138
10.3k
  nrm_dst =
139
10.3k
    u16_normalize(UNINORM_NFC, tmp_dst, tmp_size, NULL, &nrm_size);
140
10.3k
  if (nrm_dst == NULL) {
141
0
    ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
142
0
    goto fail;
143
0
  }
144
145
10.3k
  dstlen = nrm_size * 2; /* convert to bytes */
146
147
10.3k
  dst = gnutls_malloc(dstlen + 2);
148
10.3k
  if (dst == NULL) {
149
0
    gnutls_assert();
150
0
    ret = GNUTLS_E_MEMORY_ERROR;
151
0
    goto fail;
152
0
  }
153
154
  /* convert to BE */
155
10.3k
  change_u16_endianness(dst, (uint8_t *)tmp_dst, dstlen, be);
156
10.3k
  dst[dstlen] = 0;
157
10.3k
  dst[dstlen + 1] = 0;
158
159
10.3k
  output->data = (void *)dst;
160
10.3k
  output->size = dstlen;
161
162
10.3k
  ret = 0;
163
10.3k
  goto cleanup;
164
165
0
fail:
166
0
  gnutls_free(dst);
167
168
10.3k
cleanup:
169
10.3k
  free(tmp_dst);
170
10.3k
  free(nrm_dst);
171
172
10.3k
  return ret;
173
0
}