现在的位置: 首页 > 综合 > 正文

13.使用更安全CRT函数(C语言)

2013年10月15日 ⁄ 综合 ⁄ 共 4237字 ⁄ 字号 评论关闭

起因

     1 gets()
  gets()由于不能进行拷贝了的buffer的size指定、所以有BufferOverflow的问题。使用代替函数进  行Buffer的Size指定,或者使用fgets()。
     2 scanf()
      不使用scanf()、把scanf_s()、sscanf()作为代替函数来使用。
  3 strcpy()
  strcpy()不检查copy先的Buffer的Size,所以有Buffer Overflow问题。请务必使用按照strncpy_s()、strcpy_s()、strncpy()等不同环境

而准备的安全度很高的函数。
  另外、即使是使用安全度很高的函数,由于用法方面的原因,也可能发生Buffer Overflow,请注意如下几点。不要在strcpy_s()、

strncpy_s()进行Buffer Size的誤指定。
  4 strcat()
  strcat()不会进行检查 Buffer的长度检查,所以有BufferOverflow问题。请使用按照strncat_s()?、strcat_s()、strncat()等环境而准

备的安全度很高的函数。另外、即使是使用安全度很高的函数,由于用法的原因也会产生BufferOverflow。所以请注意如下几点。 strcat_s()

、strncat_s()不进行Buffer长度的誤指定。
  5 sprintf()
  使用按照sprintf_s()、 snprintf()等的环境分别准备的安全度很高的函数。另外、非常古老的UNIX/Linux系统中、特别是Linux的libc4

的古老版本中的 snprintf()等的BufferOverflow实际上是不能避免的,所以请注意

        936  3A7 00034D59 lstrcat
        937  3A8 00034D59 lstrcatA
        938  3A9 00010FC2 lstrcatW
        939  3AA 00030D64 lstrcmp
        940  3AB 00030D64 lstrcmpA
        941  3AC 0000AA5C lstrcmpW
        942  3AD 0000BB31 lstrcmpi
        943  3AE 0000BB31 lstrcmpiA
        944  3AF 0000AA26 lstrcmpiW
        945  3B0 0000BE91 lstrcpy
        946  3B1 0000BE91 lstrcpyA
        947  3B2 0000BAF4 lstrcpyW
        948  3B3 000101A1 lstrcpyn
        949  3B4 000101A1 lstrcpynA C标准函数没有这个,但有strncpy
        950  3B5 0000BA7F lstrcpynW lstrcpyn( str, strBuffer, 4 );
        951  3B6 0000BE46 lstrlen
        952  3B7 0000BE46 lstrlenA
        953  3B8 00009A99 lstrlenW

总得来说有C标准有以下
_tcscat
_tcscat_s(str, 1024, strBuffer); // 安全CRT函数
_tcscat(str, strBuffer); // C标准
::lstrcat(str, strBuffer); // API

_tcsncat
_tcsncat_s(str, 1024, strBuffer, 3); // 安全CRT函数
_tcsncat(str, strBuffer, 3); // C标准
无API

_tcscmp
无安全CRT函数
_tcscmp(strBuffer, strBuffer1); // C标准
::lstrcmp(strBuffer, strBuffer1); // API

_tcsncmp
无安全CRT函数
_tcsncmp(strBuffer ,strBuffer1, 3); // C标准
无API

_tcsicmp
无安全CRT函数
_tcsicmp(strBuffer, strBuffer1); // C标准
lstrcmpi(strBuffer, strBuffer1); // API

_tcsnicmp
无安全CRT函数
_tcsnicmp(str1, str2, 3); // C标准
无API

_tcscpy
_tcscpy_s(str, 1024, strBuffer); // 安全CRT函数
_tcscpy(str, strBuffer); // C标准
::lstrcpy(str1,str2); // API

_tcsncpy
_tcsncpy_s(str, 1024, str1, 3); // 安全CRT函数
_tcsncpy(str, strBuffer, 3); // C 标准
::lstrcpyn(str1, str2, 3); // API

_tcslen
无安全CRT函数
_tcslen(str1) // C 标准
lstrlen(str1); // API

_tcsnlen
无安全CRT函数
WORD d = _tcsnlen(str1, 3); // C 标准
WORD d = ::lstrlen(str); // API

