Coverage Report

Created: 2026-08-13 07:06

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
0
         isc_buffer_t *target) {
55
0
  char buf[3];
56
0
  unsigned int loops = 0;
57
58
0
  if (wordlength < 2) {
59
0
    wordlength = 2;
60
0
  }
61
62
0
  memset(buf, 0, sizeof(buf));
63
0
  while (source->length > 0) {
64
0
    buf[0] = hex[(source->base[0] >> 4) & 0xf];
65
0
    buf[1] = hex[(source->base[0]) & 0xf];
66
0
    RETERR(str_totext(buf, target));
67
0
    isc_region_consume(source, 1);
68
69
0
    loops++;
70
0
    if (source->length != 0 && (int)((loops + 1) * 2) >= wordlength)
71
0
    {
72
0
      loops = 0;
73
0
      RETERR(str_totext(wordbreak, target));
74
0
    }
75
0
  }
76
0
  return ISC_R_SUCCESS;
77
0
}
78
79
void
80
0
isc_hex_decodeinit(isc_hex_decodectx_t *ctx, int length, isc_buffer_t *target) {
81
0
  ctx->digits = 0;
82
0
  ctx->length = length;
83
0
  ctx->target = target;
84
0
}
85
86
isc_result_t
87
0
isc_hex_decodechar(isc_hex_decodectx_t *ctx, int c) {
88
0
  uint8_t hexval;
89
90
0
  hexval = isc_hex_char(c);
91
0
  if (hexval == 0) {
92
0
    return ISC_R_BADHEX;
93
0
  }
94
0
  ctx->val[ctx->digits++] = c - hexval;
95
0
  if (ctx->digits == 2) {
96
0
    unsigned char num;
97
98
0
    num = (ctx->val[0] << 4) + (ctx->val[1]);
99
0
    RETERR(mem_tobuffer(ctx->target, &num, 1));
100
0
    if (ctx->length >= 0) {
101
0
      if (ctx->length == 0) {
102
0
        return ISC_R_BADHEX;
103
0
      } else {
104
0
        ctx->length -= 1;
105
0
      }
106
0
    }
107
0
    ctx->digits = 0;
108
0
  }
109
0
  return ISC_R_SUCCESS;
110
0
}
111
112
isc_result_t
113
0
isc_hex_decodefinish(isc_hex_decodectx_t *ctx) {
114
0
  if (ctx->length > 0) {
115
0
    return ISC_R_UNEXPECTEDEND;
116
0
  }
117
0
  if (ctx->digits != 0) {
118
0
    return ISC_R_BADHEX;
119
0
  }
120
0
  return ISC_R_SUCCESS;
121
0
}
122
123
isc_result_t
124
0
isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
125
0
  unsigned int before, after;
126
0
  isc_hex_decodectx_t ctx;
127
0
  isc_textregion_t *tr;
128
0
  isc_token_t token;
129
0
  bool eol;
130
131
0
  REQUIRE(length >= isc_one_or_more);
132
133
0
  isc_hex_decodeinit(&ctx, length, target);
134
135
0
  before = isc_buffer_usedlength(target);
136
0
  while (ctx.length != 0) {
137
0
    unsigned int i;
138
139
0
    if (length > 0) {
140
0
      eol = false;
141
0
    } else {
142
0
      eol = true;
143
0
    }
144
0
    RETERR(isc_lex_getmastertoken(lexer, &token,
145
0
                isc_tokentype_string, eol));
146
0
    if (token.type != isc_tokentype_string) {
147
0
      break;
148
0
    }
149
0
    tr = &token.value.as_textregion;
150
0
    for (i = 0; i < tr->length; i++) {
151
0
      RETERR(isc_hex_decodechar(&ctx, tr->base[i]));
152
0
    }
153
0
  }
154
0
  after = isc_buffer_usedlength(target);
155
0
  if (ctx.length < 0) {
156
0
    isc_lex_ungettoken(lexer, &token);
157
0
  }
158
0
  RETERR(isc_hex_decodefinish(&ctx));
159
0
  if (length == isc_one_or_more && before == after) {
160
0
    return ISC_R_UNEXPECTEDEND;
161
0
  }
162
0
  return ISC_R_SUCCESS;
163
0
}
164
165
isc_result_t
166
0
isc_hex_decodestring(const char *cstr, isc_buffer_t *target) {
167
0
  isc_hex_decodectx_t ctx;
168
169
0
  isc_hex_decodeinit(&ctx, isc_zero_or_more, target);
170
0
  for (;;) {
171
0
    int c = *cstr++;
172
0
    if (c == '\0') {
173
0
      break;
174
0
    }
175
0
    if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
176
0
      continue;
177
0
    }
178
0
    RETERR(isc_hex_decodechar(&ctx, c));
179
0
  }
180
0
  RETERR(isc_hex_decodefinish(&ctx));
181
0
  return ISC_R_SUCCESS;
182
0
}
183
184
static isc_result_t
185
0
str_totext(const char *source, isc_buffer_t *target) {
186
0
  unsigned int l;
187
0
  isc_region_t region;
188
189
0
  isc_buffer_availableregion(target, &region);
190
0
  l = strlen(source);
191
192
0
  if (l > region.length) {
193
0
    return ISC_R_NOSPACE;
194
0
  }
195
196
0
  memmove(region.base, source, l);
197
0
  isc_buffer_add(target, l);
198
0
  return ISC_R_SUCCESS;
199
0
}
200
201
static isc_result_t
202
0
mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
203
0
  isc_region_t tr;
204
205
0
  isc_buffer_availableregion(target, &tr);
206
0
  if (length > tr.length) {
207
0
    return ISC_R_NOSPACE;
208
0
  }
209
0
  memmove(tr.base, base, length);
210
0
  isc_buffer_add(target, length);
211
0
  return ISC_R_SUCCESS;
212
0
}