【摘要】 在安全领域,lua编程语言因为其小巧在众多工具上都作为插件开发语言,常见的有openresty,nmap等。因此笔者将会开辟一个Lua相关的系列文章,主要记录工作过程中一些领悟或者是一些踩过的坑,希望能够借此平台帮助到读者们。

0x00 背景

最近在写一段nginx+redis的代码,主要基于openresty,其中使用到了lua-resty-redis库。我平时写代码都比较小心,针对外部输入的值一般都会进行异常判断,大概的代码如下:

local redis = require "redis"
local cjson = require "cjson"
--[[省略部分代码]]
local ok, err = redis:get("key")
if not ok thenngx.log(ngx.ERR, '[ERROR]:', err)return
end
local data = cjson.decode(ok)

在decode这里出现了错误提示,但是ok并没有为空或者nil,不然代码是走不到这里来。
发现问题后,我们就在前面打印一下ok数据的类型吧,大概的代码如下:

ngx.log(ngx.ERR, 'ok type: ', type(ok))
if not ok then-- TODO
end

这个时候我们得到的结果是userdata,这个东西算是一种复杂结构体,一般都是跨语言产生的,比如ffi.C这些。当时我的思路大概也是这样,肯定redis存放的数据是二进制的,但是呀,存放什么数据都是我自己控制的,不可能有什么畸形数据,因此这一点也排除了。最后在自己查看中发现,其实就是这个key不存在。

0x01 分析

既然原因找到了,我们就去看看为什么会这样,主要通过阅读lua-resty-redis的源码:

local function _read_reply(self, sock)local line, err = sock:receive()if not line thenif err == "timeout" and not rawget(self, "_subscribed") thensock:close()endreturn nil, errendlocal prefix = byte(line)if prefix == 36 then    -- char '$'-- print("bulk reply")local size = tonumber(sub(line, 2))if size < 0 thenreturn nullendlocal data, err = sock:receive(size)if not data thenif err == "timeout" thensock:close()endreturn nil, errendlocal dummy, err = sock:receive(2) -- ignore CRLFif not dummy thenreturn nil, errendreturn dataelseif prefix == 43 then    -- char '+'-- print("status reply")return sub(line, 2)elseif prefix == 42 then -- char '*'local n = tonumber(sub(line, 2))-- print("multi-bulk reply: ", n)if n < 0 thenreturn nullendlocal vals = new_tab(n, 0)local nvals = 0for i = 1, n dolocal res, err = _read_reply(self, sock)if res thennvals = nvals + 1vals[nvals] = reselseif res == nil thenreturn nil, errelse-- be a valid redis error valuenvals = nvals + 1vals[nvals] = {false, err}endendreturn valselseif prefix == 58 then    -- char ':'-- print("integer reply")return tonumber(sub(line, 2))elseif prefix == 45 then    -- char '-'-- print("error reply: ", n)return false, sub(line, 2)else-- when `line` is an empty string, `prefix` will be equal to nil.return nil, "unknown prefix: \"" .. tostring(prefix) .. "\""end
end

从上面的源码可以看到,在读取redis服务器返回数据的时候,如果某些格式不正确,比如数据长度的字节小于0这样的异常情况,函数就会返回null,注意是null不是nil
这个null的定义来自ngx.null,这个东西可以追溯到其官方文档lua-nginx-module.

The ngx.null constant is a NULL light userdata usually used to represent nil values in Lua tables etc and is similar to the lua-cjson library’s cjson.null constant.

从上面描述看,ngx.null就是一个代表null的userdata结构,类似一个自定义的类,但是没有什么具体含义,同时文档里面也提到了类似的值还有cjson.null,以后小心被坑。

0x02 扩展

同时文档中还提到了,使用ngx.log对几个空值进行字符串打印的时候

  • nil会显示成“nil”,

  • 逻辑值会显示成“true”或者“false”,

  • ngx.null会被显示成“null”。

来源:华为云社区  作者:HuangJacky

