diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-11-16 12:00:28 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-11-16 12:00:28 -0300 |
commit | b117bdb3448778d9e7f9a0302791e8ac3bb97ddd (patch) | |
tree | cf83da22ab3ea7fae6bb2602c790f1a0ca9533c9 /ldo.c | |
parent | f12ce4029dfbce7b89ec136e6b7ba5f6bca039da (diff) | |
download | lua-b117bdb3448778d9e7f9a0302791e8ac3bb97ddd.tar.gz lua-b117bdb3448778d9e7f9a0302791e8ac3bb97ddd.tar.bz2 lua-b117bdb3448778d9e7f9a0302791e8ac3bb97ddd.zip |
Counter for length of chains of __call metamethods
This counter will allow (in a later commit) error messages to correct
argument numbers in functions called through __call metamethods.
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 41 |
1 files changed, 27 insertions, 14 deletions
@@ -464,21 +464,26 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) { | |||
464 | 464 | ||
465 | /* | 465 | /* |
466 | ** Check whether 'func' has a '__call' metafield. If so, put it in the | 466 | ** Check whether 'func' has a '__call' metafield. If so, put it in the |
467 | ** stack, below original 'func', so that 'luaD_precall' can call it. Raise | 467 | ** stack, below original 'func', so that 'luaD_precall' can call it. |
468 | ** an error if there is no '__call' metafield. | 468 | ** Raise an error if there is no '__call' metafield. |
469 | ** Bits CIST_CCMT in status count how many _call metamethods were | ||
470 | ** invoked and how many corresponding extra arguments were pushed. | ||
471 | ** (This count will be saved in the 'callstatus' of the call). | ||
472 | ** Raise an error if this counter overflows. | ||
469 | */ | 473 | */ |
470 | static StkId tryfuncTM (lua_State *L, StkId func) { | 474 | static unsigned tryfuncTM (lua_State *L, StkId func, unsigned status) { |
471 | const TValue *tm; | 475 | const TValue *tm; |
472 | StkId p; | 476 | StkId p; |
473 | checkstackp(L, 1, func); /* space for metamethod */ | 477 | tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); |
474 | tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); /* (after previous GC) */ | 478 | if (l_unlikely(ttisnil(tm))) /* no metamethod? */ |
475 | if (l_unlikely(ttisnil(tm))) | 479 | luaG_callerror(L, s2v(func)); |
476 | luaG_callerror(L, s2v(func)); /* nothing to call */ | ||
477 | for (p = L->top.p; p > func; p--) /* open space for metamethod */ | 480 | for (p = L->top.p; p > func; p--) /* open space for metamethod */ |
478 | setobjs2s(L, p, p-1); | 481 | setobjs2s(L, p, p-1); |
479 | L->top.p++; /* stack space pre-allocated by the caller */ | 482 | L->top.p++; /* stack space pre-allocated by the caller */ |
480 | setobj2s(L, func, tm); /* metamethod is the new function to be called */ | 483 | setobj2s(L, func, tm); /* metamethod is the new function to be called */ |
481 | return func; | 484 | if ((status & MAX_CCMT) == MAX_CCMT) /* is counter full? */ |
485 | luaG_runerror(L, "'__call' chain too long"); | ||
486 | return status + (1u << CIST_CCMT); /* increment counter */ | ||
482 | } | 487 | } |
483 | 488 | ||
484 | 489 | ||
@@ -564,11 +569,17 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { | |||
564 | #define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L)) | 569 | #define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L)) |
565 | 570 | ||
566 | 571 | ||
572 | /* | ||
573 | ** Allocate and initialize CallInfo structure. At this point, the | ||
574 | ** only valid fields in the call status are number of results, | ||
575 | ** CIST_C (if it's a C function), and number of extra arguments. | ||
576 | ** (All these bit-fields fit in 16-bit values.) | ||
577 | */ | ||
567 | l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, unsigned status, | 578 | l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, unsigned status, |
568 | StkId top) { | 579 | StkId top) { |
569 | CallInfo *ci = L->ci = next_ci(L); /* new frame */ | 580 | CallInfo *ci = L->ci = next_ci(L); /* new frame */ |
570 | ci->func.p = func; | 581 | ci->func.p = func; |
571 | lua_assert((status & ~(CIST_NRESULTS | CIST_C)) == 0); | 582 | lua_assert((status & ~(CIST_NRESULTS | CIST_C | MAX_CCMT)) == 0); |
572 | ci->callstatus = status; | 583 | ci->callstatus = status; |
573 | ci->top.p = top; | 584 | ci->top.p = top; |
574 | return ci; | 585 | return ci; |
@@ -607,12 +618,13 @@ l_sinline int precallC (lua_State *L, StkId func, unsigned status, | |||
607 | */ | 618 | */ |
608 | int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, | 619 | int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, |
609 | int narg1, int delta) { | 620 | int narg1, int delta) { |
621 | unsigned status = LUA_MULTRET + 1; | ||
610 | retry: | 622 | retry: |
611 | switch (ttypetag(s2v(func))) { | 623 | switch (ttypetag(s2v(func))) { |
612 | case LUA_VCCL: /* C closure */ | 624 | case LUA_VCCL: /* C closure */ |
613 | return precallC(L, func, LUA_MULTRET + 1, clCvalue(s2v(func))->f); | 625 | return precallC(L, func, status, clCvalue(s2v(func))->f); |
614 | case LUA_VLCF: /* light C function */ | 626 | case LUA_VLCF: /* light C function */ |
615 | return precallC(L, func, LUA_MULTRET + 1, fvalue(s2v(func))); | 627 | return precallC(L, func, status, fvalue(s2v(func))); |
616 | case LUA_VLCL: { /* Lua function */ | 628 | case LUA_VLCL: { /* Lua function */ |
617 | Proto *p = clLvalue(s2v(func))->p; | 629 | Proto *p = clLvalue(s2v(func))->p; |
618 | int fsize = p->maxstacksize; /* frame size */ | 630 | int fsize = p->maxstacksize; /* frame size */ |
@@ -633,8 +645,8 @@ int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, | |||
633 | return -1; | 645 | return -1; |
634 | } | 646 | } |
635 | default: { /* not a function */ | 647 | default: { /* not a function */ |
636 | func = tryfuncTM(L, func); /* try to get '__call' metamethod */ | 648 | checkstackp(L, 1, func); /* space for metamethod */ |
637 | /* return luaD_pretailcall(L, ci, func, narg1 + 1, delta); */ | 649 | status = tryfuncTM(L, func, status); /* try '__call' metamethod */ |
638 | narg1++; | 650 | narg1++; |
639 | goto retry; /* try again */ | 651 | goto retry; /* try again */ |
640 | } | 652 | } |
@@ -676,7 +688,8 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { | |||
676 | return ci; | 688 | return ci; |
677 | } | 689 | } |
678 | default: { /* not a function */ | 690 | default: { /* not a function */ |
679 | func = tryfuncTM(L, func); /* try to get '__call' metamethod */ | 691 | checkstackp(L, 1, func); /* space for metamethod */ |
692 | status = tryfuncTM(L, func, status); /* try '__call' metamethod */ | ||
680 | goto retry; /* try again with metamethod */ | 693 | goto retry; /* try again with metamethod */ |
681 | } | 694 | } |
682 | } | 695 | } |