cocos2d / cocos2d-x

Cocos2d-x is a suite of open-source, cross-platform, game-development tools utilized by millions of developers across the globe. Its core has evolved to serve as the foundation for Cocos Creator 1.x & 2.x.
https://www.cocos.com/en/cocos2d-x
18.22k stars 7.05k forks source link

luaval_to_ccvaluemap 遍历 hash table 的时候如果 key 为 number 就会出现错误 #15318

Open xzben opened 8 years ago

xzben commented 8 years ago

example: lua table 为 local tbl = {} tbl[2] = 100 当在c++中使用 luaval_to_ccvaluemap 时会导致 错误 ,看了lua 官方的文档有提到 image 在使用 lua_next 的过程中不能对非string类型的key使用 lua_tolstring 如果使用了会破坏 table 的index结构的。

现在的代码只是简单的判断 lua_isstring ,但是在lua 5.1的源码中 LUA_API int lua_isstring (lua_State _L, int idx) { int t = lua_type(L, idx); return (t == LUA_TSTRING || t == LUA_TNUMBER); } 字符串和数字都是 lua_isstring 为 true 的,所以应该修改原先的代码 为 `bool luaval_to_ccvaluemap(luaState L, int lo, cocos2d::ValueMap* ret, const char* funcName) { if ( nullptr == L || nullptr == ret) return false;

tolua_Error tolua_err;
bool ok = true;
if (!tolua_istable(L, lo, 0, &tolua_err))
{

if COCOS2D_DEBUG >=1

    luaval_to_native_err(L,"#ferror:",&tolua_err,funcName);

endif

    ok = false;
}

if (ok)
{
    std::string stringKey = "";
    std::string stringValue = "";
    bool boolVal = false;
    ValueMap& dict = *ret;
    lua_pushnil(L);                                             /* first key L: lotable ..... nil */
    while ( 0 != lua_next(L, lo ) )                             /* L: lotable ..... key value */
    {
        if (lua_isnumber(L, -2))
        {
            int key =  lua_tonumber(L, -2);
            std::stringstream ss;
            ss << key;
            ss >> stringKey;
        }
        else if ( !lua_isstring(L, -2) || !luaval_to_std_string(L, -2, &stringKey))
        {
            lua_pop(L, 1);                                      /* removes 'value'; keep 'key' for next iteration*/
            continue;
        }

        {

            if(lua_istable(L, -1))
            {
                lua_pushnumber(L,1);
                lua_gettable(L,-2);

                if (lua_isnil(L, -1) )                          /** if table[1] = nil,we don't think it is a pure array */
                {
                    lua_pop(L,1);
                    ValueMap dictVal;
                    if (luaval_to_ccvaluemap(L, lua_gettop(L), &dictVal))
                    {
                        dict[stringKey] = Value(dictVal);
                    }
                }
                else
                {
                    lua_pop(L,1);
                    ValueVector arrVal;
                    if (luaval_to_ccvaluevector(L, lua_gettop(L), &arrVal))
                    {
                        dict[stringKey] = Value(arrVal);
                    }
                }
            }
            else if(lua_type(L, -1) == LUA_TSTRING)
            {
                if(luaval_to_std_string(L, -1, &stringValue))
                {
                    dict[stringKey] = Value(stringValue);
                }
            }
            else if(lua_type(L, -1) == LUA_TBOOLEAN)
            {
                if (luaval_to_boolean(L, -1, &boolVal))
                {
                    dict[stringKey] = Value(boolVal);
                }
            }
            else if(lua_type(L, -1) == LUA_TNUMBER)
            {
                dict[stringKey] = Value(tolua_tonumber(L, -1, 0));
            }
            else
            {
                CCASSERT(false, "not supported type");
            }
        }

        lua_pop(L, 1);                                          /* L: lotable ..... key */
    }
}

return ok;

}`

minggo commented 8 years ago

Could you please highlight your modification? Thanks.

xzben commented 8 years ago

if (lua_isnumber(L, -2)) { int key = lua_tonumber(L, -2); std::stringstream ss; ss << key; ss >> stringKey; } else if ( !lua_isstring(L, -2) || !luaval_to_std_string(L, -2, &stringKey)) { lua_pop(L, 1); /* removes 'value'; keep 'key' for next iteration*/ continue; }

minggo commented 8 years ago

Thanks, i will check it.

minggo commented 8 years ago

@dualface Could you please take a look?

minggo commented 8 years ago

@xzben will you send a pull request?