Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sql: avoid stack overflow on deeply nested ASTs #9117

Merged
merged 2 commits into from Nov 17, 2021

Conversation

benesch
Copy link
Member

@benesch benesch commented Nov 16, 2021

In the SQL planner, use the same technique as the SQL parser for
automatically growing the stack when presented with a deeply nested AST.

The stack-checking code is generalized and moved to a new ore::stack
module.

Fix #9103.

Motivation

This PR fixes a recognized bug.

Checklist

  • This PR has adequate test coverage / QA involvement has been duly considered.
  • This PR adds a release note for any
    user-facing behavior changes.

@benesch
Copy link
Member Author

benesch commented Nov 16, 2021

I still need to check that this actually fixes the issue, so just a draft for now.

@maddyblue
Copy link
Contributor

Testing locally the query in 9103 still produces a crash. Not convinced it's the same stack crash (we're investigating what might be another).

@benesch
Copy link
Member Author

benesch commented Nov 16, 2021

@mjibson did you test in release mode? In debug mode, .clone() doesn't get TCO'd, and you'll run out of stack way earlier. With this PR (finally got a release build) I'm seeing the desired results:

materialize=> SELECT 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 38 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 + 51 + 52 + 53 + 54 + 55 + 56 + 57 + 58 + 59 + 60 + 61 + 62 + 63 + 64 + 65 + 66 + 67 + 68 + 69 + 70 + 71 + 72 + 73 + 74 + 75 + 76 + 77 + 78 + 79 + 80 + 81 + 82 + 83 + 84 + 85 + 86 + 87 + 88 + 89 + 90 + 91 + 92 + 93 + 94 + 95 + 96 + 97 + 98 + 99 + 100 + 101 + 102 + 103 + 104 + 105 + 106 + 107 + 108 + 109 + 110 + 111 + 112 + 113 + 114 + 115 + 116 + 117 + 118 + 119 + 120 + 121 + 122 + 123 + 124 + 125 + 126 + 127 + 128 + 129 + 130 + 131 + 132 + 133 + 134 + 135 + 136 + 137 + 138 + 139 + 140 + 141 + 142 + 143 + 144 + 145 + 146 + 147 + 148 + 149 + 150 + 151 + 152 + 153 + 154 + 155 + 156 + 157 + 158 + 159 + 160 + 161 + 162 + 163 + 164 + 165 + 166 + 167 + 168 + 169 + 170 + 171 + 172 + 173 + 174 + 175 + 176 + 177 + 178 + 179 + 180 + 181 + 182 + 183 + 184 + 185 + 186 + 187 + 188 + 189 + 190 + 191 + 192 + 193 + 194 + 195 + 196 + 197 + 198 + 199 + 200 + 201 + 202 + 203 + 204 + 205 + 206 + 207 + 208 + 209 + 210 + 211 + 212 + 213 + 214 + 215 + 216 + 217 + 218 + 219 + 220 + 221 + 222 + 223 + 224 + 225 + 226 + 227 + 228 + 229 + 230 + 231 + 232 + 233 + 234 + 235 + 236 + 237 + 238 + 239 + 240 + 241 + 242 + 243 + 244 + 245 + 246 + 247 + 248 + 249 + 250 + 251 + 252 + 253 + 254 + 255 + 256 + 257 + 258 + 259 + 260 + 261 + 262 + 263 + 264 + 265 + 266 + 267 + 268 + 269 + 270 + 271 + 272 + 273 + 274 + 275 + 276 + 277 + 278 + 279 + 280 + 281 + 282 + 283 + 284 + 285 + 286 + 287 + 288 + 289 + 290 + 291 + 292 + 293 + 294 + 295 + 296 + 297 + 298 + 299 + 300 + 301 + 302 + 303 + 304 + 305 + 306 + 307 + 308 + 309 + 310 + 311 + 312 + 313 + 314 + 315 + 316 + 317 + 318 + 319 + 320 + 321 + 322 + 323 + 324 + 325 + 326 + 327 + 328 + 329 + 330 + 331 + 332 + 333 + 334 + 335 + 336 + 337 + 338 + 339 + 340 + 341 + 342 + 343 + 344 + 345 + 346 + 347 + 348 + 349 + 350 + 351 + 352 + 353 + 354 + 355 + 356 + 357 + 358 + 359 + 360 + 361 + 362 + 363 + 364 + 365 + 366 + 367 + 368 + 369 + 370 + 371 + 372 + 373 + 374 + 375 + 376 + 377 + 378 + 379 + 380 + 381 + 382 + 383 + 384 + 385 + 386 + 387 + 388 + 389 + 390 + 391 + 392 + 393 + 394 + 395 + 396 + 397 + 398 + 399 + 400 + 401 + 402 + 403 + 404 + 405 + 406 + 407 + 408 + 409 + 410 + 411 + 412 + 413 + 414 + 415 + 416 + 417 + 418 + 419 + 420 + 421 + 422 + 423 + 424 + 425 + 426 + 427 + 428 + 429 + 430 + 431 + 432 + 433 + 434 + 435 + 436 + 437 + 438 + 439 + 440 + 441 + 442 + 443 + 444 + 445 + 446 + 447 + 448 + 449 + 450 + 451 + 452 + 453 + 454 + 455 + 456 + 457 + 458 + 459 + 460 + 461 + 462 + 463 + 464 + 465 + 466 + 467 + 468 + 469 + 470 + 471 + 472 + 473 + 474 + 475 + 476 + 477 + 478 + 479 + 480 + 481 + 482 + 483 + 484 + 485 + 486 + 487 + 488 + 489 + 490 + 491 + 492 + 493 + 494 + 495 + 496 + 497 + 498 + 499 + 500 + 501 + 502 + 503 + 504 + 505 + 506 + 507 + 508 + 509 + 510 + 511 + 512 + 513 + 514 + 515 + 516 + 517 + 518 + 519 + 520 + 521 + 522 + 523 + 524 + 525 + 526 + 527 + 528 + 529 + 530 + 531 + 532 + 533 + 534 + 535 + 536 + 537 + 538 + 539 + 540 + 541 + 542 + 543 + 544 + 545 + 546 + 547 + 548 + 549 + 550 + 551 + 552 + 553 + 554 + 555 + 556 + 557 + 558 + 559 + 560 + 561 + 562 + 563 + 564 + 565 + 566 + 567 + 568 + 569 + 570 + 571 + 572 + 573 + 574 + 575 + 576 + 577 + 578 + 579 + 580 + 581 + 582 + 583 + 584 + 585 + 586 + 587 + 588 + 589 + 590 + 591 + 592 + 593 + 594 + 595 + 596 + 597 + 598 + 599 + 600 + 601 + 602 + 603 + 604 + 605 + 606 + 607 + 608 + 609 + 610 + 611 + 612 + 613 + 614 + 615 + 616 + 617 + 618 + 619 + 620 + 621 + 622 + 623 + 624 + 625 + 626 + 627 + 628 + 629 + 630 + 631 + 632 + 633 + 634 + 635 + 636 + 637 + 638 + 639 + 640 + 641 + 642 + 643 + 644 + 645 + 646 + 647 + 648 + 649 + 650 + 651 + 652 + 653 + 654 + 655 + 656 + 657 + 658 + 659 + 660 + 661 + 662 + 663 + 664 + 665 + 666 + 667 + 668 + 669 + 670 + 671 + 672 + 673 + 674 + 675 + 676 + 677 + 678 + 679 + 680 + 681 + 682 + 683 + 684 + 685 + 686 + 687 + 688 + 689 + 690 + 691 + 692 + 693 + 694 + 695 + 696 + 697 + 698 + 699 + 700 + 701 + 702 + 703 + 704 + 705 + 706 + 707 + 708 + 709 + 710 + 711 + 712 + 713 + 714 + 715 + 716 + 717 + 718 + 719 + 720 + 721 + 722 + 723 + 724 + 725 + 726 + 727 + 728 + 729 + 730 + 731 + 732 + 733 + 734 + 735 + 736 + 737 + 738 + 739 + 740 + 741 + 742 + 743 + 744 + 745 + 746 + 747 + 748 + 749 + 750 + 751 + 752 + 753 + 754 + 755 + 756 + 757 + 758 + 759 + 760 + 761 + 762 + 763 + 764 + 765 + 766 + 767 + 768 + 769 + 770 + 771 + 772 + 773 + 774 + 775 + 776 + 777 + 778 + 779 + 780 + 781 + 782 + 783 + 784 + 785 + 786 + 787 + 788 + 789 + 790 + 791 + 792 + 793 + 794 + 795 + 796 + 797 + 798 + 799 + 800 + 801 + 802 + 803 + 804 + 805 + 806 + 807 + 808 + 809 + 810 + 811 + 812 + 813 + 814 + 815 + 816 + 817 + 818 + 819 + 820 + 821 + 822 + 823 + 824 + 825 + 826 + 827 + 828 + 829 + 830 + 831 + 832 + 833 + 834 + 835 + 836 + 837 + 838 + 839 + 840 + 841 + 842 + 843 + 844 + 845 + 846 + 847 + 848 + 849 + 850 + 851 + 852 + 853 + 854 + 855 + 856 + 857 + 858 + 859 + 860 + 861 + 862 + 863 + 864 + 865 + 866 + 867 + 868 + 869 + 870 + 871 + 872 + 873 + 874 + 875 + 876 + 877 + 878 + 879 + 880 + 881 + 882 + 883 + 884 + 885 + 886 + 887 + 888 + 889 + 890 + 891 + 892 + 893 + 894 + 895 + 896 + 897 + 898 + 899 + 900 + 901 + 902 + 903 + 904 + 905 + 906 + 907 + 908 + 909 + 910 + 911 + 912 + 913 + 914 + 915 + 916 + 917 + 918 + 919 + 920 + 921 + 922 + 923 + 924 + 925 + 926 + 927 + 928 + 929 + 930 + 931 + 932 + 933 + 934 + 935 + 936 + 937 + 938 + 939 + 940 + 941 + 942 + 943 + 944 + 945 + 946 + 947 + 948 + 949 + 950 + 951 + 952 + 953 + 954 + 955 + 956 + 957 + 958 + 959 + 960 + 961 + 962 + 963 + 964 + 965 + 966 + 967 + 968 + 969 + 970 + 971 + 972 + 973 + 974 + 975 + 976 + 977 + 978 + 979 + 980 + 981 + 982 + 983 + 984 + 985 + 986 + 987 + 988 + 989 + 990 + 991 + 992 + 993 + 994 + 995 + 996 + 997 + 998 + 999 + 1000;
ERROR:  recursion limit exceeded

