Coverage Report

Created: 2023-11-19 07:06

/src/c-ares/src/lib/ares_parse_txt_reply.c
Line
Count
Source (jump to first uncovered line)
1
/* MIT License
2
 *
3
 * Copyright (c) 2023 Brad House
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining a copy
6
 * of this software and associated documentation files (the "Software"), to deal
7
 * in the Software without restriction, including without limitation the rights
8
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the Software is
10
 * furnished to do so, subject to the following conditions:
11
 *
12
 * The above copyright notice and this permission notice (including the next
13
 * paragraph) shall be included in all copies or substantial portions of the
14
 * Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
 * SOFTWARE.
23
 *
24
 * SPDX-License-Identifier: MIT
25
 */
26
27
#include "ares_setup.h"
28
#include "ares.h"
29
#include "ares_data.h"
30
#include "ares_private.h"
31
32
static int ares__parse_txt_reply(const unsigned char *abuf, size_t alen,
33
                                 ares_bool_t ex, void **txt_out)
34
2.40k
{
35
2.40k
  ares_status_t        status;
36
2.40k
  struct ares_txt_ext *txt_head = NULL;
37
2.40k
  struct ares_txt_ext *txt_last = NULL;
38
2.40k
  struct ares_txt_ext *txt_curr;
39
2.40k
  ares_dns_record_t   *dnsrec = NULL;
40
2.40k
  size_t               i;
41
42
2.40k
  *txt_out = NULL;
43
44
2.40k
  status = ares_dns_parse(abuf, alen, 0, &dnsrec);
45
2.40k
  if (status != ARES_SUCCESS) {
46
1.70k
    goto done;
47
1.70k
  }
48
49
700
  if (ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER) == 0) {
50
6
    status = ARES_ENODATA;
51
6
    goto done;
52
6
  }
53
54
82.3k
  for (i = 0; i < ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER); i++) {
55
81.6k
    const ares_dns_rr_t *rr =
56
81.6k
      ares_dns_record_rr_get(dnsrec, ARES_SECTION_ANSWER, i);
57
81.6k
    const unsigned char *ptr;
58
81.6k
    size_t               ptr_len;
59
60
81.6k
    if (rr == NULL) {
61
      /* Shouldn't be possible */
62
0
      status = ARES_EBADRESP;
63
0
      goto done;
64
0
    }
65
66
    /* XXX: Why Chaos? */
67
81.6k
    if ((ares_dns_rr_get_class(rr) != ARES_CLASS_IN &&
68
81.6k
         ares_dns_rr_get_class(rr) != ARES_CLASS_CHAOS) ||
69
81.6k
        ares_dns_rr_get_type(rr) != ARES_REC_TYPE_TXT) {
70
81.3k
      continue;
71
81.3k
    }
72
73
    /* Allocate storage for this TXT answer appending it to the list */
74
322
    txt_curr =
75
322
      ares_malloc_data(ex ? ARES_DATATYPE_TXT_EXT : ARES_DATATYPE_TXT_REPLY);
76
322
    if (txt_curr == NULL) {
77
0
      status = ARES_ENOMEM;
78
0
      goto done;
79
0
    }
80
81
    /* Link in the record */
82
322
    if (txt_last) {
83
292
      txt_last->next = txt_curr;
84
292
    } else {
85
30
      txt_head = txt_curr;
86
30
    }
87
322
    txt_last = txt_curr;
88
89
    /* These days, records are joined, always tag as start */
90
322
    if (ex) {
91
0
      txt_curr->record_start = 1;
92
0
    }
93
94
322
    ptr = ares_dns_rr_get_bin(rr, ARES_RR_TXT_DATA, &ptr_len);
95
96
322
    txt_curr->txt = ares_malloc(ptr_len + 1);
97
322
    if (txt_curr->txt == NULL) {
98
0
      status = ARES_ENOMEM;
99
0
      goto done;
100
0
    }
101
322
    memcpy(txt_curr->txt, ptr, ptr_len);
102
322
    txt_curr->txt[ptr_len] = 0;
103
322
    txt_curr->length       = ptr_len;
104
322
  }
105
106
2.40k
done:
107
  /* clean up on error */
108
2.40k
  if (status != ARES_SUCCESS) {
109
1.71k
    if (txt_head) {
110
0
      ares_free_data(txt_head);
111
0
    }
112
1.71k
  } else {
113
    /* everything looks fine, return the data */
114
694
    *txt_out = txt_head;
115
694
  }
116
2.40k
  ares_dns_record_destroy(dnsrec);
117
2.40k
  return (int)status;
118
694
}
119
120
int ares_parse_txt_reply(const unsigned char *abuf, int alen,
121
                         struct ares_txt_reply **txt_out)
122
2.40k
{
123
2.40k
  if (alen < 0) {
124
0
    return ARES_EBADRESP;
125
0
  }
126
2.40k
  return ares__parse_txt_reply(abuf, (size_t)alen, ARES_FALSE,
127
2.40k
                               (void **)txt_out);
128
2.40k
}
129
130
int ares_parse_txt_reply_ext(const unsigned char *abuf, int alen,
131
                             struct ares_txt_ext **txt_out)
132
0
{
133
0
  if (alen < 0) {
134
0
    return ARES_EBADRESP;
135
0
  }
136
0
  return ares__parse_txt_reply(abuf, (size_t)alen, ARES_TRUE, (void **)txt_out);
137
0
}