Mon Apr 17 19:35:36 2023 UTC ()
lua: apply upstream bugfix for "Lua-stack overflow when C stack overflows while
handling an error." (CVE-2022-33099)

 Save stack space while handling errors

Because error handling (luaG_errormsg) uses slots from EXTRA_STACK,
and some errors can recur (e.g., string overflow while creating an
error message in 'luaG_runerror', or a C-stack overflow before calling
the message handler), the code should use stack slots with parsimony.

This commit fixes the bug "Lua-stack overflow when C stack overflows
while handling an error".


(nikita)
diff -r1.12 -r1.13 src/external/mit/lua/dist/src/ldebug.c
diff -r1.15 -r1.16 src/external/mit/lua/dist/src/lvm.c

cvs diff -r1.12 -r1.13 src/external/mit/lua/dist/src/ldebug.c (expand / switch to unified diff)

--- src/external/mit/lua/dist/src/ldebug.c 2023/04/16 20:46:17 1.12
+++ src/external/mit/lua/dist/src/ldebug.c 2023/04/17 19:35:36 1.13
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ldebug.c,v 1.12 2023/04/16 20:46:17 nikita Exp $ */ 1/* $NetBSD: ldebug.c,v 1.13 2023/04/17 19:35:36 nikita Exp $ */
2 2
3/* 3/*
4** Id: ldebug.c  4** Id: ldebug.c
5** Debug Interface 5** Debug Interface
6** See Copyright Notice in lua.h 6** See Copyright Notice in lua.h
7*/ 7*/
8 8
9#define ldebug_c 9#define ldebug_c
10#define LUA_CORE 10#define LUA_CORE
11 11
12#include "lprefix.h" 12#include "lprefix.h"
13 13
14 14
@@ -818,28 +818,31 @@ l_noret luaG_errormsg (lua_State *L) { @@ -818,28 +818,31 @@ l_noret luaG_errormsg (lua_State *L) {
818 } 818 }
819 luaD_throw(L, LUA_ERRRUN); 819 luaD_throw(L, LUA_ERRRUN);
820} 820}
821 821
822 822
823l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { 823l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
824 CallInfo *ci = L->ci; 824 CallInfo *ci = L->ci;
825 const char *msg; 825 const char *msg;
826 va_list argp; 826 va_list argp;
827 luaC_checkGC(L); /* error message uses memory */ 827 luaC_checkGC(L); /* error message uses memory */
828 va_start(argp, fmt); 828 va_start(argp, fmt);
829 msg = luaO_pushvfstring(L, fmt, argp); /* format message */ 829 msg = luaO_pushvfstring(L, fmt, argp); /* format message */
830 va_end(argp); 830 va_end(argp);
831 if (isLua(ci)) /* if Lua function, add source:line information */ 831 if (isLua(ci)) { /* if Lua function, add source:line information */
832 luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci)); 832 luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci));
 833 setobjs2s(L, L->top - 2, L->top - 1); /* remove 'msg' from the stack */
 834 L->top--;
 835 }
