(计算机软件与理论专业论文)cc程序中类型转换的安全性研究.pdf_第1页
(计算机软件与理论专业论文)cc程序中类型转换的安全性研究.pdf_第2页
(计算机软件与理论专业论文)cc程序中类型转换的安全性研究.pdf_第3页
(计算机软件与理论专业论文)cc程序中类型转换的安全性研究.pdf_第4页
(计算机软件与理论专业论文)cc程序中类型转换的安全性研究.pdf_第5页
已阅读5页,还剩45页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

摘要 本论文主要研究a c + + 中静类型转换,特别越隐式类型转换的静态安全性检 爨。逶i 妻分辑冬数据类鍪稳耱浚,磁突它翻之瓣不安全戆转换,禳掇产生壤铡遗 荦亍了分类,借鉴文法盼表述形式对各类安全漏溺遴行了抽象描述,并讨论了其它 形式的描述形式,从而总结出同类型非安全转换间的共性,给出了可行的检测方 法。结合抽象语法树、程序分析模块所提供的信恩、使用g a s t a 的提供的接口,遍 历抽象语法树的程净上,设计并实现了一个简单的类型检查器。此外,本文还讨 论。 安全攘式与程痔分辑嚣大模块缭台送孬安全憋稔溺戆遮题。 关键词:隐式类型转换安全漏洞抽象语法树稷序分析 a b s t r a c t d e t e c t i n gm e t h o d so ft y p ec o n v e r s i o ns a f e t y , e s p e c i a l l yi m p l i c i tt y p ec o n v e r s i o n s s a f e t yo fc c + + p r o g r a mi ss t u d i e si nt h i sp a p e r u n s a f ec o n v e r s i o n sa r er e s e a r c h e db y a n a l y z i n gv a r i o u sd a t at y p e sa n dc l a s s i f i e da c c o r d i n gt o t h e g e n e r a t i o nm e c h a n i s m a b s t r a c td e s c r i p t i o n so fv a r i o u ss a f e t yv u l n e r a b i l i t i e sa r eg i v e na n do t h e rd e s c r i p t i o n m e t h o d sa r ed i s c u s s e d c o m m o n n e s so fu n s a f et y p ec o n v e r s i o n si ss u m m a r i z e da n d f e a s i b l e d e t e c t i n g m e t h o d sa r e g i v e n w i t h a b s t r a c t s y n t a x t r e e sa s e q u i v a l e n t p r e s e n t a t i o no f s o u r c ep r o g r a ma n dd i s p o s a lf u n c t i o n sb o u n dt op r o g r a mo f t r a v e r s i n g a b s t r a c t s y n t a xt r e e s ,as i m p l et y p e c h e c k e ri s d e s i g n e d a n d i m p l e m e n t e db y c o m b i n a t i o no fi n f o r m a t i o ng i v e n b yp r o g r a ma n a l y s i sm o d u l e b e s i d e s ,s o f t w a r es a f e t y d e t e c t i n g m e t h o d sw i t hc o m b i n a t i o no fs a f e t ym o d em o d u l ea n dp r o g r a ma n a l y s i s m o d u l ei sd i s c u s s e di nt h i sp a p e r k e y w o r d s : i m p l i c i tt y p e c o n v e r s i o n s s a f e t yv u l n e r a b i l i t y a b s t r a c t s y n t a x t r e e p r o g r a ma n a l y s i s 创新性声明 y 5 8 3 4 2 1 本人声明所呈交的论文是我个人在导师指导下进行的研究工作及取得的研究 成果。尽我所知,除了文中特别加以标注和致谢中所罗列的内容以外,论文中不 包含其他人已经发表或撰写过的研究成果;也不包含为获得西安电子科技大学或 其他教育机构的学位或证书而使用过的材料。与我一同工作的同志对本研究所做 的任何贡献均已在论文中做了明确的说明并表示了谢意。 本人签名i = i 期:c 抄t ,眵,f ) , 关于论文使用授权的说明 本人完全丁解西安电子科技大学有关保留和使用学位论文的规定,即:研究 生在校攻读学位期问论文工作的知识产权单位属西安电子科技大学。本人保证毕 业离陵后,发表论文或使用沦文工作成果时署名单位仍然为西安电子科技大学, 学眨有权保留送交论文的复印r ,允许查阅和借阅论文:学校可以公m 论文的全 部或部分内容,可以允许采用影印、缩影或其他复制手段保存论文。( 保密的沦文 在解密后遵守此规定) 本人签名:,土翌:! :丝 同期 导师签名型悭 山d 函, 同期:艘,! ! 窒 第一章绪论 1 1 研究背景 第一章绪论 本文工作源自于“十五”预研课题“软件安全性故障模式分析”。该课题主要 面向军事电子信息系统,旨在研制出一个基于静态分析的软件系统安全检查工具。 随着网络技术的发展和自由软件的广泛使用,软件的安全,特别是军事领域 软件的安全已越来越受到人们的重视,它已经成为影响计算机安全的最大问题之 一。由于计算机的安全性隐患( 包括无意的和人为的) 大量存在于软件系统中, 如系统入侵、信息窃取、病毒、以及由于程序设计语言自身问题造成的各种安全 漏洞等,使得软件通常不够健壮,导致软件在使用阶段会发生意想不到的软件故 障,从而造成重大损失。 对于自主开发的软件,主要通过测试的方法检查所有可能的不安全因素。这 需要对软件的功能、特性等具有深刻了解,并且根据软件特性设计完备的测试集。 显然这种动态测试的方法并不适用于使用可重用软件的情况。因此,如何能在静 态( 不运行) 时尽量检测出软件的安全性问题,避免不必要的损失,成为当前计 算机安全领域中需要研究的一个重要课题。 由于军事应用领域中要求软件系统具有很高的安全性,软件系统安全性分析 工具可以被广泛地应用于军事应用领域中的软件分析,以提高军事应用软件的安 全性。在研制工具过程中我们所研究的组方法,具有一定的普遍性,对其它相 关工作,如逆向工程、遗产继承等均具有理论和实际指导意义。 针对软件安全性这一重要问题,许多学者提出了不同的解决方式。如早期的 基于程序逻辑中的公理和推理规则的形式化验证方法二定理证明【1 8 a 9 4 】【o w 89 2 1 ( t h e o r e mp r o v i n g ) ,它也是出现最早的方法;八十年代初e c l a r k e 等人 。“8 5 1 【h o 。 9 7 m i l 9 2 1 提出的种基于自动机理论的模型检验( m o d e l c h e c k i n g ) 的方法,它列 举一个系统能够处于的所有可能状态,检查每个状态是否违反由用户制定的规则 和条件,并根据分析结果报告导致不合法状态的步骤。这也是种形式化的方法, 用于验证程序的正确性;1 9 9 7 年卡奈基梅隆大学的g e o r g ec n e c u l a l n e c 9 7 1 提出的 携带证明的( p r o o f - c a n t i n gc o d e ,p c c ) 方法,p c c 要求在代码中附加安全属性 的详细证明,然后通过一个证明检查器来验证所有的安全属性;由于软件的规模 越来越大,目前主流的验证软件安全性的方法是基于程序分析的安全性检查,它 已成为该领域研究的热点。 2 c c + + 程序中类型转换的安全性研究 1 2 解决问题的总体方案 不同的安全性分析方法的区别在于程序分析方法和安全性规则的内容不同。经 过分析和比较,我们发现基于程序分析的安全性检查可适用于对大规模程序的分 析,这种方法具有较高的分析效率和可扩展性。我们将主流的安全性分析方法归 结为一个普遍适用的框架( 见图1 1 ) ,此框架的特点在于,它将与安全相关的具 体模式从程序分析中剥离出来,从而以不同的方法解决最适于解决的问题。 图1 1 简化的安全性分析模型 程序分析是软件安全性检查的基础,根据不同的安全漏洞和对应的安全模式, 程序分析可以是在词法、语法、语义的任何级别上进行。程序分析器的研究内容 包括:传统的语法分析、数据流分析、控制流分析;传统分析方法向面向对象程 序设计语言的扩充;跨过程的程序切片和支持面向对象的分层切片等。这也正是 我们现阶段的工作,分析的对象是广泛使用的c c + + 语言编写的程序。 1 3 论文的主要工作 随着计算机的广泛应用,人们对软件系统的依赖程度与日俱增。 因为c c + + 是编写系统程序的主流语言,c ,c + + 语言在多个领域得到了广泛的 应用,同时c c + + 由于其自身的语言特性,在提供给程序员对系统底层( 如对内 存,外设) 灵活的控制能力的同时,也带来了一些潜在的安全性问题( 如指针的 错误使用,会带来内存漏洞) 。本文所作的主要工作是:分析c c + + 程序设计语言 中的类型机制,特别是因其不严格的类型转换机制所带来的安全隐患。构建其相 第一章绪论3 应操作的安全性规则,通过与本课题所设计的程序分析器相结合,完成此类问题 的程序自动检测。 本文的安排如下: 第一章为绪论;第二章提出软件安全模式的概念并具体阐述构建软件安全模 式的思想,同时对程序分析部分做简要介绍;第三章主要阐述c c + + 中类型转换机 制并构建其相应的安全性规则;第四章讲述类型检查器的具体实现过程:通过在 a s t 节点上捆绑处理函数,达到安全规则与程序分析器的结合,最终完成此类问题 的程序自动检测。 第二章软件安全模式 2 1 安全模式 第二章软件安全模式 2 1 1 安全模式 常见的与安全模式相关的概念有:软件安全性( s o f t w a r es a f e t y ) 、软件可靠性 ( s o f t w a r er e l i a b i l i t y ) 、软件安全性( s o f t w a r es e c u r i t y ) 等。可靠性与安全性( s a f e t y ) 是很容易混淆的一对概念。这两个概念常为人们所混用。但随着软件开发理论的 完善,它们逐渐从概念上独立起来。 可靠性常用来定义“系统在特定的环境条件、特定的时间段内完成其预设功 能的概率”。安全性则用来表示“已有的环境使得系统的失误( 危险) 不发生的概 率”,并不关心其是否达到了预先设计的功能。更通俗的来讲,可靠性需求更多的 是与系统的故障“相关,而安全性需求则更多的是与系统的失误相关噪:可靠 性与每个软件错误( 口r 加,) 相关,而安全性只与那些会导致真正的系统危险行为发 生的危险( h a z a r d ) 相关。并不是所有的软件错误都会产生问题,同时,与设计规范 一致的软件也并不能保证就是安全的。实际情况是,即便严格按照预设步骤操作, 也就是说肯定没有故障,但最终也是有可能产生一些异常的问题。 s a f e t y 和s e c u r i t y 的意思相近当容易区分一些。两者关注的都是危险( h a z a r d ) 。 不同的是s a f e t y 更加关注针对系统生命或特性的威胁,因此其研究重点在系统设 计中会导致危险发生的缺陷上;而s e c u r i t y 则更加关注信息交互的正确性、完整性 及保密性,因此对其的研究重点是在对保密信息的非法访问上,而不是去预防更 一般的怀有恶意的行为上。 本文安全模式概念中的安全性,指的s a f e t y ,而不是s e c u r i t y 。构建安全模式 的目的是通过对安全漏洞进行形式化的描述从而设计出良好的安全性分析工具。 2 1 2 安全模式的组成 程序代码编写的错误是软件安全漏洞产生的重要原因之一。而程序设计语言 本身所固有的特性,如c c 十+ 程序设计语言中对数组、指针无自动的边界检查( 这 也正是危害广泛的缓冲区溢出漏洞产生的一个重要原因) ,决定了许多错误无法在 编译阶段被发现;同时随着程序规模的扩大,状态空间急剧增大,安全漏洞也表 现的越来越复杂。因此我们引入静态检测来解决这个问题,它可以在不运行程序 6 c 圮抖程序中类型转换的安全性研究 的情况下进行分析,相对于动态检测:( 1 ) 它明确分析对象为源代码而不是更抽象 的系统描述:( 2 ) 其目标不是证明源代码或者系统设计符合特殊的安全策略,而是 发现可能的不安全因素。 由此,程序源代码与不安全因素就作为了我们最主要的分析对象一一程序源 代码由用户来提供,是已知的;不安全因素,也即源代码中的安全漏洞,是待检 测的,是未知的。因而解决问题的关键就集中在确定安全漏洞上。 漏洞的形态纷繁复杂,而形式化描述的方法借助于严格的数学概念和符号来 进行说明,然后经过逐步求精及变换,最终实现代码。通过它对问题的抽象描述, 可以清晰的说明问题的本质,从而很大的提高最终开发的产品质量以及效率,减 低反复操作带来的成本。 本课题所最终的成果除软件自动检测工具外,同时安全模式部分分析得出的 对诸多出现频率高、危害大的程序错误( 安全漏洞) 的分析和描述,对于程序开发 人员来讲也是一份很有用的参考手册,从这个角度考虑,采用形式化的方法: ( 1 ) 形式化的方法可以更深刻的揭示安全软件的需求及要求; ( 2 ) 形式化的方法大多采用数学符号及相关的运算来描述,可以减少二义性 和误解释的可能性。 除此之外,在安全模式设计过程中采用形式化的方法,可以保证程序设计过 程中的求解序列之间逻辑关系的正确性,这样最终得到的程序也可以保证是正确 的。通过这种方法产生的程序可靠性也是很高的。 2 1 3 安全漏洞的分类 程序中的安全漏洞形式多样、种类繁多。针对每一个漏洞进行分析、分别处 理的方法显然是不切实际的,但如果透过其具体的表现形式分析其产生的机理, 将会发现,实际上形态上各异的程序错误很可能是由于同一个原因产生的。 下面是常见的数组越界和字符串操作溢出的一种情况: 定义一个含n 个成员的整形数组:i n t a n ,对a 泐 伽;叻的操作将引起 数组越界; 假设有如下一段程序: i n tm a i n ( i n ta r g c ,c h a r “a r g v ) c b a r b u 9 2 5 6 :定义一个长度为2 5 6 的字符串变量; s t r c p y ( b 西a r g v 1 ) ; ) 该程序将拷贝a r g v 1 至l jb u f 中,使用了s t r c p y 函数,并且没有做任何的 别界检查。如果此时传入的a r g v 1 是- 个很长的量( 大于2 5 6 ) ,那么这将 第二章软件安全模式7 覆盖到堆栈中b u f 后面的数据,造成缓冲区溢出。 上述两者有不同的表现形式,但经过分析,可以认为它们都是在向一个有定 长的区域中写数据时,忽略了边界检查,从而将一部分数据写入了未定义或者不 属于其定义范围的区域,造成程序的异常。从而对此类问题进行如下抽象: ( 1 ) 为每个待操作的缓冲区配备一堆整数: a l l o c a t e ds i z e ,i t s _ l e n g t h 。 a l l o c a t e ds i z e 表示已分配空间的大小,i t sl e n g t h 表示写入此空间数据的大 小: ( 2 ) 正确的数据操作应该满足:a l l o c a t e ds i z e 兰i t sl e n g t h 。否则,将视为非 法操作。 由此,不同形式的问题抽象为了同一类问题,可以进行统一处理。 最终,通过对众多的安全漏洞的统计、分析、研究及归类,确定了以下几大 类重点解决的问题: ( 1 ) 动态存储分配。包括使用已经释放的空间的指针或别名、对同一内存 问进行重复释放、释放动态申请的一段连续空间中的部分地址等。 ( 2 ) 存贮越界。包括数组、缓冲区等无边界检查而产生的隐患、变量表示范 围的越界等。 ( 3 ) 内存泄漏。包括释放动态申请的空间、由于空间释放的顺序不正确导致 的地址信息丢失而带来的泄漏问题、类的构造函数中申请了空间,而析 构函数中没有释放空间造成的泄漏等。 ( 4 ) 类型不一致。主要包括各种数据类型间的转换而带来的不安全性,如编 译器所默许的隐式类型转换等。 ( 5 ) 简单的控制流。包括死循环、冗余代码以及全局变量使用所可能带来的 控制流异常等。 2 2 安全模式构建的关键技术 在安全模式的总体构建中,有两个比较重要的问题: ( 1 ) 安全漏洞的描述方法; ( 2 ) 安全分析工具的实现框架。 前者是对问题的抽象描述,后者是具体的实现;前者更多的是要求在更高层 次上的抽象,且能够涵盖其所涉及到的相同、相似的类别;后者更多是在适用性、 可扩充性方面的要求。 本文所关注的安全的类型转换方面的关键技术有: f 1 ) 根据不同类别的非安全类型转换采用有区别的抽象描述方法。例如对于 8 c c + + 程序中类型转换的安全性研究 赋值操作采用了为操作变量直接添加属性的方法,进行安全转换判断。而在跟函 数相关的类型转换处采用了“文法+ 语义规则”和为变量直接添加属性的方法进 行描述: ( 2 ) 与程序分析模块的结合问题。有了安全规则后,紧接着需要做的就是获 取安全规则运算所需的各类信息。程序分析部分所提供的信息并不能保证这些需 要获取的信息都已求得,这就需要对a s t 进行深加工,也就是进行遍历、求得需 要的数据信息。 2 3 安全模式在本课题中的地位 安全模式与程序分析是整个静态安全性检查的两大组成部分。安全模式完成 安全漏洞的提取、分析、抽象及表示;程序分析完成对源代码的分析、信息过滤、 提取及计算。 程序分析的结果直接影响到与安全模式部分有机结合的程度:能否全面、高 效的完成程序漏洞的检测;而安全模式分析的结果则决定了对安全漏洞的描述的 正确性、准确性及完整性,从而也就决定了最终的自动分析器所能达到的功效。 第三章c ,c + + 中的类型转换9 第三章c c + + 中的类型转换 3 1c c + + 中的数据类型 数据类型( d a t at y p e ) 用来定义存储空间( 内存) 使用的方式。通过定义数据类 型,编译器从而得之如何创建一片特定的存储空间,以及怎样操纵这片存储空间。 数据类型可以是内部的或抽象的。内部数据类型是编译器本来就可以理解的数据 类型,直接与编译器关联。c 和c + + 中的内部数据类型几乎是一样的。而相反, 用于定义的数据类型是由程序编写者所创建的类型,作为一个类。一般被称为抽 象数据类型。 c 中的数据类型如下图: 型。 数据类型 ,糌型 1 字符型 擗划j 篆型 r 数组类型 构造类型结构体类型 【共用体类型 指针类型 图3 1 基本数据类型 c + + 中的类型以c 为基础进行了扩展。增加了布尔( b 0 0 1 ) 类型与抽象数据类 3 2c c + + 中的类型转换 类型机制是程序设计语言的核心。而类型转换则是将数据从一种类型的值映 射为另一种类型的值,不同类型之间允许进行类型转换。类型转换包含自动隐含 ( 也成为强制) 和显式的两种。前者由编译器自动完成,后者则需程序编写者进行 显式的说明。 第三章c c + + 中的类型转换 t e m p l a t e c l a s sa r r a y ( p u b l i c : a r r a y ( i n tl o w b o u n d , i n th i g h b o u n d ) a r r a y ( i n ts i z e ) ; t & o p e r a t o r ( i n ti n d e x ) ; 第一个构造函数允许调用者确定数组索引地范围,例如从1 0 到2 0 。它是一个 两参数构造函数,所以不能做为类型转换函数。第二个构造函数让调用者仅仅定 义数组元素的个数( 使用方法与内置数组的使用方法相似) ,不过不同的是它能做 为类型转换函数使用,从而可能产生很大的问题。 3 3 显式类型转换 c 语言提供了一种“强制类型转换”运算符,将一个类型的变量强制转换为 另一种类型。例如:o n 0 3 5 中“( i n t ) ”的作用是将浮点数3 5 转换为整形数。 此类转换的一般形式为:( 类型标识符) 表达式 ( c h a r ) ( 3 - 3 1 4 1 5 * x ) k 2 ( i n t ) ( ( i n t ) x + ( f l o a t ) 嘞 ( f l o a t ) 0 = 9 9 ) p 得到字符型数+ ,枣得到整型数 p 得到实型单精度数+ 显式转换实际上是一种单元运算。各种数据类型的标识符都可以用作显式转 换运算符。对一个变量进行显式转换后,得到一个新的类型的数据,原来变量的 类型并不改变。 c + + 语言由于兼容了c 语言,因而上述c 的特性在c + + 中得到了保留,仍属 于合法的语法规则。同时,标准c + + 对于类型转换进行了改进,增加了四个类型 转换运算符( c a s to p e r a t o r s ) :s t a t i c _ c a s t ,c o n s t c a s t ,d y n a m i c _ c a s t ,r e i n t e r p r e t c a s t 。 其中,s t a t i cc a s t 操作符完成相关类型之间的转换,例如从一个指针类型到另 一个指针类型,整形到枚举类型或者浮点型到整形等。r e i n t e r p e rc a s t 处理互不相 关的类型之间的转换,例如从整形到指针,或者从一个指针到另一个毫不相干的 指针类型。这种区分使编译器能对s t a t i cc a s t 做某种小的类型检查,并使程序员 能看清由r e i n t e r p e r e tc a s t 的存在所表明的更危险的类型转换。d y n a m i c 能从_cast 多态的虚基类强制到某个派生类或者兄弟类。s t a t i cc a s t 不检查被强制的对象。 1 2 c 圮+ + 程序中类型转换的安全性研究 添加了这些显式类型转换运算符后,可以认为相应的类型转换就是程序设计 者的意图,因此本文认为这些转换是安全,不需要进行类型转换的检测。 3 4 隐式类型转换 c 语言中,允许把c h a r 隐式转换为m f 和从s h o r t 隐式转换为d o u b l e ,因此当 把一个s h o r t 值传递给准备接受d o u b l e 参数值的函数时,依然可以成功运行。c 中许多这种危险的转换可能会导致数据的丢失,它们在c + + 中依然存在,包括加r 到s h o r t 的转换和d o u b l e 到c h a r 的转换。这些转换是语言本身的特性,而只有在 用户增加自己的类型时,才可以对类型的转换有更多的控制力,因为其可以选择 是否提供函数让编译器进行隐式类型转换。例如: m t a _ i n t ; f l o a taf l o a t ; a i n t = a _ f l o a t ; 将浮点数转换为整形,会丢失精度; af l o a t = a _ i n t ; 将整形数提升为浮点数 a f l o a t 2 f l o a t ( a _ i n t ) ; ) 程序第6 、7 行自动完成整形、浮点型数据之间的类型转换,而第8 行则显 式的将整形提升为浮点型。 允许不同类型之间进行类型转换虽然使得语言的使用更加灵活多变,但不加 注意的使用甚至滥用将会产生安全隐患:数据精度丢失、引起运算错误、程序异 常等。同时因为这类转换出现的频率较高,由其产生的隐患将会给系统,特别是 安全关键系统,带来很大的危害,应该尽量避免。下面重点讨论类型转换中的隐 式类型转换问题。 3 4 1 简单的隐式类型转换 简单的隐式类型转换指的是c c + + 语言的基本类型间通过简单的算术运算符 所进行转换。例如上文所给出的整型和浮点型相互转换的例子。 l 2 3 4 5 6 7 8 9 1 第三章c ,c + + 中的类型转换1 3 c + + 语言编译系统提供的基本数据类型的自动隐式转换规则如下: ( 1 ) 程序在执行算术运算时,低级的类型可以转换为高级的类型: ( 2 ) 在赋值表达式中,右边表达式的值自动隐式地转换为左边变量的类型, 并赋值给它; ( 3 ) 发生函数调用时,系统隐式地将实参转换为形参的类型后,赋值给形参; ( 4 ) 函数有返回值时,系统自动地将返回表达式的类型转换为函数类型后, 赋值给调用函数。 在以上情况下,系统会自动进行隐式转换。其中,算术运算的结构类型由一 组称作“普通算术转换”的规则确定( 附录c ) 当编译器发现程序中两个数据类型 不相容时、又不能自动完成隐式转换时,将出现编译错误。例如: i n t + p = 1 0 0 : 在这种情况下,编译程序将报错,为了消除错误,可以进行如下所示的强制 类型转换: i n t + p 。( i n t4 ) 1 0 0 i 这样就将整型数10 0 强制转换成指针类型。 从语言本身所提供的四条转换规则可以看出,只有在第一条转换规则时,所 完成的转换是安全的。在其它三种情况下,将可能产生非期望的结果,导致安全 漏洞的产生。 为了分析这些不安全的转换,首先研究安全的转换应该依照的规则。 c + + 中提供的基本数据类型有: c h a r 、s h o r t 、i n t 、u n s i g n e d 、f d 昭、u n s i g n e dl o n g 、f l o a t 、d o u b l e 、l o n g d o u b l e 。 它们的可表示范围如表格所示: 类型说明符可表示数的范围分配字节数 字符型c h a rc 字符集 口 基本整形加f- 3 2 7 6 8 3 2 7 6 7口口 短整形s h o r ti n t- 3 2 7 6 8 3 2 7 6 7口口 长整形l o n g i n t - 2 1 4 7 4 8 3 6 4 8 2 1 4 7 4 8 3 6 4 7口口口口 无符号型u n s i g n e d 0 6 5 5 3 5口口 无符号陡整形u n s i g n e dl o n g o 4 2 9 4 9 6 7 2 9 5口口口口 单精度实型f l o a t 3 4 e - 3 8q ,4 e + 3 8口口口口 双精度实型d o u b l e 1 1 7 e 3 0 8 l ,7 e + 3 0 8口口口口口口口口 表3 1 数据类型的表示范围 从安全的角度考虑,类型转换应该以不丢失数据精度为前提,根据上面每种 c c 抖程序中类型转换的安全性研究 类型的特性,它们之间安全的转换应如下图所示: 图3 2 安全的类型转换 其中,c h a r 、s h o r t 类型直接作为f 脚类型处理,f l o a t 类型直接作为d o u b l e 类 型处理。 由此可以归纳出以下几类非安全的类型转换: 3 4 1 1 有符号类型转为无符号类型 有符号的整型对象( s i g n e d 型) 可以转换为相应的无符号类型( u n s i g n e d ) ,当这 些转换发生时,实际的位模式并没有改变,但是数的解释改变了,例如: # i n c l u d e v o i dm a i n ( ) s h o r tf = 一3 : u n s i g n e ds h o r t “; c o u t ( u = i ) ; 其输出结果如下: 6 5 5 3 3 在这个例子中,定义了一个s i g n e d s h o r t 遍历i 且初始化为一个负数,按照类 型转换规则( 2 ) ,表达式( u = i ) 使i 在赋给u 之前转换为u n s i g n e ds h o r t 类型。但f 卅 型数据的值域并不完全包含在u n s i g n e d 型的值域以内,在强制的时候可能会发生 错误。拍 型数据把内存的最高位作为符号位,u n s i g n e d 型没有符号位,二者所占 内存位数相同。在i n t - - u n s i g n e d 转换时,泐的负数x 用2 n + x 代替( n 为内存位数) 。 加减法运算和乘法运算中,用2 n + x 代替x 运算,结果会是r * 2 n 加上原运算式的 第三章c c + + 中的类型转换 形式,如果原表达式的结果是非负的,转换为u n s i g n e d 型不会影响运算结果的表 示,这是产生正确结果的原因:但是在结果为负的时候将会发生错误。 相对来讲,上述这种情况发现起来还是很容易的,然而一旦它发生在程序的 其它复杂结构中,就变的很难被发现,例如在下面这段程序中: # i n c l u d e i n tm a i n ( ) i n t 口: d = s i z e o f ( c h a r ) ; i f ( - 1 s i z e o f ( c h a r ) ) p r i n t f ( ”一1 1 ”) ; r e t u r no ; ) 程序的意图是:由于一l 应小于s i z e o f ( c h a r ) ,所以输出:一1 1 :之所以会出现这个异常结果的原因是在逻辑比较中,s i z e o f 返回的 是“”s 0 即p d 类型的值( 与此类似的是指针减的结果是一个有符号的整形) ,而- 1 是 i n t 类型,比较时f 脚被自动转换成u n s i g n e d 类型,首位的符号位被当成数字位, 小数字变成了大的数字,造成错误的结果。 3 4 1 2 无符号类型型转为有符号类型 无符号的整形对象可以被转换为相应的有符号类型。但是如果无符号对象的 值的范围超出了有符号类型可表示范围,则这种转换会导致数据的误解释,例如: # i n c l u d e i n tm a i n ( ) s h o r t f ; u n s i g n e ds h o r t “2 6 5 5 3 3 ; c o u t ( i = “) “”; r e t u r no ; ) 其输出结果如下: 一3 1 6 c c + + 程序中类型转换的安全性研究 在此转换中,u 是一个u n s i g n e d s h o r t 对象,必须转换为一个有符号量而与表 达式i = u 的求值相符,由于它的值在s i g n e ds h o r t 中不能正常表示,所以数据被 误解为上述历示内容。 在基本类型的转换中,一旦违反了上述转换顺序,则该程序点处的数据将有 可能丢失精度。 3 4 1 3 浮点数类型的降格 由低级的数据类型转换为高级的数据类型,称为数据提升。而相反方向的转 换则称为降格。 浮点数的降格,即d o u b l e 转换为f l o a t 或d o u b l e 、f l o a t 转换成l o n g i n t 、s h o r t 型。当数据超过了目标类型的取值范围时,所得到的结果将是不确定的( 事实上它 们也是有规律的,只是系统给出的是一个往往让用户难以理解的数值,例如将实 数3 2 7 8 1 2 赋给整形变量f ,由于3 2 7 6 8 超过了整数可表示的最大值3 2 7 6 7 ,在内 存- 啦将3 2 7 6 8 存储为1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 的形式,它代表整数- 3 2 7 6 8 。如果输出 f 得一3 2 7 6 8 。若将3 2 7 6 9 5 9 赋给i ,输出整数i 的值得一3 2 7 6 7 ) 。 当浮点类型转换为整数类型时,浮点数的小数部分全部舍去,并按整数形式 存储,在转换过程中不发生舍入。例如一个m n 的数将转换为m ,而类似- m 1 1 转 换为- m 。 当由d o u b l e 型转换为f l o a t 型时,将去掉多余的有效数字,但按四舍五入来 处理。 当较长得整数转换为较短得整数时,其高位将被截去。例如l o n g 型数为4 个 字节,i n t 型为2 个字节,将l o n g 型赋值给拥r 型,只会将低字节内容传送过去, 这样就会有很大得误差产生,得到得值是原数据值以3 2 7 6 8 为模的余数。 下面是上述转换的一个具体例子。 第三章c c + + 中的类型转换 # i n c l u d e i n tm a i n ( ) d o u b l e a = 1 2 3 4 5 6 7 8 9 0 9 8 7 6 5 ; f l o a t6 ; l o n gc ; i n t f ! ,; b = a ;c = 口;i = a ;j = c ; p r i n t f f “a 2 1 f ,b 2 f ,c 2 i d ,i 2 d 2 d u ”,口,b ,c ,f ,力; r e t u r no ; 程序的输出结果是: 口21 2 3 4 5 6 7 8 9 0 9 9 b 2 1 2 3 4 5 6 7 8 9 0 6 2 ;c = 1 2 3 4 5 6 ;f = - 7 6 1 6 ;j = 一7 6 1 6 3 4 1 4 指针与引用的转换 一个指向任何对象类型的指针都可以赋值给类型为v o i d * 的变量,v o i d * 可以 赋值给另一个v o i d * ,两个v o i d * 可以比较相等与否,而且可以显式地将v o i d * 转换 到另一个类型。其它操作都是不安全的,因为编译器并不知道实际被指的是哪种 对象。因此,对v o i d * 做其它操作都将引起便起错误。使用v o i d * 时应该显式的将 它转换到某个指向特定类型的指针。例如: 1 :# i n c l u d e 2 :i n tm a i n ( i n t + p i 、 3 : 4 : v o i d * p v = p f ; 从i n t + 到v o i d + 的隐式类型转换 5 : i n t + p 6 = s t a t i c _ c a s t 0 v ) 显示转换回i n t + 6 :d o u b l e + p d l 2 s t a t i c _ c a s t p v ) ; 7 :d o u b l e + p d 22 p v : 8 :r e t u r n o : 9 :) 程序语句4 ,p v 指向了一个整型对象( 通过得到) 。而语句7 将这个指针转 换后赋给了变一。d 2 ,通过_ p d 2 进行的间接访问将是不安全的。去掉程序的语句5 、 6 ( 因为转换符s t a t i c _ c a s t 在是c + + 的关键词) ,剩下的部分在g c c 中可以完全通过 1 8 c c + + 程序中类型转换的安全性研究 编译,并且无任何警告。这也就说明类似语句7 的转换将可能引发安全隐患,应 该予以关注。 若不去掉语句5 、6 ,在高级编译器中( 如v c + + ) 运行该程序,同样会编译通过, 但很明显,语句7 仍然是非安全的。 一般来说,如果一个指针转换到与被指对象的实际类型不同的指针,使用后 一个指针将是不安全的。值得注意的是,一个指向派生类的指针( 或引用1 可以隐 式的转换为指向它的某个可以访问的无歧异性的几类的指针( 或引用) ,而指向函 数的指针或者指向成员的指针不能隐式的转换到v o i d * 。 3 4 1 5 布尔类型的转换 指针、整数和浮点值可以隐式地转换为b o o l 。非0 值转换为t r u e ,0 值转换 为黟l s e 。 布尔类型操作的关键是对于布尔值的不正确理解,而引起错误的 3 4 1 6 数组类型的转换 对于类型t ,t s i z e l ,就是“具有s i z e 个r 类型的元索的数组”a 元素的下标 从0 到j 赴e j 。 数组类型的隐式转换主要是从数组名到该数组的开始元素的指针的隐式转 换,特别是在c 中。例如: l :# i n c l u d e 2 :v o i dm a i n ( i n t + p 0 3 : 4 :c h a rv - “x i d i a n ”; 5 : c h a r * p = v ;隐式地从c h a r 转换到c h a r 6 : s t r l e n ( p ) ; 7 : s t r l e n ( v ) :隐式地从c h a r 转换到c h a r + 8 : 3 4 2 复杂的隐式类型转换 复杂的隐式类型转换指的是通过复杂的程序结构所实现的类型转换。 第三章c c + + 中的类型转换 3 4 2 1 函数调用 如前文所述转换规则( 3 ) 所示,当在函数调用时,系统会隐式地将实参转换为 形参的类型后,赋给形参。假设: 函数定义形式为:t y p e tf u n c t i o n ( t y p e 2v a r i a b l e r ) ; 函数调用形式为:v a t = f u n c t i o n ( t y p e 4v a r i a b l e ? ) ;其中v a r 的类型为t y p e 3 ; 函数返回值类型:t y p e 5r e t u m _ t y p e 。 如果t y p e 2 与t y p e 3 不相等,则v a r i a b l e 2 的类型将变为t y p e 2 。例如: 1 :f l o a ta d d 0 ) 2 :i n t x ,y ; 3 : 4 :r e t u r n ( x + y ) ; 5 :) 6 :m a i n ( ) 7 : 8 :f l o a ta ,b ,c ; 9 :c = a d d ( a ,6 ) ; 1 0 : 1 1 :) 通过函数调用,语句9 处将浮点类型的实参a , b 转化为符合形参声明的整数 类型,会导致数据精度的丢失。 另一种与此相类似的情形是函数返回值类型的不一致。即: t y p e 3 t y p e 5 ; c 语言中,凡不加类型说明的函数,一律自动按整型处理。这样也就允许了 函数调用类型和返回类型的不一致。丽c + 十语言有很严格的类型安全检查,不允 许上述情况发生。因而对此类的检查面向的是( 只) 针对c 的编译器。 3 4 2 2 构造函数 构造函数同样具有类型转换功能。 在实际应用中,当类定义中提供了单个参数的构造函数时,该类便提供了一 种将其他数据类型的数值或变量转换为用户所定义数据类型的方法。因此,可以 说单个参数的构造函数提供了数据转换的功能。下面通过一个例子进一步说明单 参数构造函数的类型转换功能。 c c + + 程序中类型转换的安全性研究 # i n c l u d e c l a s s a p u b l i c : a ( )m = 以 a ( d o u b l ef ) m = f ; v o i dp r i n t ( ) c o u t m 啦 ) 这个转换函数定义了由 到毪型掰劈舻2 2 _ f 3 i n 映射关系 第三章c c + + 中的类型转换 用来将一种类型的数据转换成为另一种类型。下面通过一个例子说明转换函数的 功能。 # i n c l u d e c l a s sr a t i o n a l p u b l i c : r a t i o n a l ( i n t 吐i n tn ) d e n = d : h u m = n : ) o p e r a t o rd o u b l e ( ) ;类型转换函数 p r i v a t e : i n td e n h u m ; ) ; r a t i o n a l :o p e r a t o rd o u b l e 0 r e t u r nd o u b l e ( d e n ) d o u b l e ( n u m ) ; ) v o i dm a i n ( ) r a t i o n a lr u ,; d o u b l ed = 4 7 : d + = ,: c o u t d = r v a l u e t y p e ) ) 一违背安全规则 l i n e 一= v i s i tl i n e ( n o d e t r ) o u t p u t ( “行,m t 处的从类型l v a l u e t y p e _ 至:0r v a l

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论