C++代码安全增强与标准注解语言SAL
2010-11-11 15:21:55 来源:WEB开发网从Visual Studio 2005开始编译程序时就会遇到很多warning C4996警告。虽然没有错误但是这个警告估计还是让很多人不爽。MSDN上关于此警告有说"为了支持新的、更安全的函数,否决了某些 CRT 和标准 C++ 库函数,如果出于安全原因使用了否决的 MFC 或 ATL 函数,也可能发生 C4996"。以此为切入点来聊聊微软从Visual Studio 2005开始引入的一项针对程序安全性的新技术SAL(Standand Annotations Language),SAL就是更安全的函数的基石。
传统的代码安全性更加注重运行时程序正确性的保证,更有甚至者防御性的代码几乎占了整个代码的一多半,当然这是好的习惯但为此开发人员也浪费了大量精力和时间,而且在编写代码的逻辑时考虑安全性防御代码会或多或少的打断原本的设计思路,对程序开发人员来说这是安全性、稳定性的代价之一。C\C++语言本身对代码的安全性没有多少假设,这完全依赖开发人员的自觉和严格的代码检查。从另一个角度来看代码安全可以从两个层次上来对待"静态和动态“,静态是指代码在编译时发现更多的问题由编译器或者语法检查器这类工具来发现问题;动态是指在代码中由开发人员自己编写检查代码。相对动态方式来说静态方式更易于早些发现问题,从解决Bug的成本来说越早发现这个Bug就越廉价。SAL应运而生用来以静态方式解决代码安全性问题。
微软官方文档里并没有把SAL放到更加重要的位置,以至于我去找相关信息的时候难以轻松的理出头绪。目前看来SAL只是问题的解决方案和手段并没有独立为一种标准。微软不仅为CRT库函数提供了安全版本也为Window API提供了安全版本。CRT库函数的安全版命名规则为原有函数名加上"_s"后缀,如strcpy的安全版本为strcpy_s,返回值类型、参数个数个类型都未做变更只是加上了SAL修饰。从语法角度上来看SAL其实就是用于被编译器等工具识别的元语言。接下来看看strcpy在源文件中的定义
_Check_return_wat_ _CRTIMP_ALTERNATIVE errno_t __cdecl _strset_s(_Inout_z_cap_(_DstSize) char * _Dst, _In_ size_t _DstSize, _In_ int _Value); __DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_1(errno_t, _strset_s, _Deref_prepost_z_ char, _Dest, _In_ int, _Value) __DEFINE_CPP_OVERLOAD_STANDARD_FUNC_0_1(char *, __RETURN_POLICY_DST, __EMPTY_DECLSPEC, _strset, _Inout_z_, char, _Dest, _In_ int, _Value) #if __STDC_WANT_SECURE_LIB__ _Check_return_wat_ _CRTIMP_ALTERNATIVE errno_t __cdecl strcpy_s(_Out_z_cap_(_SizeInBytes) char * _Dst, _In_ rsize_t _SizeInBytes, _In_z_ const char * _Src); #endif __DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_1(errno_t, strcpy_s, _Deref_post_z_ char, _Dest, _In_z_ const char *, _Source) __DEFINE_CPP_OVERLOAD_STANDARD_FUNC_0_1(char *, __RETURN_POLICY_DST, __EMPTY_DECLSPEC, strcpy, _Pre_cap_for_(_Source) _Post_z_, char, _Dest, _In_z_ const char *, _Source)
把上面用到的宏展开
#define _Check_return_wat_ _Check_return_ //在dll版本 #define _CRTIMP_ALTERNATIVE _CRTIMP #define _CRTIMP __declspec(dllimport) //在exe版本只简单的定义存在 #define _CRTIMP_ALTERNATIVE #define _Inout_z_cap_(size) _Pre_z_cap_(size) _Post_z_ #define _In_ _Pre1_impl_(_$notnull) _Deref_pre2_impl_(_$valid, _$readaccess) #define _Deref_prepost_z_ _Deref_pre_z_ _Deref_post_z_ #define _Inout_z_ _Prepost_z_ #define _Out_z_cap_(size) _Pre_cap_(size) _Pre_invalid_ _Post_z_ #define _In_z_ _Pre_z_ _Deref_pre_readonly_ #define _Pre_cap_for_(param) _Pre2_impl_(_$notnull, _$cap_for(param)) #define _Post_z_ _Post1_impl_(_$zterm) _Deref_post1_impl_(_$valid) #define _Pre_z_cap_(size) _Pre3_impl_(_$notnull, _$zterm,_$cap(size)) _Deref_pre1_impl_(_$valid)
#define _Pre3_impl_(p1,p2,p3) [SA_Pre(p1,p2,p3)]<BR>
#define _Deref_pre1_impl_(p1) [SA_Pre(Deref=1,p1)]<BR>
#define _Post_z_ _Post1_impl_(_$zterm) _Deref_post1_impl_(_$valid)<BR>
<BR>
#define __DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_1(_ReturnType, _FuncName, _DstType, _Dst, _TType1, _TArg1) \ extern "C++" \ { \ template <size_t _Size> \ inline \ _ReturnType __CRTDECL _FuncName(_DstType (&_Dst)[_Size], _TType1 _TArg1) \ { \ return _FuncName(_Dst, _Size, _TArg1); \ } \ } #define __DEFINE_CPP_OVERLOAD_STANDARD_FUNC_0_1(_ReturnType, _ReturnPolicy, _DeclSpec, _FuncName, _SalAttributeDst, _DstType, _Dst, _TType1, _TArg1) \ __DEFINE_CPP_OVERLOAD_STANDARD_FUNC_0_1_EX(_ReturnType, _ReturnPolicy, _DeclSpec, _FuncName, _FuncName##_s, _DstType, _SalAttributeDst, _DstType, _Dst, _TType1, _TArg1) #define __DEFINE_CPP_OVERLOAD_STANDARD_FUNC_0_1(_ReturnType, _ReturnPolicy, _DeclSpec, _FuncName, _SalAttributeDst, _DstType, _Dst, _TType1, _TArg1) \ __DEFINE_CPP_OVERLOAD_STANDARD_FUNC_0_1_EX(_ReturnType, _ReturnPolicy, _DeclSpec, _FuncName, _FuncName##_s, _DstType, _SalAttributeDst, _DstType, _Dst, _TType1, _TArg1) #define __DEFINE_CPP_OVERLOAD_STANDARD_FUNC_0_1_EX(_ReturnType, _ReturnPolicy, _DeclSpec, _FuncName, _SecureFuncName, _SecureDstType, _SalAttributeDst, _DstType, _Dst, _TType1, _TArg1) \ _CRT_INSECURE_DEPRECATE(_SecureFuncName) _DeclSpec _ReturnType __cdecl _FuncName(_SalAttributeDst _DstType *_Dst, _TType1 _TArg1); //输出的提示信息在这儿,没错就是它 #define _CRT_INSECURE_DEPRECATE(_Replacement) _CRT_DEPRECATE_TEXT("This function or variable may be unsafe. Consider using " #_Replacement " instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.") #define _CRT_DEPRECATE_TEXT(_Text) __declspec(deprecated(_Text)) #define __RETURN_POLICY_DST(_FunctionCall, _Dst) return ((_FunctionCall) == 0 ? _Dst : 0) #define __EMPTY_DECLSPEC
- ››增强用户的体验愉悦性和专注度:保持用户的游戏体验...
- ››增强 WebSphere Service Registry and Repository...
- ››增强的恶意软件检测
- ››增强webprint打印控件一次打印多份文档的方法
- ››增强Windows7右键 让操作更简单
- ››增强 WebSphere eXtreme Scale 的 xsadmin
- ››增强SQL Server 2008的可管理性
- ››增强网站安全性,data目录隐藏功能设置详解
- ››增强Exchange服务器的安全性
- ››增强型命令行 不错的系统辅助工具
- ››增强互动 酷我音乐盒新版听歌会友
- ››增强GridCtrl
更多精彩
赞助商链接