| 296 | #define SMALL_PUNYCODE_LEN 128 |
| 297 | |
| 298 | static NODISCARD punycode_status punycode_decode(const char *start, size_t ascii_len, const char *punycode_start, size_t punycode_len, uint32_t (*out_)[SMALL_PUNYCODE_LEN], size_t *out_len) { |
| 299 | uint32_t *out = *out_; |
| 300 | |
| 301 | if (punycode_len == 0) { |
| 302 | return PunycodeError; |
| 303 | } |
| 304 | |
| 305 | if (ascii_len > SMALL_PUNYCODE_LEN) { |
| 306 | return PunycodeError; |
| 307 | } |
| 308 | for (size_t i = 0; i < ascii_len; i++) { |
| 309 | out[i] = start[i]; |
| 310 | } |
| 311 | size_t len = ascii_len; |
| 312 | |
| 313 | size_t base = 36, t_min = 1, t_max = 26, skew = 38, damp = 700, bias = 72, i = 0, n = 0x80; |
| 314 | for (;;) { |
| 315 | size_t delta = 0, w = 1, k = 0; |
| 316 | for (;;) { |
| 317 | k += base; |
| 318 | size_t biased = k < bias ? 0 : k - bias; |
| 319 | size_t t = MIN(MAX(biased, t_min), t_max); |
| 320 | size_t d; |
| 321 | if (punycode_len == 0) { |
| 322 | return PunycodeError; |
| 323 | } |
| 324 | char nx = *punycode_start++; |
| 325 | punycode_len--; |
| 326 | if ('a' <= nx && nx <= 'z') { |
| 327 | d = nx - 'a'; |
| 328 | } else if ('0' <= nx && nx <= '9') { |
| 329 | d = 26 + (nx - '0'); |
| 330 | } else { |
| 331 | return PunycodeError; |
| 332 | } |
| 333 | if (w == 0 || d > SIZE_MAX / w || d*w > SIZE_MAX - delta) { |
| 334 | return PunycodeError; |
| 335 | } |
| 336 | delta += d * w; |
| 337 | if (d < t) { |
| 338 | break; |
| 339 | } |
| 340 | if (base < t || w == 0 || (base - t) > SIZE_MAX / w) { |
| 341 | return PunycodeError; |
| 342 | } |
| 343 | w *= (base - t); |
| 344 | } |
| 345 | |
| 346 | len += 1; |
| 347 | if (i > SIZE_MAX - delta) { |
| 348 | return PunycodeError; |
| 349 | } |
| 350 | i += delta; |
| 351 | if (n > SIZE_MAX - i / len) { |
| 352 | return PunycodeError; |
| 353 | } |
| 354 | n += i / len; |
| 355 | i %= len; |
nothing calls this directly
no test coverage detected