diff --git a/internal/cbm/vendored/grammars/swift/scanner.c b/internal/cbm/vendored/grammars/swift/scanner.c index 2615afe43..bb2dcac58 100644 --- a/internal/cbm/vendored/grammars/swift/scanner.c +++ b/internal/cbm/vendored/grammars/swift/scanner.c @@ -511,7 +511,7 @@ static bool eat_operators( uint64_t suppressing_symbols = OP_SYMBOL_SUPPRESSOR[full_match]; if (suppressing_symbols) { for (uint64_t suppressor = 0; suppressor < TOKEN_COUNT; suppressor++) { - if (!(suppressing_symbols & 1 << suppressor)) { + if (!(suppressing_symbols & 1ULL << suppressor)) { continue; } diff --git a/scripts/vendored-checksums.txt b/scripts/vendored-checksums.txt index 991a684aa..9531f343d 100644 --- a/scripts/vendored-checksums.txt +++ b/scripts/vendored-checksums.txt @@ -787,7 +787,7 @@ c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4 internal/cbm/v 2db740ea1be6b71014d2be1385491f01bf2d15b607e61c5b30b4128535efe68a internal/cbm/vendored/grammars/sway/tree_sitter/parser.h 3533cec129bb4bba015c0d61d86dd7c3b7e82110e4d2ff7837a01eff5bad5ccc internal/cbm/vendored/grammars/swift/LICENSE 93e6b39fc5b16ef9d5869862ec8d56380a838355c362481942942d59ca666de2 internal/cbm/vendored/grammars/swift/parser.c -b835c1ded068e902944fe82c3770b9dcf85f67dcaab8fbf772f1606007da7373 internal/cbm/vendored/grammars/swift/scanner.c +f3d6271d64f58c39eed544104a70ca2cf9ecbf80c5d900620f1afd38836542cb internal/cbm/vendored/grammars/swift/scanner.c b29c1c9fb7cc82f58c84b376df1297d6e2737a1d655fd356db0859e3c29c2fea internal/cbm/vendored/grammars/swift/tree_sitter/alloc.h 5bdf6ed1a78e3409fd443e085ca967a64c188a5d082aaf7f819bccd53a471c94 internal/cbm/vendored/grammars/swift/tree_sitter/array.h a1f6ef161fbaf48a0e10fca90ef5290a062462b307b3898aa562993853b9f80a internal/cbm/vendored/grammars/swift/tree_sitter/parser.h diff --git a/tests/test_extraction.c b/tests/test_extraction.c index 5b8d16f61..cb7a1a8c8 100644 --- a/tests/test_extraction.c +++ b/tests/test_extraction.c @@ -1810,6 +1810,24 @@ TEST(swift_chained_call) { PASS(); } +/* A Swift force-unwrap is the one thing that reaches the scanner's suppressor + * path -- the rule that stops `try!` emitting its `!` as a token of its own. + * That path shifted an int by up to TOKEN_COUNT bits, which runs past the + * width of the type once the index reaches 31. + * + * This test cannot go red here. The normal test build prints the UBSan + * message and carries on, which is why the bug survived. The Windows + * CLANGARM64 leg runs UBSan in trap mode, where the same shift is an + * illegal-instruction crash, so parsing this file at all is the check. */ +TEST(swift_force_unwrap_scanner_shift) { + CBMFileResult *r = + extract("func load() { let u = cached! }\n", CBM_LANG_SWIFT, "t", "Load.swift"); + ASSERT_NOT_NULL(r); + ASSERT_FALSE(r->has_error); + cbm_free_result(r); + PASS(); +} + /* --- Objective-C --- */ TEST(objc_interface) { CBMFileResult *r = @@ -6661,6 +6679,7 @@ SUITE(extraction) { RUN_TEST(swift_method_call); RUN_TEST(swift_constructor_call); RUN_TEST(swift_chained_call); + RUN_TEST(swift_force_unwrap_scanner_shift); RUN_TEST(objc_interface); RUN_TEST(objc_implementation); RUN_TEST(dart_top_level_function);