一个小细节:Security Enhancements in the CRT

最近写点小程序,为了安全性,打算改写部分CRT函数成secure versions of run-time library routines。最初的想法是,对于这类函数,一般就是加上_s,有的需要加个参数就可以了。没什么其他的需要修改。前段时间改了一个程序,因为写的不是很标准,就出了一点小问题。拿一个来说说:

1
2
3
4
5
((_waccess(strVirName,0)) != -1)
{
	//ShowMessage(TEXT("There is a virus in here!"),TEXT("IsExist"));
	return true;
}

这样是一定会在改写成_waccess_s时出现问题的。最初我以为是_waccess_s的定义问题,查了下msdn,是下面这个样子:

1
2
3
4
5
6
7
8
int _waccess(
   const wchar_t *path,
   int mode
);
errno_t _waccess_s(
   const wchar_t *path,
   int mode
);

这两个函数在参数上没什么差别,貌似问题并不出在这里。看编译器并不在这里提示错误,但是最后逻辑一定会有错误。不过仔细看下类型,一个是int,一个是errno_t,这个不太一样。但是实际上你看下errno_t的定义就知道,其实这个是tpyedef int errno_t来的。好像程序分析到这里陷入到了僵局。不过注意到_waccess定义中有一句话:

Each function returns 0 if the file has the given mode. The function returns –1 if the named file does not exist or does not have the given mode; in this case, errno is set as shown in the following table.

从这句话看,我这原来的程序在这里没有任何问题,修改后应该也不会出现什么问题,但是实际上却不然。在_waccess_t的返回值中是这么提到的:

Each function returns 0 if the file has the given mode. The function returns an error code if the named file does not exist or is not accessible in the given mode. In this case, the function returns an error code from the set as follows and also sets errno to the same value.

这就说明,实际上在_wacess_s中-1并不能在这里判定文件不存在,因为在_waccess_s中不会出现这个返回值,仅会出现EACCES、ENOENT、EINVAL三者之中的一个。因此实际上将最初语句中的-1替换为ENOENT就可以解决这个问题了。

实际上,这个问题也是很有提示作用的,这说明在写程序的时候,还是需要用些定义的了东西,不仅在移植的时候方便,而且更新的时候不需要具体的调整参数了,避免一些莫名其妙的错误。

此条目发表在 技术交流 分类目录,贴了 , , 标签。将固定链接加入收藏夹。

一个小细节:Security Enhancements in the CRT》有 2 条评论

  1. KC Windows XP Firefox 3.0.11 说:

    厄,整个字符串操作函数都有安全版的,不过MS现在人用的不多……

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

:zzz :stop :stone :smile :oops: :love :hurt2 :hurt :hit :hide :freeze :evil2 :cry :blind :angel 注意: 评论者允许使用'@user空格'的方式将自己的评论通知另外评论者。例如, ABC是本文的评论者之一,则使用'@ABC '(不包括单引号)将会自动将您的评论发送给ABC。使用'@all ',将会将评论发送给之前所有其它评论者。请务必注意user必须和评论者名相匹配(大小写一致)。