_stprintf
_stprintf_s(str, 1024, _T("%d"), d); // 安全CRT函数
_stprintf(str, _T("%d"), i); // C 标准
::wsprintf(str, _T("%d"), i);// API

_sntprintf
_sntprintf_s(str, 1024, 32, _T("%d"), d); // 安全CRT函数
_sntprintf(str,32,_T("%d"), d); // C 标准
无API

_tcschr
无安全CRT函数
    TCHAR str1[64] = _T("eshfoer34r253gf");
    LPTSTR str = _tcschr(str1, _T('r')); // C 标准
    ::MessageBox( NULL, str, _T("标题"), MB_ICONASTERISK|MB_TASKMODAL|MB_OK );
    // 结果:r34r253gf
无API

_tcsrchr
无安全CRT函数
    TCHAR str1[64] = _T("eshfoer34r253gf");
    LPTSTR str = _tcsrchr(str1, _T('r')); // C 标准
    ::MessageBox( NULL, str, _T("标题"), MB_ICONASTERISK|MB_TASKMODAL|MB_OK );
    // 结果:r253gf
无API

strcspn // 没搞,没意义

_tcsdup // 复制字符串
无安全CRT函数
    TCHAR str1[64] = _T("eshfoer34r253gf");
    LPTSTR str2 = NULL;
    str2 = _tcsdup( str1 ); // C 标准
    ::MessageBox( NULL, str2, _T("标题"), MB_ICONASTERISK|MB_TASKMODAL|MB_OK );
无API

_tcslwr_s // 不会用,因返回的类型是errno_t(#define int errno_t) // 安全CRT函数
_tcslwr // 将字符串全部转成小写
    TCHAR str1[64] = _T("eshfoeRESEr34r253gf");
    LPTSTR str2 = (LPTSTR)calloc(_tcslen(str1)+1, sizeof(TCHAR));
    str2 = _tcslwr(str1); // C 标准
    ::MessageBox( NULL, str2, _T("标题"), MB_ICONASTERISK|MB_TASKMODAL|MB_OK );
    free(str2);
应该有这方面的API吧

// 将字符串全部转成大写
_tcsupr_s // 不会用,因返回的类型是errno_t(#define int errno_t) // 安全CRT函数
    TCHAR str1[64] = _T("eshfoeRESEr34r253gf");
    LPTSTR str2 = (LPTSTR)calloc(_tcslen(str1)+1, sizeof(TCHAR));
    str2 = _tcsupr(str1); // C 标准
    ::MessageBox( NULL, str2, str1, MB_ICONASTERISK|MB_TASKMODAL|MB_OK );
    // 结果 str1 和 str2 是一样的
    free(str2);
无API

strpbrk // 查找字符串里最先出现的字符串

// 翻转
_tcsrev
无安全CRT函数
    TCHAR str1[64] = _T("1234");
    LPTSTR str2 = (LPTSTR)calloc(_tcslen(str1)+1, sizeof(TCHAR));
    str2 = _tcsrev(str1); // C 标准
    ::MessageBox(0,str1, str2,MB_ICONASTERISK|MB_TASKMODAL|MB_OK);
    // 结果 str1 和 str2 都是被倒过来的,为什么相同呢?其实就是把str1的头指针str2,当str1改变,那str2也就改变了.

_tcsset_s(str1, SIZEOF(str1), _t('A')); // 安全CRT函数
_tcsset(str1, _t('A')); // C 标准
无API

_tcsnset_s(str1, SIZEOF(str1), _t('A'), 3); // 安全CRT函数
_tcsnset(str1,_t('A'), 3); // C 标准
无API

_tcsstr
无安全CRT函数
str3 = _tcsstr(str1, str2); // 在str1中搜索str2,返回搜索到的字符处指针,反之为NULL // C 标准
不清楚API

strtok //分解字符串

strxfrm // 不清楚

// 动态格式化字符
_vstprintf_s // 安全CRT函数
_vstprintf // C 标准
不清楚API

建议,不再使用char或者wchar_t(如:strcpy)和API函数(如:lstrcpy),
使用可以
1)转换的类型(如:TCHAR、LPTSTR、_tcscpy_s);
2)安全CRT函数,如果没有,则使用C标准函数;
3)对字符串处理的,一定要有长度来限制;

 

抱歉!评论已关闭.