Coverage Report

Created: 2026-08-08 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/bytestring/unicode.cc
Line
Count
Source
1
// Copyright 2018 The BoringSSL Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include <openssl/bytestring.h>
16
17
#include "internal.h"
18
19
20
61.5M
static int is_valid_code_point(uint32_t v) {
21
  // References in the following are to Unicode 15.0.0.
22
61.5M
  if (// The Unicode space runs from zero to 0x10ffff (3.4 D9).
23
61.5M
      v > 0x10ffff ||
24
      // Values 0x...fffe, 0x...ffff, and 0xfdd0-0xfdef are permanently reserved
25
      // as noncharacters (3.4 D14). See also 23.7. As our APIs are intended for
26
      // "open interchange", such as ASN.1, we reject them.
27
61.5M
      (v & 0xfffe) == 0xfffe ||
28
61.5M
      (v >= 0xfdd0 && v <= 0xfdef) ||
29
      // Surrogate code points are invalid (3.2 C1).
30
61.5M
      (v >= 0xd800 && v <= 0xdfff)) {
31
2.23k
    return 0;
32
2.23k
  }
33
61.5M
  return 1;
34
61.5M
}
35
36
// BOTTOM_BITS returns a byte with the bottom `n` bits set.
37
98.1M
#define BOTTOM_BITS(n) (uint8_t)((1u << (n)) - 1)
38
39
// TOP_BITS returns a byte with the top `n` bits set.
40
59.0M
#define TOP_BITS(n) ((uint8_t)~BOTTOM_BITS(8 - (n)))
41
42
8.00M
int CBS_get_utf8(CBS *cbs, uint32_t *out) {
43
8.00M
  uint8_t c;
44
8.00M
  if (!CBS_get_u8(cbs, &c)) {
45
0
    return 0;
46
0
  }
47
8.00M
  if (c <= 0x7f) {
48
7.97M
    *out = c;
49
7.97M
    return 1;
50
7.97M
  }
51
34.0k
  uint32_t v, lower_bound;
52
34.0k
  size_t len;
53
34.0k
  if ((c & TOP_BITS(3)) == TOP_BITS(2)) {
54
24.7k
    v = c & BOTTOM_BITS(5);
55
24.7k
    len = 1;
56
24.7k
    lower_bound = 0x80;
57
24.7k
  } else if ((c & TOP_BITS(4)) == TOP_BITS(3)) {
58
5.92k
    v = c & BOTTOM_BITS(4);
59
5.92k
    len = 2;
60
5.92k
    lower_bound = 0x800;
61
5.92k
  } else if ((c & TOP_BITS(5)) == TOP_BITS(4)) {
62
3.18k
    v = c & BOTTOM_BITS(3);
63
3.18k
    len = 3;
64
3.18k
    lower_bound = 0x10000;
65
3.18k
  } else {
66
190
    return 0;
67
190
  }
68
79.7k
  for (size_t i = 0; i < len; i++) {
69
46.0k
    if (!CBS_get_u8(cbs, &c) ||
70
45.9k
        (c & TOP_BITS(2)) != TOP_BITS(1)) {
71
164
      return 0;
72
164
    }
73
45.8k
    v <<= 6;
74
45.8k
    v |= c & BOTTOM_BITS(6);
75
45.8k
  }
76
33.7k
  if (!is_valid_code_point(v) ||
77
33.5k
      v < lower_bound) {
78
180
    return 0;
79
180
  }
80
33.5k
  *out = v;
81
33.5k
  return 1;
82
33.7k
}
83
84
4.88M
int CBS_get_latin1(CBS *cbs, uint32_t *out) {
85
4.88M
  uint8_t c;
86
4.88M
  if (!CBS_get_u8(cbs, &c)) {
87
0
    return 0;
88
0
  }
89
4.88M
  *out = c;
90
4.88M
  return 1;
91
4.88M
}
92
93
34.1M
int CBS_get_ucs2_be(CBS *cbs, uint32_t *out) {
94
  // Note UCS-2 (used by BMPString) does not support surrogates.
95
34.1M
  uint16_t c;
96
34.1M
  if (!CBS_get_u16(cbs, &c) ||
97
34.1M
      !is_valid_code_point(c)) {
98
877
    return 0;
99
877
  }
100
34.1M
  *out = c;
101
34.1M
  return 1;
102
34.1M
}
103
104
28.1k
int CBS_get_utf32_be(CBS *cbs, uint32_t *out) {
105
28.1k
  return CBS_get_u32(cbs, out) && is_valid_code_point(*out);
106
28.1k
}
107
108
0
size_t CBB_get_utf8_len(uint32_t u) {
109
0
  if (u <= 0x7f) {
110
0
    return 1;
111
0
  }
112
0
  if (u <= 0x7ff) {
113
0
    return 2;
114
0
  }
115
0
  if (u <= 0xffff) {
116
0
    return 3;
117
0
  }
118
0
  return 4;
119
0
}
120
121
27.3M
int CBB_add_utf8(CBB *cbb, uint32_t u) {
122
27.3M
  if (!is_valid_code_point(u)) {
123
0
    return 0;
124
0
  }
125
27.3M
  if (u <= 0x7f) {
126
7.64M
    return CBB_add_u8(cbb, (uint8_t)u);
127
7.64M
  }
128
19.7M
  if (u <= 0x7ff) {
129
309k
    return CBB_add_u8(cbb, TOP_BITS(2) | (u >> 6)) &&
130
309k
           CBB_add_u8(cbb, TOP_BITS(1) | (u & BOTTOM_BITS(6)));
131
309k
  }
132
19.3M
  if (u <= 0xffff) {
133
19.3M
    return CBB_add_u8(cbb, TOP_BITS(3) | (u >> 12)) &&
134
19.3M
           CBB_add_u8(cbb, TOP_BITS(1) | ((u >> 6) & BOTTOM_BITS(6))) &&
135
19.3M
           CBB_add_u8(cbb, TOP_BITS(1) | (u & BOTTOM_BITS(6)));
136
19.3M
  }
137
13.1k
  if (u <= 0x10ffff) {
138
13.1k
    return CBB_add_u8(cbb, TOP_BITS(4) | (u >> 18)) &&
139
13.1k
           CBB_add_u8(cbb, TOP_BITS(1) | ((u >> 12) & BOTTOM_BITS(6))) &&
140
13.1k
           CBB_add_u8(cbb, TOP_BITS(1) | ((u >> 6) & BOTTOM_BITS(6))) &&
141
13.1k
           CBB_add_u8(cbb, TOP_BITS(1) | (u & BOTTOM_BITS(6)));
142
13.1k
  }
143
0
  return 0;
144
13.1k
}
145
146
0
int CBB_add_latin1(CBB *cbb, uint32_t u) {
147
0
  return u <= 0xff && CBB_add_u8(cbb, (uint8_t)u);
148
0
}
149
150
1.75k
int CBB_add_ucs2_be(CBB *cbb, uint32_t u) {
151
1.75k
  return u <= 0xffff && is_valid_code_point(u) && CBB_add_u16(cbb, (uint16_t)u);
152
1.75k
}
153
154
0
int CBB_add_utf32_be(CBB *cbb, uint32_t u) {
155
0
  return is_valid_code_point(u) && CBB_add_u32(cbb, u);
156
0
}