Coverage Report

Created: 2023-03-26 07:33

/src/gnutls/lib/str-iconv.c
Line
Count
Source (jump to first uncovered line)
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
0
{
40
0
  unsigned convert = 0;
41
0
  unsigned i;
42
0
  uint8_t tmp;
43
44
#ifdef WORDS_BIGENDIAN
45
  if (!be)
46
    convert = 1;
47
#else
48
0
  if (be)
49
0
    convert = 1;
50
0
#endif
51
52
  /* convert to LE */
53
0
  if (convert) {
54
0
    for (i = 0; i < size; i += 2) {
55
0
      tmp = src[i];
56
0
      dst[i] = src[1 + i];
57
0
      dst[1 + i] = tmp;
58
0
    }
59
0
  } else {
60
0
    if (dst != src)
61
0
      memcpy(dst, src, size);
62
0
  }
63
0
}
64
65
int _gnutls_ucs2_to_utf8(const void *data, size_t size,
66
       gnutls_datum_t * output, unsigned be)
67
0
{
68
0
  int ret;
69
0
  size_t dstlen;
70
0
  void *src;
71
0
  uint8_t *tmp_dst = NULL;
72
0
  uint8_t *dst = NULL;
73
74
0
  if (size > 2 && ((uint8_t *) data)[size - 1] == 0
75
0
      && ((uint8_t *) data)[size - 2] == 0) {
76
0
    size -= 2;
77
0
  }
78
79
0
  if (size == 0)
80
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
81
82
0
  src = gnutls_malloc(size + 2);
83
0
  if (src == NULL)
84
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
85
86
  /* convert to LE if needed */
87
0
  change_u16_endianness(src, data, size, be);
88
89
0
  dstlen = 0;
90
0
  tmp_dst = u16_to_u8((uint16_t *) src, size / 2, NULL, &dstlen);
91
0
  if (tmp_dst == NULL) {
92
0
    ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
93
0
    goto fail;
94
0
  }
95
96
0
  dst = gnutls_malloc(dstlen + 1);
97
0
  if (dst == NULL) {
98
0
    gnutls_assert();
99
0
    ret = GNUTLS_E_MEMORY_ERROR;
100
0
    goto fail;
101
0
  }
102
103
0
  memcpy(dst, tmp_dst, dstlen);
104
0
  dst[dstlen] = 0;
105
106
0
  output->data = (void *)dst;
107
0
  output->size = dstlen;
108
109
0
  ret = 0;
110
0
  goto cleanup;
111
112
0
 fail:
113
0
  gnutls_free(dst);
114
115
0
 cleanup:
116
0
  gnutls_free(src);
117
0
  free(tmp_dst);
118
119
0
  return ret;
120
0
}
121
122
int _gnutls_utf8_to_ucs2(const void *data, size_t size,
123
       gnutls_datum_t * output, unsigned be)
124
0
{
125
0
  int ret;
126
0
  size_t dstlen, nrm_size = 0, tmp_size = 0;
127
0
  uint16_t *tmp_dst = NULL;
128
0
  uint16_t *nrm_dst = NULL;
129
0
  uint8_t *dst = NULL;
130
131
0
  if (size == 0)
132
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
133
134
0
  tmp_dst = u8_to_u16(data, size, NULL, &tmp_size);
135
0
  if (tmp_dst == NULL)
136
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
137
138
0
  nrm_dst =
139
0
      u16_normalize(UNINORM_NFC, tmp_dst, tmp_size, NULL, &nrm_size);
140
0
  if (nrm_dst == NULL) {
141
0
    ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
142
0
    goto fail;
143
0
  }
144
145
0
  dstlen = nrm_size * 2;  /* convert to bytes */
146
147
0
  dst = gnutls_malloc(dstlen + 2);
148
0
  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
0
  change_u16_endianness(dst, (uint8_t *) tmp_dst, dstlen, be);
156
0
  dst[dstlen] = 0;
157
0
  dst[dstlen + 1] = 0;
158
159
0
  output->data = (void *)dst;
160
0
  output->size = dstlen;
161
162
0
  ret = 0;
163
0
  goto cleanup;
164
165
0
 fail:
166
0
  gnutls_free(dst);
167
168
0
 cleanup:
169
0
  free(tmp_dst);
170
0
  free(nrm_dst);
171
172
0
  return ret;
173
0
}