Lua - 空值判断的几种情况相关推荐

  1. 怎么判断油烟净化器需要清洗?出现这三种情况,需要及时清洗!

    众所周知,由于工作环境复杂,油烟净化器在日常使用过程中需要经常清洁和维护.但是至于何时需要清洁油烟净化器,餐饮公司的许多朋友可能不知道.那么如何确定油烟净化器是否需要清洗呢?今天,天珑小编介绍三种情况 ...

  2. C++编程练习 计算一元二次方程组解判断是否测试过三种情况

    原题来自菜鸟教程 C++ 实例 - 求一元二次方程的根 实现方法相当简单 就是最基础的C语言程序 以下是菜鸟教程给的答案-- #include <iostream> #include &l ...

  3. python空值赋0_Python中的空值判断

    本文中所有代码均运行在Python 2.7上 在实际的工作当中,我们难免要与空值打交道,相信不少初学者都会写出下面的代码: if a is None: do something. else: do t ...

  4. optional空值判断_Java 8 Optional不仅用于替换空值

    optional空值判断 总览 在Java 8中,您可以返回Optional而不是返回null. 就像您在Java 7中所做的那样.这可能会有所不同,这取决于您是否倾向于忘记检查null还是使用静态代 ...

  5. if语句判断真假的几种情况

    在写二叉树的最后判断二叉树是否为空的时候遇到if语句的判断竟然跟想得不一样!于是深入地了解了下if语句的判断真假的几种情况,发现还真有点东西-(自己果然是菜鸡hhhhhhhh) 这个是书本上的 i = ...

  6. 进一步封装axios并调用其读取数据(吐槽~在安卓9.0以下或者IOS10.X以下手机端H5页面不支持,在这两种情况下的系统只能使用ajax或者原生js请求后台数据)

    注意!!!(修改于2020年7月18日) 在安卓9.0以下或者IOS10.X以下手机端H5页面不支持,在这两种情况下的系统只能使用ajax或者原生js请求后台数据 报错截图如下 报错内容: {&quo ...

  7. 2021-10-11 ! AVL树 及其平衡调整 四种情况 恋上数据结构笔记 (考过)

    b站有个up讲的很详细 https://www.bilibili.com/video/BV1xE411h7dd?from=search&seid=11383601726930144190&am ...

  8. sql中索引不会被用到的几种情况

    转载自  sql中索引不会被用到的几种情况 1.查询谓词没有使用索引的主要边界,换句话说就是select *,可能会导致不走索引. 比如,你查询的是SELECT * FROM T WHERE Y=XX ...

  9. Linux系统编程16:进程控制之进程终止以及终止进程的三种情况

    文章目录 (1)进程终止时的三种情况 (2)退出进程的方法 A:正常退出-exit和return的区别 B:异常退出 C:_exit()函数 (3)实践 (1)进程终止时的三种情况 一个进程结束了,无 ...

最新文章

  1. 安卓高手之路之java层Binder
  2. 【原创】基于ARM的流水灯仿真示例
  3. 用户控件如何控制ASPX页面的控件
  4. 任务调度之Quartz1
  5. 娄底二中高考2021成绩查询,2021年娄底高考状元名单公布,娄底高考状元学校资料及最高分...
  6. web---SSL/TSL
  7. T-SQL查询字符串的字节数和字符个数
  8. 精选JAVA毕业设计83套——源码+论文完整资源
  9. php安装libpng,安装php:configure: error: libpng.(a|so) not found解决办法
  10. Zedgraph 总结
  11. java 文档查看技巧
  12. 常用的统计抽样分布和正态总体的抽样分布
  13. 怎么把柱形图和折线图放在一起_Excel图表制作:柱形图和折线图的组合图案例...
  14. 小米公司开源 MIUI 6 第三方适配工具 『Patchrom』
  15. 知乎-知乎网站-复制文字-破解知乎复制
  16. SAP全球副总裁、中国区总经理李强,离职去向大家就不要猜了
  17. NAMD跑分子动力学模拟出现的一些问题(更新中)
  18. 分布式锁-Redis解决方案和Redisson解决方案
  19. srtm数据格式.hgt读取
  20. Java实现单点登录(SSO)方式

热门文章

  1. java最大最小距离算法缺点_java算法(蓝桥杯)- 算法提高 题目1 最大最小值
  2. java写的教育管理的项目_干货分享|推荐12款适合做Java后台管理系统的项目
  3. python语音播放文本_python将文本转化成语音并播放
  4. 鸿蒙系统 闹钟,华为鸿蒙2.0操作系统正式版
  5. python 折线图 尾部_Matplotlib 折线图plot()所有用法详解
  6. Nginx http 视频点播服务器搭建操作指南
  7. 贡献分选择结果——Teamwork
  8. Python 第一章 基础知识
  9. USACO / Factorials (简单模拟)
  10. textread读取记事本文件