Skip to content

Commit

Permalink
Issue #81 : Fix an infinite loop when tables contain numeric Zero as …
Browse files Browse the repository at this point in the history
…an index
  • Loading branch information
yuin committed Sep 18, 2016
1 parent 6a1397d commit be46d31
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 29 deletions.
22 changes: 22 additions & 0 deletions _glua-tests/issues.lua
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,25 @@ stack traceback:
@TAB@issues.lua:103: in main chunk
@TAB@[G]: ?]], "@TAB@", "\t"))

-- issue 81
local tbl = {
[-1] = "a",
[0] = "b",
[1] = "c",
}
local a, b = next(tbl, nil)
assert( a == -1 and b == "a" or a == 0 and b == "b" or a == 1 and b == "c")
local a, b = next(tbl, a)
assert( a == -1 and b == "a" or a == 0 and b == "b" or a == 1 and b == "c")
local a, b = next(tbl, a)
assert( a == -1 and b == "a" or a == 0 and b == "b" or a == 1 and b == "c")
local a, b = next(tbl, a)
assert( a == nil and b == nil)

local tbl = {'a', 'b'}
local a, b = next(tbl, nil)
assert(a == 1 and b == "a")
local a, b = next(tbl, a)
assert(a == 2 and b == "b")
local a, b = next(tbl, a)
assert(a == nil and b == nil)
49 changes: 21 additions & 28 deletions table.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,10 +316,12 @@ func (tb *LTable) ForEach(cb func(LValue, LValue)) {
// This function is equivalent to lua_next ( http://www.lua.org/manual/5.1/manual.html#lua_next ).
func (tb *LTable) Next(key LValue) (LValue, LValue) {
// TODO: inefficient way
init := false
if key == LNil {
tb.keys = nil
tb.k2i = nil
key = LNumber(0)
init = true
}

length := 0
Expand Down Expand Up @@ -350,43 +352,34 @@ func (tb *LTable) Next(key LValue) (LValue, LValue) {
}
}

if kv, ok := key.(LNumber); ok && isInteger(kv) && int(kv) >= 0 {
index := int(kv)
if tb.array != nil {
for ; index < len(tb.array); index++ {
if v := tb.array[index]; v != LNil {
return LNumber(index + 1), v
if init || key != LNumber(0) {
if kv, ok := key.(LNumber); ok && isInteger(kv) && int(kv) >= 0 {
index := int(kv)
if tb.array != nil {
for ; index < len(tb.array); index++ {
if v := tb.array[index]; v != LNil {
return LNumber(index + 1), v
}
}
}
}
if tb.array == nil || index == len(tb.array) {
if (tb.dict == nil || len(tb.dict) == 0) && (tb.strdict == nil || len(tb.strdict) == 0) {
tb.keys = nil
tb.k2i = nil
return LNil, LNil
}
key = tb.keys[0]
if skey, sok := key.(LString); sok && tb.strdict != nil {
if sv, svok := tb.strdict[string(skey)]; svok && sv != LNil {
return key, sv
if tb.array == nil || index == len(tb.array) {
if (tb.dict == nil || len(tb.dict) == 0) && (tb.strdict == nil || len(tb.strdict) == 0) {
tb.keys = nil
tb.k2i = nil
return LNil, LNil
}
} else if tb.dict != nil {
if v, vok := tb.dict[key]; vok && v != LNil {
key = tb.keys[0]
if v := tb.RawGetH(key); v != LNil {
return key, v
}
}
}
}

for i := tb.k2i[key] + 1; i < length; i++ {
key = tb.keys[i]
if skey, sok := key.(LString); sok && tb.strdict != nil {
if sv, svok := tb.strdict[string(skey)]; svok && sv != LNil {
return key, sv
}
} else if tb.dict != nil {
if v, vok := tb.dict[key]; vok && v != LNil {
return key, v
}
key = tb.keys[tb.k2i[key]+1]
if v := tb.RawGetH(key); v != LNil {
return key, v
}
}
tb.keys = nil
Expand Down
2 changes: 1 addition & 1 deletion utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (fs *flagScanner) Next() (byte, bool) {
var cDateFlagToGo = map[byte]string{
'a': "mon", 'A': "Monday", 'b': "Jan", 'B': "January", 'c': "02 Jan 06 15:04 MST", 'd': "02",
'F': "2006-01-02", 'H': "15", 'I': "03", 'm': "01", 'M': "04", 'p': "PM", 'P': "pm", 'S': "05",
'x': "15/04/05", 'X': "15:04:05",'y': "06", 'Y': "2006", 'z': "-0700", 'Z': "MST"}
'x': "15/04/05", 'X': "15:04:05", 'y': "06", 'Y': "2006", 'z': "-0700", 'Z': "MST"}

func strftime(t time.Time, cfmt string) string {
sc := newFlagScanner('%', "", "", cfmt)
Expand Down

0 comments on commit be46d31

Please sign in to comment.