@benesch
Copy link
Member Author

benesch commented Nov 16, 2021

@philip-stoev perhaps you could take a stab at tweaking the tests or the recursion limit constant here? I'm not going to have a chance to look at this for a bit.

@maddyblue
Copy link
Contributor

Nope, was in debug.

In the SQL planner, use the same technique as the SQL parser for
automatically growing the stack when presented with a deeply nested AST.

The stack-checking code is generalized and moved to a new `ore::stack`
module.

Fix MaterializeInc#9103.
@benesch benesch marked this pull request as ready for review November 17, 2021 00:48
@benesch
Copy link
Member Author

benesch commented Nov 17, 2021

Ok, great, this should be ready to go now. @philip-stoev the limits test now passes, and if you like you could introduce an even larger number of additions and verify that you get a smooth error message rather than a crash. I'm also pretty confident that the infrastructure in ore::stack will be useful in the other places we recurse arbitrarily deep, like in the optimizer.

Copy link
Contributor

@umanwizard umanwizard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only unfortunate thing about this is that using checked recursion probably impedes TCO even in cases where the compiler could have made it work.

Probably not an issue in any of the cases we’re using it in, though.

@philip-stoev
Copy link
Contributor

philip-stoev commented Nov 17, 2021

With 1000 items I get an actual result out of this query. With 1100 items I get a stack overflow elsewhere. I am unable to get the "recursion limit exceeded" error.

