一种空指针引用的检测方法及检测装置
技术领域
本申请属于计算机软件领域,更具体地,涉及一种空指针引用的检测方法及检测装置。
背景技术
在当今各类计算机系统和应用软件的实现中,广泛的使用指针来访问系统和软件的各种资源和数据。然而软件的复杂度使得指针的使用极易发生错误。空指针引用就是指针使用错误的一种,它试图访问一个值为空的指针,即实际上没有指向任何资源和数据的指针。软件运行时若发生了空指针引用,即企图使用一个未指向任何有效资源和数据的指针,则软件的行为会变得不可预测。更严重的是,空指针引用可以被恶意攻击方所利用,从而获得用户系统的各种资源和数据的控制权,从而导致各种安全问题和隐私泄露问题。
目前,用于检测空指针引用的方案普遍存在以下问题:1)对上下文信息不敏感,当指针访问的需求来源于其他上下文时,无法有效判断该指针会否为空;2)对控制流信息不敏感,在软件内部有复杂的控制流程的情况下,缺乏有效判断单一指针在不同分支情况下是否为空的依据。
鉴于此,克服该现有技术所存在的缺陷是本技术领域亟待解决的问题。
发明内容
针对现有技术的以上缺陷或改进需求,本申请提供了一种空指针引用的检测方法及检测装置,其目的在于本申请的检测方法保留了控制流信息,在软件内部有复杂的控制流程的情况下,能够有效判断单一指针在不同分支情况下是否为空,同时,获取每个代码以及多个代码之间的上下文信息,当指针访问的需求来源于其他上下文时,可以有效判断该指针会否为空,从而检测出软件中可能发生空指针引用的地方,以提示软件开发者进行修改,避免空指针引用。
为实现上述目的,按照本申请的一个方面,提供了一种空指针引用的检测方法,所述检测方法包括:
获取多个源代码,对所述源代码进行转换,得到保留控制流信息的内部表示;
对所述多个源代码进行解析,获取每个源代码以及各源代码之间的上下文信息;
遍历多个源代码,基于所述内部表示和所述上下文信息,检测各源代码中是否存在空指针引用。
优选地,所述遍历多个源代码,基于所述内部表示和所述上下文信息,检测各源代码中是否存在空指针引用包括:
针对其中一个目标源代码进行检测时,通过所述上下文信息确定与目标源代码相关联的关联源代码,将目标源代码和关联源代码进行链接;
获取目标源代码中存在的指针,解析所述指针在目标源代码和关联源代码的使用情况,以在所述内部表示上追踪单一指针在各个使用点是否为空。
优选地,所述获取目标源代码中存在的指针,解析所述指针在目标源代码和关联源代码的使用情况,以在所述内部表示上追踪单一指针在各个使用点是否为空包括:
判断目标源代码中是否存在未访问语句;
若存在,判断当前语句中是否存在指针;
若存在,判断所述指针的值在当前语句中是否已经确定;
若所述指针的值在当前语句中没有确定,判断所述指针是否来源于关联源代码;
若是,则将所述关联源代码加载至所述目标源代码,再次执行判断所述指针的值在当前语句中是否已经确定的步骤。
优选地,所述判断所述指针的值在当前语句中是否已经确定之后还包括:
若所述指针的值在当前语句中已经确定,则判断所述指针的值是否可以为零;
若所述指针的值可以为零,则输出错误信息,以提醒所述指针为空。
优选地,所述判断所述指针的值是否可以为零之后还包括:
若所述指针的值不为零,则返回执行判断目标源代码中是否存在未访问语句的步骤。
优选地,所述判断所述指针是否来源于关联源代码之后还包括:
若否,则输出错误信息,以提醒所述指针为空。
优选地,所述获取多个源代码,对所述源代码进行转换,得到保留控制流信息的内部表示包括:
获取多个源代码,对所述源代码进行转换;
得到保留控制流信息的内部表示,其中,所述内部表示为静态单赋值形式。
优选地,所述检测方法还包括:
当检测到源代码中存在空指针时,将检测到的空指针反馈给开发者,并提供空指针的位置。
按照本申请的另一方面,提供了一种检测装置,所述检测装置包括转换模块、搜集模块和检测模块;
所述转换模块用于获取多个源代码,对所述源代码进行转换,得到保留控制流信息的内部表示;
所述搜集模块用于对所述多个源代码进行解析,获取每个源代码以及各源代码之间的上下文信息;
所述检测模块用于遍历多个源代码,基于所述内部表示和所述上下文信息,检测各源代码中是否存在空指针引用。
按照本申请的又一方面,提供了一种检测装置,包括至少一个处理器;以及,与所述至少一个处理器通信连接的存储器;其中,所述存储器存储有可被所述至少一个处理器执行的指令,所述指令被程序设置为执行本申请所述的检测的方法。
总体而言,通过本申请所构思的以上技术方案与现有技术相比,具有如下有益效果:本申请提供了一种空指针引用的检测方法及检测装置,所述检测方法包括:获取多个源代码,对所述源代码进行转换,得到保留控制流信息的内部表示;对所述多个源代码进行解析,获取每个源代码以及各源代码之间的上下文信息;遍历多个源代码,基于所述内部表示和所述上下文信息,检测各源代码中是否存在空指针引用。本申请的检测方法保留了控制流信息,在软件内部有复杂的控制流程的情况下,能够有效判断单一指针在不同分支情况下是否为空,同时,获取每个代码以及多个代码之间的上下文信息,当指针访问的需求来源于其他上下文时,可以有效判断该指针会否为空,从而检测出软件中可能发生空指针引用的地方,以提示软件开发者进行修改,避免空指针引用。
附图说明
为了更清楚地说明本申请实施例的技术方案,下面将对本申请实施例中所需要使用的附图作简单地介绍。显而易见地,下面所描述的附图仅仅是本申请的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。
图1是本申请实施例提供的一种空指针引用的检测方法的流程示意图;
图2是本申请实施例提供的一种空指针引用的检测方法的具体实现方式之一;
图3是本申请实施例提供的一种代码实例示意图;
图4是本申请实施例提供的一种检测装置的结构示意图;
图5是本申请实施例提供的另一种检测装置的结构示意图。
具体实施方式
为了使本申请的目的、技术方案及优点更加清楚明白,以下结合附图及实施例,对本申请进行进一步详细说明。应当理解,此处所描述的具体实施例仅仅用以解释本申请,并不用于限定本申请。
此外,下面所描述的本申请各个实施方式中所涉及到的技术特征只要彼此之间未构成冲突就可以相互组合。
实施例1:
参阅图1,本实施例提供一种空指针引用的检测方法,所述检测方法包括如下步骤:
步骤101:获取多个源代码,对所述源代码进行转换,得到保留控制流信息的内部表示。
其中,针对某个软件程序会存在多个源代码,例如,图3所示的main.c函数、bar.c函数和foo.c函数。
在本实施例中,对所述源代码进行转换,得到保留控制流信息的内部表示,其中,内部表示为计算机所能识别的语言,所述内部表示为静态单赋值形式,可以减小内存。
其中,控制流信息用于反映函数的运行顺序、过程或跳转,可以包括函数内部的条件语句或判断语句。
步骤102:对所述多个源代码进行解析,获取每个源代码以及各源代码之间的上下文信息。
在本实施例中,对所述多个源代码进行解析,获取每个源代码以及各源代码之间的上下文信息,其中,上下文信息包括每个源代码(例如,某个函数)内部同一参数的上下文信息,还包括不同源代码之间同一参数的上下文信息,通过上下文信息可以建立源代码之间的关联关系,以及,同一参数的关联关系。
步骤103:遍历多个源代码,基于所述内部表示和所述上下文信息,检测各源代码中是否存在空指针引用。
在本实施例中,依次遍历多个源代码,基于所述内部表示和所述上下文信息,检测各源代码中是否存在空指针引用,并输出检测结果。当检测到源代码中存在空指针时,将检测到的空指针反馈给开发者,并提供空指针的位置。
具体地,针对其中一个目标源代码进行检测时,通过所述上下文信息确定与目标源代码相关联的关联源代码,将目标源代码和关联源代码进行链接;获取目标源代码中存在的指针,解析所述指针在目标源代码和关联源代码的使用情况,以在所述内部表示上追踪单一指针在各个使用点是否为空。
结合图2,所述获取目标源代码中存在的指针,解析所述指针在目标源代码和关联源代码的使用情况,以在所述内部表示上追踪单一指针在各个使用点是否为空包括:
首先,判断目标源代码中是否存在未访问语句,若不存在,则结束检测流程,若存在,判断当前语句中是否存在指针,若当前语句中不存在指针若,则返回“判断目标源代码中是否存在未访问语句”的步骤,若当前语句中存在指针,则进一步判断所述指针的值在当前语句中是否已经确定;若所述指针的值在当前语句中没有确定,判断所述指针是否来源于关联源代码;若所述指针来源于关联源代码,则将所述关联源代码加载至所述目标源代码,再次执行判断所述指针的值在当前语句中是否已经确定的步骤,若所述指针不来源于关联源代码,则输出错误信息,以提醒所述指针为空。
若所述指针的值在当前语句中已经确定,则判断所述指针的值是否可以为零,若所述指针的值不为零,则返回执行判断目标源代码中是否存在未访问语句的步骤;若所述指针的值可以为零,则输出错误信息,以提醒所述指针为空。
区别于现有技术,本实施例的检测方法保留了控制流信息,在软件内部有复杂的控制流程的情况下,能够有效判断单一指针在不同分支情况下是否为空,同时,获取每个代码以及多个代码之间的上下文信息,当指针访问的需求来源于其他上下文时,可以有效判断该指针会否为空,从而检测出软件中可能发生空指针引用的地方,以提示软件开发者进行修改,避免空指针引用。
为了更清楚地说明本实施例的检测方法的实现过程,以图3所示的代码为例,举例说明本实施例的检测方法的实现过程。在图3的左半部分,给出了foo函数中静态单赋值形式的内部表示的部分内容:在初始化赋值后,lcl_p和lcl_q的值变成了版本1(即lcl_p的取值为lcl_p1,lcl_q的取值为lcl_q1);表示在条件语句成立的条件下(即val==0),lcl_p和lcl_q的值被更新成了版本2(即lcl_p的取值为lcl_p2,lcl_q的取值为lcl_q2);在条件语句结束后,lcl_p和lcl_q的值成了版本3,即此时lcl_p和lcl_q的值可能是版本1或者版本2(表示为Φ(lcl_p1,lcl_p2))。由此,静态单赋值形式的内部表示保留了源代码上的控制流信息。
在图3中,展示了main.c、foo.c和bar.c在空指针检测中有关联性的部分代码,其中,main.c、foo.c和bar.c来源于源代码。在分别转换为静态单赋值形式的内部表示,并完成上下文信息搜集后,其中,所执行的空指针引用的检测过程如下:
首先,检测bar.c文件,在bar.c文件的bar函数的内部,当前语句中发现了指针ptr_p的引用(箭头1所指的语句处),通过在bar函数内部的上下文查找,检测到该指针实际是bar函数的参数,即该指针来源于其他函数,于是通过函数调用关系(其中,调用关系是上下文信息的一部分)查找,找到bar函数被调用的地方(箭头2所指向的语句处),即foo.c文件的foo函数内,于是加载foo函数的静态单赋值形式的内部表示和上下文信息,由此,确定bar函数中的指针ptr_p,即foo函数的lcl_p,lcl_p在此处的值为lcl_p3,由于lcl_p3有两个可能的赋值来源,lcl_p3可能等于lcl_p1,lcl_p3也可能等于lcl_p2,需要检测部分分支的赋值来源。
在foo函数中,检测到条件语句((如箭头3所指示的语句))与指针ptr_p的取值有关,同时检测到该条件语句成立的条件依赖于val的取值,而val是foo函数的参数(箭头4),通过函数调用关系查找,检测到foo函数在main.c文件的main函数内被调用了两次。
选择其中一个调用,箭头5所标识的调用(另一处虚线和箭头5所标识的调用处理相同,不再赘述),将main函数的上下文信息和静态单赋值形式的内部形式加载后,检测到foo在此处的调用的实际参数是全局变量g_val,通过全局变量的查找,确定g_val的值是10(箭头6),由此可以判断foo内的条件表达式并不成立,因而此时lcl_p的值并不等于lcl_p2。于是,选择另一条支路进行查找(箭头7),发现lcl_p1的值就是在foo函数内部定义的,由此bar调用的lcl_p的值来源于lcl_p1,即lcl_p的值为0,即,bar函数中的ptr_p为0,从而可以断定箭头1所标识的语句发生了空指针引用。输出控制针引用的错误提示,报告bar当前语句的指针ptr_p发生了空指针引用,同时,提供检测过程所经历的过程信息,从而帮助开发者理解该错误信息,该过程信息包含了foo.c文件的foo函数和main.c文件的main函数的关联调用点,及条件成立与否的依据来源。
实施例2:
基于前述实施例1的检测方法,本实施例提供一种检测装置,该检测装置可以实现实施例1的检测方法,如图4所示,所述检测装置包括转换模块、搜集模块和检测模块。
在实际应用场景下,所述转换模块用于获取多个源代码,对所述源代码进行转换,得到保留控制流信息的内部表示;所述搜集模块用于对所述多个源代码进行解析,获取每个源代码以及各源代码之间的上下文信息;所述检测模块用于遍历多个源代码,基于所述内部表示和所述上下文信息,检测各源代码中是否存在空指针引用。
具体地,所述检测模块包括信息链接模块、指针使用检测模块和错误报告模块,其中,针对某个源代码进行空指针引用检测时,信息链接模块用于对源代码进行链接,以获取所可能用到的其他上下文信息和静态单赋值形式的内部表示。指针使用检测模块用于依据上下文信息,在静态单赋值形式的内部表示上追踪单一指针在各个使用点是否为空。错误报告模块用于将检出的空指针引用反馈给软件开发者,提供软件中可能发生空指针引用的确切位置信息。
关于检测装置的具体实现过程可以参阅实施例1,在此,不再赘述。
实施例3:
请参阅图5,图5是本申请实施例提供的一种检测装置的结构示意图。本实施例的检测装置包括一个或多个处理器41以及存储器42。其中,图5中以一个处理器41为例。
处理器41和存储器42可以通过总线或者其他方式连接,图5中以通过总线连接为例。
存储器42作为一种基于检测方法的非易失性计算机可读存储介质,可用于存储非易失性软件程序、非易失性计算机可执行程序以及模块,如实施例1中的检测方法以及对应的程序指令。处理器41通过运行存储在存储器42中的非易失性软件程序、指令以及模块,从而执行检测方法的各种功能应用以及数据处理,实现实施例1的检测方法的功能。
其中,存储器42可以包括高速随机存取存储器,还可以包括非易失性存储器,例如至少一个磁盘存储器件、闪存器件、或其他非易失性固态存储器件。在一些实施例中,存储器42可选包括相对于处理器41远程设置的存储器,这些远程存储器可以通过网络连接至处理器41。上述网络的实例包括但不限于互联网、企业内部网、局域网、移动通信网及其组合。
关于检测方法请参照图1~图3及相关的文字描述在此,不再赘述。
值得说明的是,上述装置和系统内的模块、单元之间的信息交互、执行过程等内容,由于与本申请的处理方法实施例基于同一构思,具体内容可参见本申请方法实施例中的叙述,此处不再赘述。
本领域普通技术人员可以理解实施例的各种方法中的全部或部分步骤是可以通过程序来指令相关的硬件来完成,该程序可以存储于一计算机可读存储介质中,存储介质可以包括:只读存储器(Read Only Memory,简写为ROM)、随机存取存储器(Random AccessMemory,简写为RAM)、磁盘或光盘等。
本领域的技术人员容易理解,以上所述仅为本申请的较佳实施例而已,并不用以限制本申请,凡在本申请的精神和原则之内所作的任何修改、等同替换和改进等,均应包含在本申请的保护范围之内。