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 = [[ ]], |