ql::plan::transform_ast::Desugarer::visit_expr_mut_internal () at src/sql/src/plan/transform_ast.rs:549
549	        visit_mut::visit_expr_mut(self, expr);
(gdb) bt
#0  sql::plan::transform_ast::Desugarer::visit_expr_mut_internal () at src/sql/src/plan/transform_ast.rs:549
#1  0x00005555583c4529 in <sql::plan::transform_ast::Desugarer as sql_parser::ast::visit_mut::VisitMut<sql_parser::ast::defs::query::Raw>>::visit_expr_mut () at src/sql/src/plan/transform_ast.rs:305
#2  sql_parser::ast::visit_mut::visit_expr_mut () at /home/pstoev/benesch-stack-guards/target/release/build/sql-parser-69302e5f466aab74/out/visit_mut.rs:1344
#3  0x00005555582a029e in sql::plan::transform_ast::Desugarer::visit_expr_mut_internal () at src/sql/src/plan/transform_ast.rs:549
#4  0x00005555583c4529 in <sql::plan::transform_ast::Desugarer as sql_parser::ast::visit_mut::VisitMut<sql_parser::ast::defs::query::Raw>>::visit_expr_mut () at src/sql/src/plan/transform_ast.rs:305
#5  sql_parser::ast::visit_mut::visit_expr_mut () at /home/pstoev/benesch-stack-guards/target/release/build/sql-parser-69302e5f466aab74/out/visit_mut.rs:1344
#6  0x00005555582a029e in sql::plan::transform_ast::Desugarer::visit_expr_mut_internal () at src/sql/src/plan/transform_ast.rs:549
#7  0x00005555583c4529 in <sql::plan::transform_ast::Desugarer as sql_parser::ast::visit_mut::VisitMut<sql_parser::ast::defs::query::Raw>>::visit_expr_mut () at src/sql/src/plan/transform_ast.rs:305
#8  sql_parser::ast::visit_mut::visit_expr_mut () at /home/pstoev/benesch-stack-guards/target/release/build/sql-parser-69302e5f466aab74/out/visit_mut.rs:1344