833 luaG_errormsg(L); 836 luaG_errormsg(L);
834} 837}
835 838
836 839
837/* 840/*
838** Check whether new instruction 'newpc' is in a different line from 841** Check whether new instruction 'newpc' is in a different line from
839** previous instruction 'oldpc'. More often than not, 'newpc' is only 842** previous instruction 'oldpc'. More often than not, 'newpc' is only
840** one or a few instructions after 'oldpc' (it must be after, see 843** one or a few instructions after 'oldpc' (it must be after, see
841** caller), so try to avoid calling 'luaG_getfuncline'. If they are 844** caller), so try to avoid calling 'luaG_getfuncline'. If they are
842** too far apart, there is a good chance of a ABSLINEINFO in the way, 845** too far apart, there is a good chance of a ABSLINEINFO in the way,
843** so it goes directly to 'luaG_getfuncline'. 846** so it goes directly to 'luaG_getfuncline'.
844*/ 847*/
845static int changedline (const Proto *p, int oldpc, int newpc) { 848static int changedline (const Proto *p, int oldpc, int newpc) {

cvs diff -r1.15 -r1.16 src/external/mit/lua/dist/src/lvm.c (expand / switch to unified diff)

--- src/external/mit/lua/dist/src/lvm.c 2023/04/16 20:46:17 1.15
+++ src/external/mit/lua/dist/src/lvm.c 2023/04/17 19:35:36 1.16
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: lvm.c,v 1.15 2023/04/16 20:46:17 nikita Exp $ */ 1/* $NetBSD: lvm.c,v 1.16 2023/04/17 19:35:36 nikita Exp $ */
2 2
3/* 3/*
4** Id: lvm.c  4** Id: lvm.c
5** Lua virtual machine 5** Lua virtual machine
6** See Copyright Notice in lua.h 6** See Copyright Notice in lua.h
7*/ 7*/
8 8
9#define lvm_c 9#define lvm_c
10#define LUA_CORE 10#define LUA_CORE
11 11
12#include "lprefix.h" 12#include "lprefix.h"
13 13
14#ifndef _KERNEL 14#ifndef _KERNEL
@@ -688,43 +688,45 @@ void luaV_concat (lua_State *L, int tota @@ -688,43 +688,45 @@ void luaV_concat (lua_State *L, int tota
688 luaT_tryconcatTM(L); 688 luaT_tryconcatTM(L);
689 else if (isemptystr(s2v(top - 1))) /* second operand is empty? */ 689 else if (isemptystr(s2v(top - 1))) /* second operand is empty? */
690 cast_void(tostring(L, s2v(top - 2))); /* result is first operand */ 690 cast_void(tostring(L, s2v(top - 2))); /* result is first operand */
691 else if (isemptystr(s2v(top - 2))) { /* first operand is empty string? */ 691 else if (isemptystr(s2v(top - 2))) { /* first operand is empty string? */
692 setobjs2s(L, top - 2, top - 1); /* result is second op. */ 692 setobjs2s(L, top - 2, top - 1); /* result is second op. */
693 } 693 }
694 else { 694 else {
695 /* at least two non-empty string values; get as many as possible */ 695 /* at least two non-empty string values; get as many as possible */
696 size_t tl = vslen(s2v(top - 1)); 696 size_t tl = vslen(s2v(top - 1));
697 TString *ts; 697 TString *ts;
698 /* collect total length and number of strings */ 698 /* collect total length and number of strings */
699 for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) { 699 for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) {
700 size_t l = vslen(s2v(top - n - 1)); 700 size_t l = vslen(s2v(top - n - 1));
701 if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) 701 if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) {
 702 L->top = top - total; /* pop strings to avoid wasting stack */
702 luaG_runerror(L, "string length overflow"); 703 luaG_runerror(L, "string length overflow");
 704 }
703 tl += l; 705 tl += l;
704 } 706 }
705 if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */ 707 if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */
706 char buff[LUAI_MAXSHORTLEN]; 708 char buff[LUAI_MAXSHORTLEN];
707 copy2buff(top, n, buff); /* copy strings to buffer */ 709 copy2buff(top, n, buff); /* copy strings to buffer */
708 ts = luaS_newlstr(L, buff, tl); 710 ts = luaS_newlstr(L, buff, tl);
709 } 711 }
710 else { /* long string; copy strings directly to final result */ 712 else { /* long string; copy strings directly to final result */
711 ts = luaS_createlngstrobj(L, tl); 713 ts = luaS_createlngstrobj(L, tl);
712 copy2buff(top, n, getstr(ts)); 714 copy2buff(top, n, getstr(ts));
713 } 715 }
714 setsvalue2s(L, top - n, ts); /* create result */ 716 setsvalue2s(L, top - n, ts); /* create result */
715 } 717 }
716 total -= n-1; /* got 'n' strings to create 1 new */ 718 total -= n-1; /* got 'n' strings to create 1 new */
717 L->top -= n-1; /* popped 'n' strings and pushed one */ 719 L->top = top - (n - 1); /* popped 'n' strings and pushed one */
718 } while (total > 1); /* repeat until only 1 result left */ 720 } while (total > 1); /* repeat until only 1 result left */
719} 721}
720 722
721 723
722/* 724/*
723** Main operation 'ra = #rb'. 725** Main operation 'ra = #rb'.
724*/ 726*/
725void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { 727void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
726 const TValue *tm; 728 const TValue *tm;
727 switch (ttypetag(rb)) { 729 switch (ttypetag(rb)) {
728 case LUA_VTABLE: { 730 case LUA_VTABLE: {
729 Table *h = hvalue(rb); 731 Table *h = hvalue(rb);
730 tm = fasttm(L, h->metatable, TM_LEN); 732 tm = fasttm(L, h->metatable, TM_LEN);