Coverage Report

Created: 2026-06-07 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/isc/hex.c
Line
Count
Source
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4
 * SPDX-License-Identifier: MPL-2.0
5
 *
6
 * This Source Code Form is subject to the terms of the Mozilla Public
7
 * License, v. 2.0. If a copy of the MPL was not distributed with this
8
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9
 *
10
 * See the COPYRIGHT file distributed with this work for additional
11
 * information regarding copyright ownership.
12
 */
13
14
/*! \file */
15
16
#include <stdbool.h>
17
18
#include <isc/buffer.h>
19
#include <isc/hex.h>
20
#include <isc/lex.h>
21
#include <isc/string.h>
22
#include <isc/util.h>
23
24
#define D ('0' - 0x0) /* ascii '0' to hex */
25
#define U ('A' - 0xA) /* ascii 'A' to hex */
26
#define L ('a' - 0xa) /* ascii 'a' to hex */
27
28
const uint8_t isc__hex_char[256] = {
29
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31
  0, 0, 0, 0, D, D, D, D, D, D, D, D, D, D, 0, 0, 0, 0, 0, 0, 0, U,
32
  U, U, U, U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33
  0, 0, 0, 0, 0, 0, 0, 0, 0, L, L, L, L, L, L, 0, 0, 0, 0, 0, 0, 0,
34
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
35
};
36
37
#undef D
38
#undef U
39
#undef L
40
41
/*
42
 * BEW: These static functions are copied from lib/dns/rdata.c.
43
 */
44
static isc_result_t
45
str_totext(const char *source, isc_buffer_t *target);
46
47
static isc_result_t
48
mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
49
50
static const char hex[] = "0123456789ABCDEF";
51
52
isc_result_t
53
isc_hex_totext(isc_region_t *source, int wordlength, const char *wordbreak,
54
74.4k
         isc_buffer_t *target) {
55
74.4k
  char buf[3];
56
74.4k
  unsigned int loops = 0;
57
58
74.4k
  if (wordlength < 2) {
59
8.10k
    wordlength = 2;
60
8.10k
  }
61
62
74.4k
  memset(buf, 0, sizeof(buf));
63
2.31M
  while (source->length > 0) {
64
2.23M
    buf[0] = hex[(source->base[0] >> 4) & 0xf];
65
2.23M
    buf[1] = hex[(source->base[0]) & 0xf];
66
2.23M
    RETERR(str_totext(buf, target));
67
2.23M
    isc_region_consume(source, 1);
68
69
2.23M
    loops++;
70
2.23M
    if (source->length != 0 && (int)((loops + 1) * 2) >= wordlength)
71
157k
    {
72
157k
      loops = 0;
73
157k
      RETERR(str_totext(wordbreak, target));
74
157k
    }
75
2.23M
  }
76
74.4k
  return ISC_R_SUCCESS;
77
74.4k
}
78
79
void
80
322k
isc_hex_decodeinit(isc_hex_decodectx_t *ctx, int length, isc_buffer_t *target) {
81
322k
  ctx->digits = 0;
82
322k
  ctx->length = length;
83
322k
  ctx->target = target;
84
322k
}
85
86
isc_result_t
87
3.81M
isc_hex_decodechar(isc_hex_decodectx_t *ctx, int c) {
88
3.81M
  uint8_t hexval;
89
90
3.81M
  hexval = isc_hex_char(c);
91
3.81M
  if (hexval == 0) {
92
118
    return ISC_R_BADHEX;
93
118
  }
94
3.81M
  ctx->val[ctx->digits++] = c - hexval;
95
3.81M
  if (ctx->digits == 2) {
96
1.90M
    unsigned char num;
97
98
1.90M
    num = (ctx->val[0] << 4) + (ctx->val[1]);
99
1.90M
    RETERR(mem_tobuffer(ctx->target, &num, 1));
100
1.90M
    if (ctx->length >= 0) {
101
1.60M
      if (ctx->length == 0) {
102
2
        return ISC_R_BADHEX;
103
1.60M
      } else {
104
1.60M
        ctx->length -= 1;
105
1.60M
      }
106
1.60M
    }
107
1.90M
    ctx->digits = 0;
108
1.90M
  }
109
3.81M
  return ISC_R_SUCCESS;
110
3.81M
}
111
112
isc_result_t
113
322k
isc_hex_decodefinish(isc_hex_decodectx_t *ctx) {
114
322k
  if (ctx->length > 0) {
115
0
    return ISC_R_UNEXPECTEDEND;
116
0
  }
117
322k
  if (ctx->digits != 0) {
118
62
    return ISC_R_BADHEX;
119
62
  }
120
322k
  return ISC_R_SUCCESS;
121
322k
}
122
123
isc_result_t
124
318k
isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
125
318k
  unsigned int before, after;
