** check whether pattern may go from 'p' to 'e' without consuming any ** input. Raises an error if it detects a left recursion. 'op' points ** the beginning of the pattern. If pattern belongs to a grammar, ** 'rule' is the stack index where is its corresponding key (only for ** error messages) and 'posttable' is the stack index with a table ** mapping rule keys to the position of their code in th
| 654 | ** mapping rule keys to the position of their code in the pattern. |
| 655 | */ |
| 656 | static int verify (lua_State *L, Instruction *op, const Instruction *p, |
| 657 | Instruction *e, int postable, int rule) { |
| 658 | static const char dummy[] = ""; |
| 659 | Stack back[MAXBACKVER]; |
| 660 | int backtop = 0; /* point to first empty slot in back */ |
| 661 | while (p != e) { |
| 662 | switch ((Opcode)p->i.code) { |
| 663 | case IRet: { |
| 664 | p = back[--backtop].p; |
| 665 | continue; |
| 666 | } |
| 667 | case IChoice: { |
| 668 | if (backtop >= MAXBACKVER) |
| 669 | return luaL_error(L, "too many pending calls/choices"); |
| 670 | back[backtop].p = dest(0, p); |
| 671 | back[backtop++].s = dummy; |
| 672 | p++; |
| 673 | continue; |
| 674 | } |
| 675 | case ICall: { |
| 676 | assert((p + 1)->i.code != IRet); /* no tail call */ |
| 677 | if (backtop >= MAXBACKVER) |
| 678 | return luaL_error(L, "too many pending calls/choices"); |
| 679 | back[backtop].s = NULL; |
| 680 | back[backtop++].p = p + 1; |
| 681 | goto dojmp; |
| 682 | } |
| 683 | case IOpenCall: { |
| 684 | int i; |
| 685 | if (postable == 0) /* grammar still not fixed? */ |
| 686 | goto fail; /* to be verified later */ |
| 687 | for (i = 0; i < backtop; i++) { |
| 688 | if (back[i].s == NULL && back[i].p == p + 1) |
| 689 | return luaL_error(L, "%s is left recursive", val2str(L, rule)); |
| 690 | } |
| 691 | if (backtop >= MAXBACKVER) |
| 692 | return luaL_error(L, "too many pending calls/choices"); |
| 693 | back[backtop].s = NULL; |
| 694 | back[backtop++].p = p + 1; |
| 695 | p = op + getposition(L, postable, p->i.offset); |
| 696 | continue; |
| 697 | } |
| 698 | case IBackCommit: |
| 699 | case ICommit: { |
| 700 | assert(backtop > 0 && p->i.offset > 0); |
| 701 | backtop--; |
| 702 | goto dojmp; |
| 703 | } |
| 704 | case IPartialCommit: { |
| 705 | assert(backtop > 0); |
| 706 | if (p->i.offset > 0) goto dojmp; /* forward jump */ |
| 707 | else { /* loop will be detected when checking corresponding rule */ |
| 708 | assert(postable != 0); |
| 709 | backtop--; |
| 710 | p++; /* just go on now */ |
| 711 | continue; |
| 712 | } |
| 713 | } |
no test coverage detected