Coverage Report

Created: 2026-11-12 06:28

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
/* Copies @units 16-bit code units from @src to @dst, converting them
38
 * from or to the requested endianness. @src and @dst must not overlap,
39
 * unless they are the same buffer, as the copy is done with memcpy().
40
 */
41
static void change_u16_endianness(uint8_t *dst, const uint8_t *src,
42
          size_t units, unsigned be)
43
0
{
44
0
  unsigned convert = 0;
45
0
  size_t i;
46
0
  uint8_t tmp;
47
48
#ifdef WORDS_BIGENDIAN
49
  if (!be)
50
    convert = 1;
51
#else
52
0
  if (be)
53
0
    convert = 1;
54
0
#endif
55
56
  /* convert to LE */
57
0
  if (convert) {
58
0
    for (i = 0; i < units; i++) {
59
0
      tmp = src[2 * i];
60
0
      dst[2 * i] = src[2 * i + 1];
61
0
      dst[2 * i + 1] = tmp;
62
0
    }
63
0
  } else {
64
0
    if (dst != src)
65
0
      memcpy(dst, src, units * 2);
66
0
  }
67
0
}
68
69
int _gnutls_ucs2_to_utf8(const void *data, size_t size, gnutls_datum_t *output,
70
       unsigned be)
71
0
{
72
0
  int ret;
73
0
  size_t dstlen;
74
0
  void *src;
75
0
  uint8_t *tmp_dst = NULL;
76
0
  uint8_t *dst = NULL;
77
78
0
  if (size > 2 && ((uint8_t *)data)[size - 1] == 0 &&
79
0
      ((uint8_t *)data)[size - 2] == 0) {
80
0
    size -= 2;
81
0
  }
82
83
0
  if (size == 0 || size % 2 != 0)
84
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
85
86
0
  src = gnutls_malloc(size + 2);
87
0
  if (src == NULL)
88
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
89
90
  /* convert to LE if needed */
91
0
  change_u16_endianness(src, data, size / 2, be);
92
93
0
  dstlen = 0;
94
0
  tmp_dst = u16_to_u8((uint16_t *)src, size / 2, NULL, &dstlen);
95
0
  if (tmp_dst == NULL) {
96
0
    ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
97
0
    goto fail;
98
0
  }
99
100
0
  dst = gnutls_malloc(dstlen + 1);
101
0
  if (dst == NULL) {
102
0
    gnutls_assert();
103
0
    ret = GNUTLS_E_MEMORY_ERROR;
104
0
    goto fail;
105
0
  }
106
107
0
  memcpy(dst, tmp_dst, dstlen);
108
0
  dst[dstlen] = 0;
109
110
0
  output->data = (void *)dst;
111
0
  output->size = dstlen;
112
113
0
  ret = 0;
114
0
  goto cleanup;
115
116
0
fail:
117
0
  gnutls_free(dst);
118
119
0
cleanup:
120
0
  gnutls_free(src);
121
0
  free(tmp_dst);
122
123
0
  return ret;
124
0
}
125
126
int _gnutls_utf8_to_ucs2(const void *data, size_t size, gnutls_datum_t *output,
127
       unsigned be)
128
0
{
129
0
  int ret;
130
0
  size_t dstlen, nrm_size = 0, tmp_size = 0;
131
0
  uint16_t *tmp_dst = NULL;
132
0
  uint16_t *nrm_dst = NULL;
133
0
  uint8_t *dst = NULL;
134
135
0
  if (size == 0)
136
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
137
138
0
  tmp_dst = u8_to_u16(data, size, NULL, &tmp_size);
139
0
  if (tmp_dst == NULL)
140
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
141
142
0
  nrm_dst =
143
0
    u16_normalize(UNINORM_NFC, tmp_dst, tmp_size, NULL, &nrm_size);
144
0
  if (nrm_dst == NULL) {
145
0
    ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
146
0
    goto fail;
147
0
  }
148
149
0
  dstlen = nrm_size * 2; /* convert to bytes */
150
151
0
  dst = gnutls_malloc(dstlen + 2);
152
0
  if (dst == NULL) {
153
0
    gnutls_assert();
154
0
    ret = GNUTLS_E_MEMORY_ERROR;
155
0
    goto fail;
156
0
  }
157
158
  /* convert to BE */
159
0
  change_u16_endianness(dst, (uint8_t *)nrm_dst, nrm_size, be);
160
0
  dst[dstlen] = 0;
161
0
  dst[dstlen + 1] = 0;
162
163
0
  output->data = (void *)dst;
164
0
  output->size = dstlen;
165
166
0
  ret = 0;
167
0
  goto cleanup;
168
169
0
fail:
170
0
  gnutls_free(dst);
171
172
0
cleanup:
173
0
  free(tmp_dst);
174
0
  free(nrm_dst);
175
176
0
  return ret;
177
0
}