Bug Summary

File:lookup.c
Location:line 226, column 3
Description:Value stored to 'e' is never read

Annotated Source Code

1/* lookup.c - implementation of IDNA2008 lookup functions
2 Copyright (C) 2011-2017 Simon Josefsson
3
4 Libidn2 is free software: you can redistribute it and/or modify it
5 under the terms of either:
6
7 * the GNU Lesser General Public License as published by the Free
8 Software Foundation; either version 3 of the License, or (at
9 your option) any later version.
10
11 or
12
13 * the GNU General Public License as published by the Free
14 Software Foundation; either version 2 of the License, or (at
15 your option) any later version.
16
17 or both in parallel, as here.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received copies of the GNU General Public License and
25 the GNU Lesser General Public License along with this program. If
26 not, see <http://www.gnu.org/licenses/>.
27*/
28
29#include <config.h>
30
31#include "idn2.h"
32
33#include <errno(*__errno_location ()).h> /* errno */
34#include <stdlib.h> /* malloc, free */
35
36#include "punycode.h"
37
38#include <unitypes.h>
39#include <uniconv.h> /* u8_strconv_from_locale */
40#include <uninorm.h> /* u32_normalize */
41#include <unistr.h> /* u8_to_u32 */
42
43#include "idna.h" /* _idn2_label_test */
44#include "tr46map.h" /* defintion for tr46map.c */
45
46static int
47label (const uint8_t * src, size_t srclen, uint8_t * dst, size_t * dstlen,
48 int flags)
49{
50 size_t plen;
51 uint32_t *p;
52 int rc;
53 size_t tmpl;
54
55 if (_idn2_ascii_p (src, srclen))
56 {
57 if (flags & IDN2_ALABEL_ROUNDTRIP)
58 /* FIXME implement this MAY:
59
60 If the input to this procedure appears to be an A-label
61 (i.e., it starts in "xn--", interpreted
62 case-insensitively), the lookup application MAY attempt to
63 convert it to a U-label, first ensuring that the A-label is
64 entirely in lowercase (converting it to lowercase if
65 necessary), and apply the tests of Section 5.4 and the
66 conversion of Section 5.5 to that form. */
67 return -1;
68
69 if (srclen > IDN2_LABEL_MAX_LENGTH63)
70 return IDN2_TOO_BIG_LABEL;
71 if (srclen > *dstlen)
72 return IDN2_TOO_BIG_DOMAIN;
73
74 memcpy (dst, src, srclen);
75 *dstlen = srclen;
76 return IDN2_OK;
77 }
78
79 rc = _idn2_u8_to_u32_nfc (src, srclen, &p, &plen, flags & IDN2_NFC_INPUT);
80 if (rc != IDN2_OK)
81 return rc;
82
83 rc = _idn2_label_test (TEST_NFC |
84 TEST_2HYPHEN |
85 TEST_LEADING_COMBINING |
86 TEST_DISALLOWED |
87 TEST_CONTEXTJ_RULE |
88 TEST_CONTEXTO_WITH_RULE |
89 TEST_UNASSIGNED | TEST_BIDI, p, plen);
90 if (rc != IDN2_OK)
91 {
92 free (p);
93 return rc;
94 }
95
96 dst[0] = 'x';
97 dst[1] = 'n';
98 dst[2] = '-';
99 dst[3] = '-';
100
101 tmpl = *dstlen - 4;
102 rc = _idn2_punycode_encode (plen, p, NULL((void*)0), &tmpl, (char *) dst + 4);
103 free (p);
104 if (rc != IDN2_OK)
105 return rc;
106
107 *dstlen = 4 + tmpl;
108
109 return IDN2_OK;
110}
111
112#define TR46_TRANSITIONAL_CHECK(TEST_NFC | TEST_2HYPHEN | TEST_HYPHEN_STARTEND | TEST_LEADING_COMBINING
| TEST_TRANSITIONAL)
\
113 (TEST_NFC | TEST_2HYPHEN | TEST_HYPHEN_STARTEND | TEST_LEADING_COMBINING | TEST_TRANSITIONAL)
114#define TR46_NONTRANSITIONAL_CHECK(TEST_NFC | TEST_2HYPHEN | TEST_HYPHEN_STARTEND | TEST_LEADING_COMBINING
| TEST_NONTRANSITIONAL)
\
115 (TEST_NFC | TEST_2HYPHEN | TEST_HYPHEN_STARTEND | TEST_LEADING_COMBINING | TEST_NONTRANSITIONAL)
116
117static int
118_tr46 (const uint8_t * domain_u8, uint8_t ** out, int transitional)
119{
120 size_t len, it;
121 uint32_t *domain_u32;
122 int err = IDN2_OK, rc;
123
124 /* convert UTF-8 to UTF-32 */
125 if (!
126 (domain_u32 =
127 u8_to_u32 (domain_u8, u8_strlen (domain_u8) + 1, NULL((void*)0), &len)))
128 {
129 if (errno(*__errno_location ()) == ENOMEM12)
130 return IDN2_MALLOC;
131 return IDN2_ENCODING_ERROR;
132 }
133
134 size_t len2 = 0;
135 for (it = 0; it < len - 1; it++)
136 {
137 IDNAMap map;
138
139 get_idna_map (domain_u32[it], &map);
140
141 if (map_is (&map, TR46_FLG_DISALLOWED16))
142 {
143 if (domain_u32[it])
144 {
145 free (domain_u32);
146 return IDN2_DISALLOWED;
147 }
148 len2++;
149 }
150 else if (map_is (&map, TR46_FLG_MAPPED2))
151 {
152 len2 += map.nmappings;
153 }
154 else if (map_is (&map, TR46_FLG_VALID1))
155 {
156 len2++;
157 }
158 else if (map_is (&map, TR46_FLG_IGNORED4))
159 {
160 continue;
161 }
162 else if (map_is (&map, TR46_FLG_DEVIATION8))
163 {
164 if (transitional)
165 {
166 len2 += map.nmappings;
167 }
168 else
169 len2++;
170 }
171 }
172
173 uint32_t *tmp = malloc ((len2 + 1) * sizeof (uint32_t));
174
175 len2 = 0;
176 for (it = 0; it < len - 1; it++)
177 {
178 uint32_t c = domain_u32[it];
179 IDNAMap map;
180
181 get_idna_map (c, &map);
182
183 if (map_is (&map, TR46_FLG_DISALLOWED16))
184 {
185 tmp[len2++] = c;
186 }
187 else if (map_is (&map, TR46_FLG_MAPPED2))
188 {
189 len2 += get_map_data (tmp + len2, &map);
190 }
191 else if (map_is (&map, TR46_FLG_VALID1))
192 {
193 tmp[len2++] = c;
194 }
195 else if (map_is (&map, TR46_FLG_IGNORED4))
196 {
197 continue;
198 }
199 else if (map_is (&map, TR46_FLG_DEVIATION8))
200 {
201 if (transitional)
202 {
203 len2 += get_map_data (tmp + len2, &map);
204 }
205 else
206 tmp[len2++] = c;
207 }
208 }
209 free (domain_u32);
210
211 /* Normalize to NFC */
212 tmp[len2] = 0;
213 domain_u32 = u32_normalize (UNINORM_NFC(&uninorm_nfc), tmp, len2 + 1, NULL((void*)0), &len);
214 free (tmp);
215 tmp = NULL((void*)0);
216
217 if (!domain_u32)
218 {
219 if (errno(*__errno_location ()) == ENOMEM12)
220 return IDN2_MALLOC;
221 return IDN2_ENCODING_ERROR;
222 }
223
224 /* split into labels and check */
225 uint32_t *e, *s;
226 e = s = domain_u32;
Value stored to 'e' is never read
227 for (e = s = domain_u32; *e; s = e)
228 {
229 while (*e && *e != '.')
230 e++;
231
232 if (e - s >= 4 && s[0] == 'x' && s[1] == 'n' && s[2] == '-'
233 && s[3] == '-')
234 {
235 /* decode punycode and check result non-transitional */
236 size_t ace_len;
237 uint32_t name_u32[IDN2_LABEL_MAX_LENGTH63];
238 size_t name_len = IDN2_LABEL_MAX_LENGTH63;
239 uint8_t *ace;
240
241 ace = u32_to_u8 (s + 4, e - s - 4, NULL((void*)0), &ace_len);
242 if (!ace)
243 {
244 free (domain_u32);
245 if (errno(*__errno_location ()) == ENOMEM12)
246 return IDN2_MALLOC;
247 return IDN2_ENCODING_ERROR;
248 }
249
250 rc =
251 _idn2_punycode_decode (ace_len, (char *) ace, &name_len, name_u32,
252 NULL((void*)0));
253
254 free (ace);
255
256 if (rc)
257 {
258 free (domain_u32);
259 return rc;
260 }
261
262 if ((rc =
263 _idn2_label_test (TR46_NONTRANSITIONAL_CHECK(TEST_NFC | TEST_2HYPHEN | TEST_HYPHEN_STARTEND | TEST_LEADING_COMBINING
| TEST_NONTRANSITIONAL)
, name_u32,
264 name_len)))
265 err = rc;
266 }
267 else
268 {
269 if ((rc =
270 _idn2_label_test (transitional ? TR46_TRANSITIONAL_CHECK(TEST_NFC | TEST_2HYPHEN | TEST_HYPHEN_STARTEND | TEST_LEADING_COMBINING
| TEST_TRANSITIONAL)
:
271 TR46_NONTRANSITIONAL_CHECK(TEST_NFC | TEST_2HYPHEN | TEST_HYPHEN_STARTEND | TEST_LEADING_COMBINING
| TEST_NONTRANSITIONAL)
, s, e - s)))
272 err = rc;
273 }
274
275 if (*e)
276 e++;
277 }
278
279 if (err == IDN2_OK && out)
280 {
281 uint8_t *_out = u32_to_u8 (domain_u32, len, NULL((void*)0), &len);
282 free (domain_u32);
283
284 if (!_out)
285 {
286 if (errno(*__errno_location ()) == ENOMEM12)
287 return IDN2_MALLOC;
288 return IDN2_ENCODING_ERROR;
289 }
290
291 *out = _out;
292 }
293 else
294 free (domain_u32);
295
296 return err;
297}
298
299/**
300 * idn2_lookup_u8:
301 * @src: input zero-terminated UTF-8 string in Unicode NFC normalized form.
302 * @lookupname: newly allocated output variable with name to lookup in DNS.
303 * @flags: optional #idn2_flags to modify behaviour.
304 *
305 * Perform IDNA2008 lookup string conversion on domain name @src, as
306 * described in section 5 of RFC 5891. Note that the input string
307 * must be encoded in UTF-8 and be in Unicode NFC form.
308 *
309 * Pass %IDN2_NFC_INPUT in @flags to convert input to NFC form before
310 * further processing. Pass %IDN2_ALABEL_ROUNDTRIP in @flags to
311 * convert any input A-labels to U-labels and perform additional
312 * testing. Pass %IDN2_TRANSITIONAL to enable Unicode TR46
313 * transitional processing, and %IDN2_NONTRANSITIONAL to enable
314 * Unicode TR46 non-transitional processing. Multiple flags may be
315 * specified by binary or:ing them together, for example
316 * %IDN2_NFC_INPUT | %IDN2_NONTRANSITIONAL.
317 *
318 * After version 0.11: @lookupname may be NULL to test lookup of @src
319 * without allocating memory.
320 *
321 * Returns: On successful conversion %IDN2_OK is returned, if the
322 * output domain or any label would have been too long
323 * %IDN2_TOO_BIG_DOMAIN or %IDN2_TOO_BIG_LABEL is returned, or
324 * another error code is returned.
325 **/
326int
327idn2_lookup_u8 (const uint8_t * src, uint8_t ** lookupname, int flags)
328{
329 size_t lookupnamelen = 0;
330 uint8_t _lookupname[IDN2_DOMAIN_MAX_LENGTH255 + 1];
331 uint8_t _mapped[IDN2_DOMAIN_MAX_LENGTH255 + 1];
332 int rc, tr46_mode = 0;
333
334 if (src == NULL((void*)0))
335 {
336 if (lookupname)
337 *lookupname = NULL((void*)0);
338 return IDN2_OK;
339 }
340
341 if ((flags & (IDN2_TRANSITIONAL | IDN2_NONTRANSITIONAL)) ==
342 (IDN2_TRANSITIONAL | IDN2_NONTRANSITIONAL))
343 return IDN2_INVALID_FLAGS;
344
345 if (flags & IDN2_TRANSITIONAL)
346 tr46_mode = IDN2_TRANSITIONAL;
347 else if (flags & IDN2_NONTRANSITIONAL)
348 tr46_mode = IDN2_NONTRANSITIONAL;
349
350 if (tr46_mode)
351 {
352 uint8_t *out;
353 size_t outlen;
354
355 rc = _tr46 (src, &out, tr46_mode == IDN2_TRANSITIONAL);
356 if (rc != IDN2_OK)
357 return rc;
358
359 outlen = u8_strlen (out);
360 if (outlen >= sizeof (_mapped))
361 {
362 free (out);
363 return IDN2_TOO_BIG_DOMAIN;
364 }
365
366 memcpy (_mapped, out, outlen + 1);
367 src = _mapped;
368 free (out);
369 }
370
371 do
372 {
373 const uint8_t *end = (uint8_t *) strchrnul ((const char *) src, '.');
374 /* XXX Do we care about non-U+002E dots such as U+3002, U+FF0E
375 and U+FF61 here? Perhaps when IDN2_NFC_INPUT? */
376 size_t labellen = end - src;
377 uint8_t tmp[IDN2_LABEL_MAX_LENGTH63];
378 size_t tmplen = IDN2_LABEL_MAX_LENGTH63;
379
380 rc = label (src, labellen, tmp, &tmplen, flags);
381 if (rc != IDN2_OK)
382 return rc;
383
384 if (lookupnamelen + tmplen
385 > IDN2_DOMAIN_MAX_LENGTH255 - (tmplen == 0 && *end == '\0' ? 1 : 2))
386 return IDN2_TOO_BIG_DOMAIN;
387
388 memcpy (_lookupname + lookupnamelen, tmp, tmplen);
389 lookupnamelen += tmplen;
390
391 if (*end == '.')
392 {
393 if (lookupnamelen + 1 > IDN2_DOMAIN_MAX_LENGTH255)
394 return IDN2_TOO_BIG_DOMAIN;
395
396 _lookupname[lookupnamelen] = '.';
397 lookupnamelen++;
398 }
399 _lookupname[lookupnamelen] = '\0';
400
401 src = end;
402 }
403 while (*src++);
404
405 if (lookupname)
406 {
407 uint8_t *tmp = malloc (lookupnamelen + 1);
408
409 if (tmp == NULL((void*)0))
410 return IDN2_MALLOC;
411
412 memcpy (tmp, _lookupname, lookupnamelen + 1);
413 *lookupname = tmp;
414 }
415
416 return IDN2_OK;
417}
418
419/**
420 * idn2_lookup_ul:
421 * @src: input zero-terminated locale encoded string.
422 * @lookupname: newly allocated output variable with name to lookup in DNS.
423 * @flags: optional #idn2_flags to modify behaviour.
424 *
425 * Perform IDNA2008 lookup string conversion on domain name @src, as
426 * described in section 5 of RFC 5891. Note that the input is assumed
427 * to be encoded in the locale's default coding system, and will be
428 * transcoded to UTF-8 and NFC normalized by this function.
429 *
430 * Pass %IDN2_ALABEL_ROUNDTRIP in @flags to convert any input A-labels
431 * to U-labels and perform additional testing. Pass
432 * %IDN2_TRANSITIONAL to enable Unicode TR46 transitional processing,
433 * and %IDN2_NONTRANSITIONAL to enable Unicode TR46 non-transitional
434 * processing. Multiple flags may be specified by binary or:ing them
435 * together, for example %IDN2_ALABEL_ROUNDTRIP |
436 * %IDN2_NONTRANSITIONAL. The %IDN2_NFC_INPUT in @flags is always
437 * enabled in this function.
438 *
439 * After version 0.11: @lookupname may be NULL to test lookup of @src
440 * without allocating memory.
441 *
442 * Returns: On successful conversion %IDN2_OK is returned, if
443 * conversion from locale to UTF-8 fails then %IDN2_ICONV_FAIL is
444 * returned, if the output domain or any label would have been too
445 * long %IDN2_TOO_BIG_DOMAIN or %IDN2_TOO_BIG_LABEL is returned, or
446 * another error code is returned.
447 **/
448int
449idn2_lookup_ul (const char *src, char **lookupname, int flags)
450{
451 uint8_t *utf8src = NULL((void*)0);
452 int rc;
453
454 if (src)
455 {
456 utf8src = u8_strconv_from_locale (src);
457 if (utf8src == NULL((void*)0))
458 {
459 if (errno(*__errno_location ()) == ENOMEM12)
460 return IDN2_MALLOC;
461 return IDN2_ICONV_FAIL;
462 }
463 }
464
465 rc = idn2_lookup_u8 (utf8src, (uint8_t **) lookupname,
466 flags | IDN2_NFC_INPUT);
467
468 free (utf8src);
469
470 return rc;
471}