diff options
-rw-r--r-- | bugs | 406 |
1 files changed, 404 insertions, 2 deletions
@@ -2899,6 +2899,30 @@ patch = [[ | |||
2899 | ]] | 2899 | ]] |
2900 | } | 2900 | } |
2901 | 2901 | ||
2902 | Bug{ | ||
2903 | what = [[Lua does not check memory use when creating error messages]], | ||
2904 | report = [[John Dunn, 2012/09/24]], | ||
2905 | since = [[5.2.0]], | ||
2906 | fix = nil, | ||
2907 | example = [[ | ||
2908 | local code = "function test()\n bob.joe.larry = 23\n end" | ||
2909 | |||
2910 | load(code)() | ||
2911 | |||
2912 | -- memory will grow steadly | ||
2913 | for i = 1, math.huge do | ||
2914 | pcall(test) | ||
2915 | if i % 100000 == 0 then | ||
2916 | io.write(collectgarbage'count'*1024, "\n") | ||
2917 | end | ||
2918 | end | ||
2919 | ]], | ||
2920 | patch = [[ | ||
2921 | ]] | ||
2922 | } | ||
2923 | |||
2924 | |||
2925 | |||
2902 | 2926 | ||
2903 | 2927 | ||
2904 | ----------------------------------------------------------------- | 2928 | ----------------------------------------------------------------- |
@@ -3656,9 +3680,9 @@ It needs an "interceptor" 'memcmp' function that continues | |||
3656 | reading memory after a difference is found.]], | 3680 | reading memory after a difference is found.]], |
3657 | patch = [[ | 3681 | patch = [[ |
3658 | 2c2 | 3682 | 2c2 |
3659 | < ** $Id: bugs,v 1.150 2016/07/19 17:10:45 roberto Exp roberto $ | 3683 | < ** $Id: bugs,v 1.160 2018/05/24 20:25:14 roberto Exp roberto $ |
3660 | --- | 3684 | --- |
3661 | > ** $Id: bugs,v 1.150 2016/07/19 17:10:45 roberto Exp roberto $ | 3685 | > ** $Id: bugs,v 1.160 2018/05/24 20:25:14 roberto Exp roberto $ |
3662 | 263c263,264 | 3686 | 263c263,264 |
3663 | < for (option = LUA_STRFTIMEOPTIONS; *option != '\0'; option += oplen) { | 3687 | < for (option = LUA_STRFTIMEOPTIONS; *option != '\0'; option += oplen) { |
3664 | --- | 3688 | --- |
@@ -3711,9 +3735,387 @@ A() | |||
3711 | patch = [[ | 3735 | patch = [[ |
3712 | ]] | 3736 | ]] |
3713 | } | 3737 | } |
3738 | |||
3739 | |||
3740 | ----------------------------------------------------------------- | ||
3741 | -- Lua 5.3.4 | ||
3742 | |||
3743 | |||
3744 | Bug{ | ||
3745 | what = [[Wrong code for a goto followed by a label inside an 'if']], | ||
3746 | report = [[云风, 2017/04/13]], | ||
3747 | since = [[5.2]], | ||
3748 | fix = nil, | ||
3749 | example = [[ | ||
3750 | -- should print 32323232..., but prints only '3' | ||
3751 | if true then | ||
3752 | goto LBL | ||
3753 | ::loop:: | ||
3754 | print(2) | ||
3755 | ::LBL:: | ||
3756 | print(3) | ||
3757 | goto loop | ||
3758 | end | ||
3759 | ]], | ||
3760 | patch = [[ | ||
3761 | --- lparser.c 2017/04/19 17:20:42 2.155.1.1 | ||
3762 | +++ lparser.c 2017/04/29 18:11:40 2.155.1.2 | ||
3763 | @@ -1392,7 +1392,7 @@ | ||
3764 | luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ | ||
3765 | enterblock(fs, &bl, 0); /* must enter block before 'goto' */ | ||
3766 | gotostat(ls, v.t); /* handle goto/break */ | ||
3767 | - skipnoopstat(ls); /* skip other no-op statements */ | ||
3768 | + while (testnext(ls, ';')) {} /* skip semicolons */ | ||
3769 | if (block_follow(ls, 0)) { /* 'goto' is the entire block? */ | ||
3770 | leaveblock(fs); | ||
3771 | return; /* and that is it */ | ||
3772 | ]] | ||
3773 | } | ||
3774 | |||
3775 | |||
3776 | Bug{ | ||
3777 | what = [[Lua crashes when building sequences with more than 2^30 elements.]], | ||
3778 | report = [[Viacheslav Usov, 2017/05/11]], | ||
3779 | since = [[ ]], | ||
3780 | fix = nil, | ||
3781 | example = [[ | ||
3782 | -- crashes if machine has enough memory | ||
3783 | local t = {} | ||
3784 | for i = 1, 0x7fffffff do | ||
3785 | t[i] = i | ||
3786 | end | ||
3787 | ]], | ||
3788 | patch = [[ | ||
3789 | --- ltable.c 2017/04/19 17:20:42 2.118.1.1 | ||
3790 | +++ ltable.c 2018/05/24 18:34:38 | ||
3791 | @@ -223,7 +223,9 @@ | ||
3792 | unsigned int na = 0; /* number of elements to go to array part */ | ||
3793 | unsigned int optimal = 0; /* optimal size for array part */ | ||
3794 | /* loop while keys can fill more than half of total size */ | ||
3795 | - for (i = 0, twotoi = 1; *pna > twotoi / 2; i++, twotoi *= 2) { | ||
3796 | + for (i = 0, twotoi = 1; | ||
3797 | + twotoi > 0 && *pna > twotoi / 2; | ||
3798 | + i++, twotoi *= 2) { | ||
3799 | if (nums[i] > 0) { | ||
3800 | a += nums[i]; | ||
3801 | if (a > twotoi/2) { /* more than half elements present? */ | ||
3802 | ]] | ||
3803 | } | ||
3804 | |||
3805 | |||
3806 | Bug{ | ||
3807 | what = [[Table length computation overflows for sequences larger than | ||
3808 | 2^31 elements.]], | ||
3809 | report = [[Viacheslav Usov, 2017/05/12]], | ||
3810 | since = [[ ]], | ||
3811 | fix = nil, | ||
3812 | example = [[ | ||
3813 | -- on a machine with enough memory | ||
3814 | local t = {} | ||
3815 | for i = 1, 2147483681 do | ||
3816 | t[i] = i | ||
3817 | end | ||
3818 | print(#t) | ||
3819 | ]], | ||
3820 | patch = [[ | ||
3821 | --- ltable.h 2017/04/19 17:20:42 2.23.1.1 | ||
3822 | +++ ltable.h 2018/05/24 19:31:50 | ||
3823 | @@ -56,3 +56,3 @@ | ||
3824 | LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); | ||
3825 | -LUAI_FUNC int luaH_getn (Table *t); | ||
3826 | +LUAI_FUNC lua_Unsigned luaH_getn (Table *t); | ||
3827 | |||
3828 | --- ltable.c 2018/05/24 19:22:37 2.118.1.2 | ||
3829 | +++ ltable.c 2018/05/24 19:25:05 | ||
3830 | @@ -614,4 +614,4 @@ | ||
3831 | |||
3832 | -static int unbound_search (Table *t, unsigned int j) { | ||
3833 | - unsigned int i = j; /* i is zero or a present index */ | ||
3834 | +static lua_Unsigned unbound_search (Table *t, lua_Unsigned j) { | ||
3835 | + lua_Unsigned i = j; /* i is zero or a present index */ | ||
3836 | j++; | ||
3837 | @@ -620,3 +620,3 @@ | ||
3838 | i = j; | ||
3839 | - if (j > cast(unsigned int, MAX_INT)/2) { /* overflow? */ | ||
3840 | + if (j > l_castS2U(LUA_MAXINTEGER) / 2) { /* overflow? */ | ||
3841 | /* table was built with bad purposes: resort to linear search */ | ||
3842 | @@ -630,3 +630,3 @@ | ||
3843 | while (j - i > 1) { | ||
3844 | - unsigned int m = (i+j)/2; | ||
3845 | + lua_Unsigned m = (i+j)/2; | ||
3846 | if (ttisnil(luaH_getint(t, m))) j = m; | ||
3847 | @@ -642,3 +642,3 @@ | ||
3848 | */ | ||
3849 | -int luaH_getn (Table *t) { | ||
3850 | +lua_Unsigned luaH_getn (Table *t) { | ||
3851 | unsigned int j = t->sizearray; | ||
3852 | ]] | ||
3853 | } | ||
3854 | |||
3855 | |||
3856 | Bug{ | ||
3857 | what = [[Lua does not check GC when creating error messages]], | ||
3858 | report = [[Viacheslav Usov, 2017/07/06]], | ||
3859 | since = [[5.3.2]], | ||
3860 | fix = nil, | ||
3861 | example = [[ | ||
3862 | function test() | ||
3863 | bob.joe.larry = 23 | ||
3864 | end | ||
3865 | |||
3866 | -- memory will grow steadly | ||
3867 | for i = 1, math.huge do | ||
3868 | pcall(test) | ||
3869 | if i % 100000 == 0 then | ||
3870 | io.write(collectgarbage'count'*1024, "\n") | ||
3871 | end | ||
3872 | end | ||
3873 | ]], | ||
3874 | patch = [[ | ||
3875 | --- ldebug.c 2017/04/19 17:20:42 2.121.1.1 | ||
3876 | +++ ldebug.c 2017/07/10 17:08:39 | ||
3877 | @@ -653,6 +653,7 @@ | ||
3878 | CallInfo *ci = L->ci; | ||
3879 | const char *msg; | ||
3880 | va_list argp; | ||
3881 | + luaC_checkGC(L); /* error message uses memory */ | ||
3882 | va_start(argp, fmt); | ||
3883 | msg = luaO_pushvfstring(L, fmt, argp); /* format message */ | ||
3884 | va_end(argp); | ||
3885 | ]] | ||
3886 | } | ||
3887 | |||
3888 | |||
3889 | Bug{ | ||
3890 | what = [[dead keys with nil values can stay in weak tables]], | ||
3891 | report = [[云风 Cloud Wu, 2017/08/15]], | ||
3892 | since = [[5.2]], | ||
3893 | fix = nil, | ||
3894 | example = [[ | ||
3895 | -- The following chunk, under a memory checker like valgrind, | ||
3896 | -- produces a memory access violation. | ||
3897 | |||
3898 | local a = setmetatable({}, {__mode = 'kv'}) | ||
3899 | |||
3900 | a['ABCDEFGHIJKLMNOPQRSTUVWXYZ' .. 'abcdefghijklmnopqrstuvwxyz'] = {} | ||
3901 | a[next(a)] = nil | ||
3902 | collectgarbage() | ||
3903 | print(a['BCDEFGHIJKLMNOPQRSTUVWXYZ' .. 'abcdefghijklmnopqrstuvwxyz']) | ||
3904 | ]], | ||
3905 | patch = [[ | ||
3906 | --- lgc.c 2016/12/22 13:08:50 2.215 | ||
3907 | +++ lgc.c 2017/08/31 16:08:23 | ||
3908 | @@ -643,8 +643,9 @@ | ||
3909 | for (n = gnode(h, 0); n < limit; n++) { | ||
3910 | if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { | ||
3911 | setnilvalue(gval(n)); /* remove value ... */ | ||
3912 | - removeentry(n); /* and remove entry from table */ | ||
3913 | } | ||
3914 | + if (ttisnil(gval(n))) /* is entry empty? */ | ||
3915 | + removeentry(n); /* remove entry from table */ | ||
3916 | } | ||
3917 | } | ||
3918 | } | ||
3919 | ]] | ||
3920 | } | ||
3921 | |||
3922 | |||
3923 | Bug{ | ||
3924 | what = [['lua_pushcclosure' should not call the garbage collector when | ||
3925 | 'n' is zero.]], | ||
3926 | report = [[Andrew Gierth, 2017/12/05]], | ||
3927 | since = [[5.3.3]], | ||
3928 | fix = nil, | ||
3929 | example = [[ ]], | ||
3930 | patch = [[ | ||
3931 | --- lapi.c 2017/04/19 17:13:00 2.259.1.1 | ||
3932 | +++ lapi.c 2017/12/06 18:14:45 | ||
3933 | @@ -533,6 +533,7 @@ | ||
3934 | lua_lock(L); | ||
3935 | if (n == 0) { | ||
3936 | setfvalue(L->top, fn); | ||
3937 | + api_incr_top(L); | ||
3938 | } | ||
3939 | else { | ||
3940 | CClosure *cl; | ||
3941 | @@ -546,9 +547,9 @@ | ||
3942 | /* does not need barrier because closure is white */ | ||
3943 | } | ||
3944 | setclCvalue(L, L->top, cl); | ||
3945 | + api_incr_top(L); | ||
3946 | + luaC_checkGC(L); | ||
3947 | } | ||
3948 | - api_incr_top(L); | ||
3949 | - luaC_checkGC(L); | ||
3950 | lua_unlock(L); | ||
3951 | } | ||
3952 | ]] | ||
3953 | } | ||
3954 | |||
3955 | |||
3956 | Bug{ | ||
3957 | what = [[memory-allocation error when resizing a table can leave it | ||
3958 | in an inconsistent state.]], | ||
3959 | report = [[Roberto, 2017/12/08]], | ||
3960 | since = [[5.0]], | ||
3961 | fix = nil, | ||
3962 | example = [[ | ||
3963 | local a = {x = 1, y = 1, z = 1} | ||
3964 | a[1] = 10 -- goes to the hash part (which has 4 slots) | ||
3965 | print(a[1]) --> 10 | ||
3966 | |||
3967 | -- assume that the 2nd memory allocation from now fails | ||
3968 | pcall(rawset, a, 2, 20) -- forces a rehash | ||
3969 | |||
3970 | -- a[1] now exists both in the array part (because the array part | ||
3971 | -- grew) and in the hash part (because the allocation of the hash | ||
3972 | -- part failed, keeping it as it was). | ||
3973 | -- This makes the following traversal goes forever... | ||
3974 | for k,v in pairs(a) do print(k,v) end | ||
3975 | ]], | ||
3976 | patch = [[ | ||
3977 | --- ltable.c 2018/05/24 19:39:05 2.118.1.3 | ||
3978 | +++ ltable.c 2018/06/04 16:00:25 | ||
3979 | @@ -332,17 +332,34 @@ | ||
3980 | } | ||
3981 | |||
3982 | |||
3983 | +typedef struct { | ||
3984 | + Table *t; | ||
3985 | + unsigned int nhsize; | ||
3986 | +} AuxsetnodeT; | ||
3987 | + | ||
3988 | + | ||
3989 | +static void auxsetnode (lua_State *L, void *ud) { | ||
3990 | + AuxsetnodeT *asn = cast(AuxsetnodeT *, ud); | ||
3991 | + setnodevector(L, asn->t, asn->nhsize); | ||
3992 | +} | ||
3993 | + | ||
3994 | + | ||
3995 | void luaH_resize (lua_State *L, Table *t, unsigned int nasize, | ||
3996 | unsigned int nhsize) { | ||
3997 | unsigned int i; | ||
3998 | int j; | ||
3999 | + AuxsetnodeT asn; | ||
4000 | unsigned int oldasize = t->sizearray; | ||
4001 | int oldhsize = allocsizenode(t); | ||
4002 | Node *nold = t->node; /* save old hash ... */ | ||
4003 | if (nasize > oldasize) /* array part must grow? */ | ||
4004 | setarrayvector(L, t, nasize); | ||
4005 | /* create new hash part with appropriate size */ | ||
4006 | - setnodevector(L, t, nhsize); | ||
4007 | + asn.t = t; asn.nhsize = nhsize; | ||
4008 | + if (luaD_rawrunprotected(L, auxsetnode, &asn) != LUA_OK) { /* mem. error? */ | ||
4009 | + setarrayvector(L, t, oldasize); /* array back to its original size */ | ||
4010 | + luaD_throw(L, LUA_ERRMEM); /* rethrow memory error */ | ||
4011 | + } | ||
4012 | if (nasize < oldasize) { /* array part must shrink? */ | ||
4013 | t->sizearray = nasize; | ||
4014 | /* re-insert elements from vanishing slice */ | ||
4015 | ]] | ||
4016 | } | ||
4017 | |||
4018 | |||
4019 | |||
4020 | ----------------------------------------------------------------- | ||
4021 | -- Lua 5.3.5 | ||
4022 | |||
4023 | --[=[ | ||
4024 | Bug{ | ||
4025 | what = [[Long brackets with a huge number of '=' overflow some | ||
4026 | internal buffer arithmetic]], | ||
4027 | report = [[Marco, 2018/12/12]], | ||
4028 | since = [[5.1]], | ||
4029 | fix = nil, | ||
4030 | example = [[ | ||
4031 | local eqs = string.rep("=", 0x3ffffffe) | ||
4032 | local code = "return [" .. eqs .. "[a]" .. eqs .. "]" | ||
4033 | print(#assert(load(code))()) | ||
4034 | ]], | ||
4035 | patch = [[ | ||
4036 | --- a/llex.c | ||
4037 | +++ b/llex.c | ||
4038 | @@ -244,12 +244,12 @@ | ||
4039 | |||
4040 | |||
4041 | /* | ||
4042 | -** skip a sequence '[=*[' or ']=*]'; if sequence is well formed, return | ||
4043 | -** its number of '='s; otherwise, return a negative number (-1 iff there | ||
4044 | -** are no '='s after initial bracket) | ||
4045 | +** reads a sequence '[=*[' or ']=*]', leaving the last bracket. | ||
4046 | +** If sequence is well formed, return its number of '='s + 2; otherwise, | ||
4047 | +** return 1 if there is no '='s or 0 otherwise (an unfinished '[==...'). | ||
4048 | */ | ||
4049 | -static int skip_sep (LexState *ls) { | ||
4050 | - int count = 0; | ||
4051 | +static size_t skip_sep (LexState *ls) { | ||
4052 | + size_t count = 0; | ||
4053 | int s = ls->current; | ||
4054 | lua_assert(s == '[' || s == ']'); | ||
4055 | save_and_next(ls); | ||
4056 | @@ -257,11 +257,14 @@ | ||
4057 | save_and_next(ls); | ||
4058 | count++; | ||
4059 | } | ||
4060 | - return (ls->current == s) ? count : (-count) - 1; | ||
4061 | + return (ls->current == s) ? count + 2 | ||
4062 | + : (count == 0) ? 1 | ||
4063 | + : 0; | ||
4064 | + | ||
4065 | } | ||
4066 | |||
4067 | |||
4068 | -static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { | ||
4069 | +static void read_long_string (LexState *ls, SemInfo *seminfo, size_t sep) { | ||
4070 | int line = ls->linenumber; /* initial line (for error message) */ | ||
4071 | save_and_next(ls); /* skip 2nd '[' */ | ||
4072 | if (currIsNewline(ls)) /* string starts with a newline? */ | ||
4073 | @@ -295,8 +298,8 @@ | ||
4074 | } | ||
4075 | } endloop: | ||
4076 | if (seminfo) | ||
4077 | - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), | ||
4078 | - luaZ_bufflen(ls->buff) - 2*(2 + sep)); | ||
4079 | + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + sep, | ||
4080 | + luaZ_bufflen(ls->buff) - 2 * sep); | ||
4081 | } | ||
4082 | |||
4083 | |||
4084 | @@ -444,9 +447,9 @@ | ||
4085 | /* else is a comment */ | ||
4086 | next(ls); | ||
4087 | if (ls->current == '[') { /* long comment? */ | ||
4088 | - int sep = skip_sep(ls); | ||
4089 | + size_t sep = skip_sep(ls); | ||
4090 | luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */ | ||
4091 | - if (sep >= 0) { | ||
4092 | + if (sep >= 2) { | ||
4093 | read_long_string(ls, NULL, sep); /* skip long comment */ | ||
4094 | luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ | ||
4095 | break; | ||
4096 | @@ -458,12 +461,12 @@ | ||
4097 | break; | ||
4098 | } | ||
4099 | case '[': { /* long string or simply '[' */ | ||
4100 | - int sep = skip_sep(ls); | ||
4101 | - if (sep >= 0) { | ||
4102 | + size_t sep = skip_sep(ls); | ||
4103 | + if (sep >= 2) { | ||
4104 | read_long_string(ls, seminfo, sep); | ||
4105 | return TK_STRING; | ||
4106 | } | ||
4107 | - else if (sep != -1) /* '[=...' missing second bracket */ | ||
4108 | + else if (sep == 0) /* '[=...' missing second bracket */ | ||
4109 | lexerror(ls, "invalid long string delimiter", TK_STRING); | ||
4110 | return '['; | ||
4111 | } | ||
4112 | ]] | ||
4113 | } | ||
3714 | ]=] | 4114 | ]=] |
3715 | 4115 | ||
3716 | 4116 | ||
4117 | |||
4118 | |||
3717 | --[=[ | 4119 | --[=[ |
3718 | Bug{ | 4120 | Bug{ |
3719 | what = [[ ]], | 4121 | what = [[ ]], |