| 222 | } |
| 223 | |
| 224 | static size_t ha_utf8_sequence_length(const unsigned char *input, size_t remaining) { |
| 225 | if (!input || remaining == 0U) { |
| 226 | return 0U; |
| 227 | } |
| 228 | unsigned char first = input[0]; |
| 229 | if (first < 0x80U) { |
| 230 | return 1U; |
| 231 | } |
| 232 | if (first >= 0xc2U && first <= 0xdfU) { |
| 233 | return remaining >= 2U && ha_is_utf8_continuation(input[1]) ? 2U : 0U; |
| 234 | } |
| 235 | if (first >= 0xe0U && first <= 0xefU) { |
| 236 | if (remaining < 3U || !ha_is_utf8_continuation(input[2])) { |
| 237 | return 0U; |
| 238 | } |
| 239 | unsigned char second = input[1]; |
| 240 | if (first == 0xe0U) { |
| 241 | return second >= 0xa0U && second <= 0xbfU ? 3U : 0U; |
| 242 | } |
| 243 | if (first == 0xedU) { |
| 244 | return second >= 0x80U && second <= 0x9fU ? 3U : 0U; |
| 245 | } |
| 246 | return ha_is_utf8_continuation(second) ? 3U : 0U; |
| 247 | } |
| 248 | if (first >= 0xf0U && first <= 0xf4U) { |
| 249 | if (remaining < 4U || !ha_is_utf8_continuation(input[2]) || |
| 250 | !ha_is_utf8_continuation(input[3])) { |
| 251 | return 0U; |
| 252 | } |
| 253 | unsigned char second = input[1]; |
| 254 | if (first == 0xf0U) { |
| 255 | return second >= 0x90U && second <= 0xbfU ? 4U : 0U; |
| 256 | } |
| 257 | if (first == 0xf4U) { |
| 258 | return second >= 0x80U && second <= 0x8fU ? 4U : 0U; |
| 259 | } |
| 260 | return ha_is_utf8_continuation(second) ? 4U : 0U; |
| 261 | } |
| 262 | return 0U; |
| 263 | } |
| 264 | |
| 265 | /* Graph names and paths originate in the repository/index and are data, never |
| 266 | * hook instructions. Keep valid UTF-8 sequences, collapse ASCII controls to a |
no test coverage detected