I am going to open a separate ticket for this (as I have for several other stack overflows elsewhere).

Copy link
Contributor

@philip-stoev philip-stoev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the particular crash the issue was about is now fixed and the test passes, I think this PR is good to go. I am going to open a follow-up ticket about the sql::plan::transform_ast::Desugarer::visit_expr_mut_internal crash.

@uce
Copy link
Contributor

uce commented Nov 17, 2021

For the optimizer, I had filed #9000 to use stacker. I added a comment in that ticket to use the newly added stack management utilities.

Copy link
Contributor

@aalexandrov aalexandrov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, I will then it to fix similar issues in the optimizer (see #9000).

///
/// If the recursion limit for the recursion guard returned by
/// [`CheckedRecursion::recursion_guard`] has been reached, returns a
/// `RecursionLimitError`. Otherwise, it will call `f`, possibly growing the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: strictly speaking, returns a RecursionLimitError converted to E.

@benesch benesch merged commit 63c0639 into MaterializeInc:main Nov 17, 2021
@benesch benesch deleted the stack-guards branch November 17, 2021 10:03
@benesch
Copy link
Member Author

benesch commented Nov 17, 2021

Thanks for the reviews, everyone! Let the games of whack a mole begin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

regression: stack exhaustion in sql::plan::query::plan_* with an expression in the SELECT list
6 participants