lua转换string到Table

1、系统中经常需要将string转换为table,为求方便一般会直接用类似下面的方式:

function stringToTable(str)
   local ret = loadstring("return "..str)()
   return ret
end
问题1:这样的调用呢,本身在传入参数正确的情况下,是没有问题。如果传入参数非法,在调用loadstring的时候会失败,返回为nil,不能执行后面的调用操作

问题2:如果字符串是由不受信任的客户端传过来的,客户端可以通过构造特殊的字符串,达到执行LUA代码的目的,这就相当于有了一个远程执行代码的漏洞,例子如下:

  

str = "{1}, print('run print')"
stringToTable(str)

2、安全的转换方式,通过对编译后的指令进行检查,判断出是否是合法的构造TABLE的语句,如果是才执行。

static int luaB_makeACall (lua_State *L) {
    size_t l;
    const char *s = luaL_checklstring(L, 1, &l);
    const char *chunkname = luaL_optstring(L, 2, s);
    int ret = luaL_loadbuffer(L, s, l, chunkname);
    LClosure *cl = NULL;
    struct Proto *p = NULL;
    Instruction *code = NULL;
    int i = 0;
    int funNum = 0;

    if(ret != 0)
    {
        lua_pushnumber(L,-1);
        return 1;
    }

    // 如果成功则检查是否有违规指令
    cl = &clvalue(L->top - 1)->l;
    p  = cl->p;
    code = p->code;


    for (i=0;i< p->sizecode;++i)
    {
        int opcode = GET_OPCODE(code[i]);
        switch(opcode)
        {
        case OP_NEWTABLE:
        case OP_LOADK:
        case OP_LOADBOOL:
        case OP_LOADNIL:
        case OP_SETTABLE:
        case OP_SETLIST:
        case OP_GETGLOBAL:
        case OP_RETURN:
            break;
        case OP_CALL:
        case OP_TAILCALL:
            funNum++;
            if (funNum > 1)
            {
                lua_pushnumber(L,-1);
                return 1;
            }
            break;
        default:
            lua_pushnumber(L,-1);
            return 1;
        }
    }

    // 校验指令完毕后,执行函数
    lua_call(L, 0, 1);

    // 返回0表示执行成功
    lua_pushnumber(L,0);

    return 1;
}

笔者的公司在处理客户端NPC请求时,用了loadstring的方式对客户端传来的TABLE字符串进行解析,这样就存在以上的问题。

另外还有一部分请求在处理的时候,直接执行客户端请求的字符串,所以也有类似问题。

经过几种方案的测试,最终选择了使用检查编译后指令的方式,彻底解决这个问题。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值