126
318k
  isc_hex_decodectx_t ctx;
127
318k
  isc_textregion_t *tr;
128
318k
  isc_token_t token;
129
318k
  bool eol;
130
131
318k
  REQUIRE(length >= isc_one_or_more);
132
133
318k
  isc_hex_decodeinit(&ctx, length, target);
134
135
318k
  before = isc_buffer_usedlength(target);
136
744k
  while (ctx.length != 0) {
137
432k
    unsigned int i;
138
139
432k
    if (length > 0) {
140
394k
      eol = false;
141
394k
    } else {
142
37.9k
      eol = true;
143
37.9k
    }
144
432k
    RETERR(isc_lex_getmastertoken(lexer, &token,
145
432k
                isc_tokentype_string, eol));
146
432k
    if (token.type != isc_tokentype_string) {
147
5.97k
      break;
148
5.97k
    }
149
426k
    tr = &token.value.as_textregion;
150
4.21M
    for (i = 0; i < tr->length; i++) {
151
3.79M
      RETERR(isc_hex_decodechar(&ctx, tr->base[i]));
152
3.79M
    }
153
426k
  }
154
317k
  after = isc_buffer_usedlength(target);
155
317k
  if (ctx.length < 0) {
156
5.97k
    isc_lex_ungettoken(lexer, &token);
157
5.97k
  }
158
317k
  RETERR(isc_hex_decodefinish(&ctx));
159
317k
  if (length == isc_one_or_more && before == after) {
160
36
    return ISC_R_UNEXPECTEDEND;
161
36
  }
162
317k
  return ISC_R_SUCCESS;
163
317k
}
164
165
isc_result_t
166
4.32k
isc_hex_decodestring(const char *cstr, isc_buffer_t *target) {
167
4.32k
  isc_hex_decodectx_t ctx;
168
169
4.32k
  isc_hex_decodeinit(&ctx, isc_zero_or_more, target);
170
30.8k
  for (;;) {
171
30.8k
    int c = *cstr++;
172
30.8k
    if (c == '\0') {
173
4.26k
      break;
174
4.26k
    }
175
26.5k
    if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
176
0
      continue;
177
0
    }
178
26.5k
    RETERR(isc_hex_decodechar(&ctx, c));
179
26.5k
  }
180
4.26k
  RETERR(isc_hex_decodefinish(&ctx));
181
4.25k
  return ISC_R_SUCCESS;
182
4.26k
}
183
184
static isc_result_t
185
2.39M
str_totext(const char *source, isc_buffer_t *target) {
186
2.39M
  unsigned int l;
187
2.39M
  isc_region_t region;
188
189
2.39M
  isc_buffer_availableregion(target, &region);
190
2.39M
  l = strlen(source);
191
192
2.39M
  if (l > region.length) {
193
1
    return ISC_R_NOSPACE;
194
1
  }
195
196
2.39M
  memmove(region.base, source, l);
197
2.39M
  isc_buffer_add(target, l);
198
2.39M
  return ISC_R_SUCCESS;
199
2.39M
}
200
201
static isc_result_t
202
1.90M
mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
203
1.90M
  isc_region_t tr;
204
205
1.90M
  isc_buffer_availableregion(target, &tr);
206
1.90M
  if (length > tr.length) {
207
10
    return ISC_R_NOSPACE;
208
10
  }
209
1.90M
  memmove(tr.base, base, length);
210
1.90M
  isc_buffer_add(target, length);
211
1.90M
  return ISC_R_SUCCESS;
212
1.90M
}