2011-08-24 60 views
2

用这个代码片段有可能是错误的(在软件安全性方面),我似乎无法弄清楚......函数在显示字符串参数后终止程序。c代码片段中的安全缺陷?

void get_user(char* user) 
{ 
    char buf[1024]; 
    if (strlen(user) > sizeof(buf)) 
    die("error: user string too long\n"); 
    strcpy(buf, user); 
    … 
} 

-thx!

+2

这功课吗? – Skizz

回答

4

它不计算NUL(\0)终止的字符串。

if (strlen(user) >= sizeof(buf)) 

这是不安全的,如果user有1024个字符(会写0某处在堆栈上)。

+2

尽管'strlen(user)+ 1'的病态实现可能会溢出,原则上最好使用'> ='运算符而不是加法来避免数值溢出问题。 –

+0

@R ..这很有趣;你能详细了解溢出问题吗? – cnicutar

+2

'strlen(user)+ 1'不能溢出,因为字符串对象的实际大小包含空终止符。但是,假设你想知道'size1'和'size2'的对象是否可以放在一个缓冲区中。 'if(size1 + size2> available)'不是一个正确的测试,因为添加大小可能会换行(如果它们是未签名的)或溢出并给予UB(如果它们是已签名的)。因此,至少在我看来,这种形式的条件是*代码气味* - 它们表明潜在的安全缺陷,并需要进一步阅读以确定代码是否实际上是安全的。 –

1

答案是使用字符strcpy副本的数量与字符strlen返回的数量进行比较。

提示:strcpystrlen

4

如果strlen(user)等于1024,strcpy将在buf的末尾写入一个字节。

3

的问题是在这里:

if (strlen(user) > sizeof(buf)) 

这并不占空终止时strlen(user) == sizeof(buf)。该检查应

if (strlen(user) > sizeof(buf) - 1) 

使strcpy()可以随时复制空终止。

2

有一个可能导致缓冲区溢出的错误的错误。请记住,strlen会为您提供字符串中的字符数,,不包括空终止符。检查应该是:

if (strlen(user) + 1 > sizeof(buf)) 
1

从strlen的手册页:

所述的strlen()函数计算的字符串s的长度,不 包括终止 '\ 0' 字符。

并从strcpy的手册页:

的的strcpy()函数将字符串由src指出,包括 终止空字节( '\ 0'),到缓冲区指向DEST。

尺寸比较存在不匹配。代码检查字符串长度是否小于缓冲区,但复制字符串长度为+1个字符。如果字符串长度(小于终止'\ 0')为1024,则会发生溢出。