| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,4 @@ | |||
| 1 | - /* auto-generated on 2026-02-23 21:29:24 -0500. Do not edit! */ | ||
| 1 | + /* auto-generated on 2026-03-23 17:52:13 -0400. Do not edit! */ | ||
| 2 | 2 | /* begin file src/ada.cpp */ | |
| 3 | 3 | #include "ada.h" | |
| 4 | 4 | /* begin file src/checkers.cpp */ | |
@@ -10725,7 +10725,7 @@ constexpr static std::array<uint8_t, 256> is_forbidden_domain_code_point_table = | |||
| 10725 | 10725 | for (uint8_t c = 0; c <= 32; c++) { | |
| 10726 | 10726 | result[c] = true; | |
| 10727 | 10727 | } | |
| 10728 | - for (size_t c = 127; c < 255; c++) { | ||
| 10728 | + for (size_t c = 127; c < 256; c++) { | ||
| 10729 | 10729 | result[c] = true; | |
| 10730 | 10730 | } | |
| 10731 | 10731 | return result; | |
@@ -10767,7 +10767,7 @@ constexpr static std::array<uint8_t, 256> | |||
| 10767 | 10767 | for (uint8_t c = 0; c <= 32; c++) { | |
| 10768 | 10768 | result[c] = 1; | |
| 10769 | 10769 | } | |
| 10770 | - for (size_t c = 127; c < 255; c++) { | ||
| 10770 | + for (size_t c = 127; c < 256; c++) { | ||
| 10771 | 10771 | result[c] = 1; | |
| 10772 | 10772 | } | |
| 10773 | 10773 | return result; | |
@@ -13404,7 +13404,13 @@ result_type parse_url_impl(std::string_view user_input, | |||
| 13404 | 13404 | url.query = base_url->query; | |
| 13405 | 13405 | } else { | |
| 13406 | 13406 | url.update_base_pathname(base_url->get_pathname()); | |
| 13407 | - url.update_base_search(base_url->get_search()); | ||
| 13407 | + if (base_url->has_search()) { | ||
| 13408 | + // get_search() returns "" for an empty query string (URL ends | ||
| 13409 | + // with '?'). update_base_search("") would incorrectly clear the | ||
| 13410 | + // query, so pass "?" to preserve the empty query distinction. | ||
| 13411 | + auto s = base_url->get_search(); | ||
| 13412 | + url.update_base_search(s.empty() ? std::string_view("?") : s); | ||
| 13413 | + } | ||
| 13408 | 13414 | } | |
| 13409 | 13415 | url.update_unencoded_base_hash(*fragment); | |
| 13410 | 13416 | return url; | |
@@ -13628,7 +13634,13 @@ result_type parse_url_impl(std::string_view user_input, | |||
| 13628 | 13634 | // cloning the base path includes cloning the has_opaque_path flag | |
| 13629 | 13635 | url.has_opaque_path = base_url->has_opaque_path; | |
| 13630 | 13636 | url.update_base_pathname(base_url->get_pathname()); | |
| 13631 | - url.update_base_search(base_url->get_search()); | ||
| 13637 | + if (base_url->has_search()) { | ||
| 13638 | + // get_search() returns "" for an empty query string (URL ends | ||
| 13639 | + // with '?'). update_base_search("") would incorrectly clear the | ||
| 13640 | + // query, so pass "?" to preserve the empty query distinction. | ||
| 13641 | + auto s = base_url->get_search(); | ||
| 13642 | + url.update_base_search(s.empty() ? std::string_view("?") : s); | ||
| 13643 | + } | ||
| 13632 | 13644 | } | |
| 13633 | 13645 | ||
| 13634 | 13646 | url.has_opaque_path = base_url->has_opaque_path; | |
@@ -14046,7 +14058,13 @@ result_type parse_url_impl(std::string_view user_input, | |||
| 14046 | 14058 | } else { | |
| 14047 | 14059 | url.update_host_to_base_host(base_url->get_hostname()); | |
| 14048 | 14060 | url.update_base_pathname(base_url->get_pathname()); | |
| 14049 | - url.update_base_search(base_url->get_search()); | ||
| 14061 | + if (base_url->has_search()) { | ||
| 14062 | + // get_search() returns "" for an empty query string (URL ends | ||
| 14063 | + // with '?'). update_base_search("") would incorrectly clear the | ||
| 14064 | + // query, so pass "?" to preserve the empty query distinction. | ||
| 14065 | + auto s = base_url->get_search(); | ||
| 14066 | + url.update_base_search(s.empty() ? std::string_view("?") : s); | ||
| 14067 | + } | ||
| 14050 | 14068 | } | |
| 14051 | 14069 | url.has_opaque_path = base_url->has_opaque_path; | |
| 14052 | 14070 | ||
@@ -16657,8 +16675,15 @@ tl::expected<std::string, errors> canonicalize_pathname( | |||
| 16657 | 16675 | const auto pathname = url->get_pathname(); | |
| 16658 | 16676 | // If leading slash is false, then set result to the code point substring | |
| 16659 | 16677 | // from 2 to the end of the string within result. | |
| 16660 | - return leading_slash ? std::string(pathname) | ||
| 16661 | - : std::string(pathname.substr(2)); | ||
| 16678 | + if (!leading_slash) { | ||
| 16679 | + // pathname should start with "/-" but path traversal (e.g. "../../") | ||
| 16680 | + // can reduce it to just "/" which is shorter than 2 characters. | ||
| 16681 | + if (pathname.size() < 2) { | ||
| 16682 | + return tl::unexpected(errors::type_error); | ||
| 16683 | + } | ||
| 16684 | + return std::string(pathname.substr(2)); | ||
| 16685 | + } | ||
| 16686 | + return std::string(pathname); | ||
| 16662 | 16687 | } | |
| 16663 | 16688 | // If parseResult is failure, then throw a TypeError. | |
| 16664 | 16689 | return tl::unexpected(errors::type_error); | |
@@ -17195,7 +17220,8 @@ std::string generate_pattern_string( | |||
| 17195 | 17220 | // point. | |
| 17196 | 17221 | bool needs_grouping = | |
| 17197 | 17222 | !part.suffix.empty() || | |
| 17198 | - (!part.prefix.empty() && part.prefix[0] != options.get_prefix()[0]); | ||
| 17223 | + (!part.prefix.empty() && !options.get_prefix().empty() && | ||
| 17224 | + part.prefix[0] != options.get_prefix()[0]); | ||
| 17199 | 17225 | ||
| 17200 | 17226 | // If all of the following are true: | |
| 17201 | 17227 | // - needs grouping is false; and | |
@@ -17233,9 +17259,8 @@ std::string generate_pattern_string( | |||
| 17233 | 17259 | // then set needs grouping to true. | |
| 17234 | 17260 | if (!needs_grouping && part.prefix.empty() && previous_part && | |
| 17235 | 17261 | previous_part->type == url_pattern_part_type::FIXED_TEXT && | |
| 17236 | - !options.get_prefix().empty() && | ||
| 17237 | - previous_part->value.at(previous_part->value.size() - 1) == | ||
| 17238 | - options.get_prefix()[0]) { | ||
| 17262 | + !previous_part->value.empty() && !options.get_prefix().empty() && | ||
| 17263 | + previous_part->value.back() == options.get_prefix()[0]) { | ||
| 17239 | 17264 | needs_grouping = true; | |
| 17240 | 17265 | } | |
| 17241 | 17266 | ||
@@ -17358,8 +17383,14 @@ std_regex_provider::regex_search(std::string_view input, | |||
| 17358 | 17383 | const std::regex& pattern) { | |
| 17359 | 17384 | // Use iterator-based regex_search to avoid string allocation | |
| 17360 | 17385 | std::match_results<std::string_view::const_iterator> match_result; | |
| 17361 | - if (!std::regex_search(input.begin(), input.end(), match_result, pattern, | ||
| 17362 | - std::regex_constants::match_any)) { | ||
| 17386 | + try { | ||
| 17387 | + if (!std::regex_search(input.begin(), input.end(), match_result, pattern, | ||
| 17388 | + std::regex_constants::match_any)) { | ||
| 17389 | + return std::nullopt; | ||
| 17390 | + } | ||
| 17391 | + } catch (const std::regex_error& e) { | ||
| 17392 | + (void)e; | ||
| 17393 | + ada_log("std_regex_provider::regex_search failed:", e.what()); | ||
| 17363 | 17394 | return std::nullopt; | |
| 17364 | 17395 | } | |
| 17365 | 17396 | std::vector<std::optional<std::string>> matches; | |
@@ -17378,7 +17409,13 @@ std_regex_provider::regex_search(std::string_view input, | |||
| 17378 | 17409 | ||
| 17379 | 17410 | bool std_regex_provider::regex_match(std::string_view input, | |
| 17380 | 17411 | const std::regex& pattern) { | |
| 17381 | - return std::regex_match(input.begin(), input.end(), pattern); | ||
| 17412 | + try { | ||
| 17413 | + return std::regex_match(input.begin(), input.end(), pattern); | ||
| 17414 | + } catch (const std::regex_error& e) { | ||
| 17415 | + (void)e; | ||
| 17416 | + ada_log("std_regex_provider::regex_match failed:", e.what()); | ||
| 17417 | + return false; | ||
| 17418 | + } | ||
| 17382 | 17419 | } | |
| 17383 | 17420 | ||
| 17384 | 17421 | #endif // ADA_USE_UNSAFE_STD_REGEX_PROVIDER | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,4 @@ | |||
| 1 | - /* auto-generated on 2026-02-23 21:29:24 -0500. Do not edit! */ | ||
| 1 | + /* auto-generated on 2026-03-23 17:52:13 -0400. Do not edit! */ | ||
| 2 | 2 | /* begin file include/ada.h */ | |
| 3 | 3 | /** | |
| 4 | 4 | * @file ada.h | |
@@ -6458,6 +6458,39 @@ constexpr std::string_view is_special_list[] = {"http", " ", "https", "ws", | |||
| 6458 | 6458 | "ftp", "wss", "file", " "}; | |
| 6459 | 6459 | // for use with get_special_port | |
| 6460 | 6460 | constexpr uint16_t special_ports[] = {80, 0, 443, 80, 21, 443, 0, 0}; | |
| 6461 | + | ||
| 6462 | + // @private | ||
| 6463 | + // convert a string_view to a 64-bit integer key for fast comparison | ||
| 6464 | + constexpr uint64_t make_key(std::string_view sv) { | ||
| 6465 | + uint64_t val = 0; | ||
| 6466 | + for (size_t i = 0; i < sv.size(); i++) | ||
| 6467 | + val |= (uint64_t)(uint8_t)sv[i] << (i * 8); | ||
| 6468 | + return val; | ||
| 6469 | + } | ||
| 6470 | + // precomputed keys for the special schemes, indexed by a hash of the input | ||
| 6471 | + // string | ||
| 6472 | + constexpr uint64_t scheme_keys[] = { | ||
| 6473 | + make_key("http"), // 0: HTTP | ||
| 6474 | + 0, // 1: sentinel | ||
| 6475 | + make_key("https"), // 2: HTTPS | ||
| 6476 | + make_key("ws"), // 3: WS | ||
| 6477 | + make_key("ftp"), // 4: FTP | ||
| 6478 | + make_key("wss"), // 5: WSS | ||
| 6479 | + make_key("file"), // 6: FILE | ||
| 6480 | + 0, // 7: sentinel | ||
| 6481 | + }; | ||
| 6482 | + | ||
| 6483 | + // @private | ||
| 6484 | + // branchless load of up to 5 characters into a uint64_t, padding with zeros if | ||
| 6485 | + // n < 5 | ||
| 6486 | + inline uint64_t branchless_load5(const char *p, size_t n) { | ||
| 6487 | + uint64_t input = (uint8_t)p[0]; | ||
| 6488 | + input |= ((uint64_t)(uint8_t)p[n > 1] << 8) & (0 - (uint64_t)(n > 1)); | ||
| 6489 | + input |= ((uint64_t)(uint8_t)p[(n > 2) * 2] << 16) & (0 - (uint64_t)(n > 2)); | ||
| 6490 | + input |= ((uint64_t)(uint8_t)p[(n > 3) * 3] << 24) & (0 - (uint64_t)(n > 3)); | ||
| 6491 | + input |= ((uint64_t)(uint8_t)p[(n > 4) * 4] << 32) & (0 - (uint64_t)(n > 4)); | ||
| 6492 | + return input; | ||
| 6493 | + } | ||
| 6461 | 6494 | } // namespace details | |
| 6462 | 6495 | ||
| 6463 | 6496 | /**** | |
@@ -6498,7 +6531,9 @@ constexpr uint16_t get_special_port(std::string_view scheme) noexcept { | |||
| 6498 | 6531 | } | |
| 6499 | 6532 | int hash_value = (2 * scheme.size() + (unsigned)(scheme[0])) & 7; | |
| 6500 | 6533 | const std::string_view target = details::is_special_list[hash_value]; | |
| 6501 | - if ((target[0] == scheme[0]) && (target.substr(1) == scheme.substr(1))) { | ||
| 6534 | + if (scheme.size() == target.size() && | ||
| 6535 | + details::branchless_load5(scheme.data(), scheme.size()) == | ||
| 6536 | + details::scheme_keys[hash_value]) { | ||
| 6502 | 6537 | return details::special_ports[hash_value]; | |
| 6503 | 6538 | } else { | |
| 6504 | 6539 | return 0; | |
@@ -6513,7 +6548,9 @@ constexpr ada::scheme::type get_scheme_type(std::string_view scheme) noexcept { | |||
| 6513 | 6548 | } | |
| 6514 | 6549 | int hash_value = (2 * scheme.size() + (unsigned)(scheme[0])) & 7; | |
| 6515 | 6550 | const std::string_view target = details::is_special_list[hash_value]; | |
| 6516 | - if ((target[0] == scheme[0]) && (target.substr(1) == scheme.substr(1))) { | ||
| 6551 | + if (scheme.size() == target.size() && | ||
| 6552 | + details::branchless_load5(scheme.data(), scheme.size()) == | ||
| 6553 | + details::scheme_keys[hash_value]) { | ||
| 6517 | 6554 | return ada::scheme::type(hash_value); | |
| 6518 | 6555 | } else { | |
| 6519 | 6556 | return ada::scheme::NOT_SPECIAL; | |
@@ -9368,7 +9405,8 @@ inline void url_search_params::remove(const std::string_view key, | |||
| 9368 | 9405 | } | |
| 9369 | 9406 | ||
| 9370 | 9407 | inline void url_search_params::sort() { | |
| 9371 | - // We rely on the fact that the content is valid UTF-8. | ||
| 9408 | + // Keys are expected to be valid UTF-8, but percent_decode can produce | ||
| 9409 | + // arbitrary byte sequences. Handle truncated/invalid sequences gracefully. | ||
| 9372 | 9410 | std::ranges::stable_sort(params, [](const key_value_pair &lhs, | |
| 9373 | 9411 | const key_value_pair &rhs) { | |
| 9374 | 9412 | size_t i = 0, j = 0; | |
@@ -9382,18 +9420,15 @@ inline void url_search_params::sort() { | |||
| 9382 | 9420 | low_surrogate1 = 0; | |
| 9383 | 9421 | } else { | |
| 9384 | 9422 | uint8_t c1 = uint8_t(lhs.first[i]); | |
| 9385 | - if (c1 <= 0x7F) { | ||
| 9386 | - codePoint1 = c1; | ||
| 9387 | - i++; | ||
| 9388 | - } else if (c1 <= 0xDF) { | ||
| 9423 | + if (c1 > 0x7F && c1 <= 0xDF && i + 1 < lhs.first.size()) { | ||
| 9389 | 9424 | codePoint1 = ((c1 & 0x1F) << 6) | (uint8_t(lhs.first[i + 1]) & 0x3F); | |
| 9390 | 9425 | i += 2; | |
| 9391 | - } else if (c1 <= 0xEF) { | ||
| 9426 | + } else if (c1 > 0xDF && c1 <= 0xEF && i + 2 < lhs.first.size()) { | ||
| 9392 | 9427 | codePoint1 = ((c1 & 0x0F) << 12) | | |
| 9393 | 9428 | ((uint8_t(lhs.first[i + 1]) & 0x3F) << 6) | | |
| 9394 | 9429 | (uint8_t(lhs.first[i + 2]) & 0x3F); | |
| 9395 | 9430 | i += 3; | |
| 9396 | - } else { | ||
| 9431 | + } else if (c1 > 0xEF && c1 <= 0xF7 && i + 3 < lhs.first.size()) { | ||
| 9397 | 9432 | codePoint1 = ((c1 & 0x07) << 18) | | |
| 9398 | 9433 | ((uint8_t(lhs.first[i + 1]) & 0x3F) << 12) | | |
| 9399 | 9434 | ((uint8_t(lhs.first[i + 2]) & 0x3F) << 6) | | |
@@ -9404,6 +9439,10 @@ inline void url_search_params::sort() { | |||
| 9404 | 9439 | uint16_t high_surrogate = uint16_t(0xD800 + (codePoint1 >> 10)); | |
| 9405 | 9440 | low_surrogate1 = uint16_t(0xDC00 + (codePoint1 & 0x3FF)); | |
| 9406 | 9441 | codePoint1 = high_surrogate; | |
| 9442 | + } else { | ||
| 9443 | + // ASCII (c1 <= 0x7F) or truncated/invalid UTF-8: treat as raw byte | ||
| 9444 | + codePoint1 = c1; | ||
| 9445 | + i++; | ||
| 9407 | 9446 | } | |
| 9408 | 9447 | } | |
| 9409 | 9448 | ||
@@ -9412,18 +9451,15 @@ inline void url_search_params::sort() { | |||
| 9412 | 9451 | low_surrogate2 = 0; | |
| 9413 | 9452 | } else { | |
| 9414 | 9453 | uint8_t c2 = uint8_t(rhs.first[j]); | |
| 9415 | - if (c2 <= 0x7F) { | ||
| 9416 | - codePoint2 = c2; | ||
| 9417 | - j++; | ||
| 9418 | - } else if (c2 <= 0xDF) { | ||
| 9454 | + if (c2 > 0x7F && c2 <= 0xDF && j + 1 < rhs.first.size()) { | ||
| 9419 | 9455 | codePoint2 = ((c2 & 0x1F) << 6) | (uint8_t(rhs.first[j + 1]) & 0x3F); | |
| 9420 | 9456 | j += 2; | |
| 9421 | - } else if (c2 <= 0xEF) { | ||
| 9457 | + } else if (c2 > 0xDF && c2 <= 0xEF && j + 2 < rhs.first.size()) { | ||
| 9422 | 9458 | codePoint2 = ((c2 & 0x0F) << 12) | | |
| 9423 | 9459 | ((uint8_t(rhs.first[j + 1]) & 0x3F) << 6) | | |
| 9424 | 9460 | (uint8_t(rhs.first[j + 2]) & 0x3F); | |
| 9425 | 9461 | j += 3; | |
| 9426 | - } else { | ||
| 9462 | + } else if (c2 > 0xEF && c2 <= 0xF7 && j + 3 < rhs.first.size()) { | ||
| 9427 | 9463 | codePoint2 = ((c2 & 0x07) << 18) | | |
| 9428 | 9464 | ((uint8_t(rhs.first[j + 1]) & 0x3F) << 12) | | |
| 9429 | 9465 | ((uint8_t(rhs.first[j + 2]) & 0x3F) << 6) | | |
@@ -9433,6 +9469,10 @@ inline void url_search_params::sort() { | |||
| 9433 | 9469 | uint16_t high_surrogate = uint16_t(0xD800 + (codePoint2 >> 10)); | |
| 9434 | 9470 | low_surrogate2 = uint16_t(0xDC00 + (codePoint2 & 0x3FF)); | |
| 9435 | 9471 | codePoint2 = high_surrogate; | |
| 9472 | + } else { | ||
| 9473 | + // ASCII (c2 <= 0x7F) or truncated/invalid UTF-8: treat as raw byte | ||
| 9474 | + codePoint2 = c2; | ||
| 9475 | + j++; | ||
| 9436 | 9476 | } | |
| 9437 | 9477 | } | |
| 9438 | 9478 | ||
@@ -11228,14 +11268,14 @@ constructor_string_parser<regex_provider>::parse(std::string_view input) { | |||
| 11228 | 11268 | #ifndef ADA_ADA_VERSION_H | |
| 11229 | 11269 | #define ADA_ADA_VERSION_H | |
| 11230 | 11270 | ||
| 11231 | - #define ADA_VERSION "3.4.3" | ||
| 11271 | + #define ADA_VERSION "3.4.4" | ||
| 11232 | 11272 | ||
| 11233 | 11273 | namespace ada { | |
| 11234 | 11274 | ||
| 11235 | 11275 | enum { | |
| 11236 | 11276 | ADA_VERSION_MAJOR = 3, | |
| 11237 | 11277 | ADA_VERSION_MINOR = 4, | |
| 11238 | - ADA_VERSION_REVISION = 3, | ||
| 11278 | + ADA_VERSION_REVISION = 4, | ||
| 11239 | 11279 | }; | |
| 11240 | 11280 | ||
| 11241 | 11281 | } // namespace ada | |
| Back | FazBrowse Home | New Git URL |
0 commit comments