`recv()`会导致缓冲区溢出吗?

DJS*_*nny 5 c c++ sockets buffer-overflow recv

我将自己介绍给C/C++中的套接字编程,并使用send()recv()通过TCP套接字在客户端和服务器程序之间交换数据.

以下是我的代码中的一些相关摘录:

server.c:

char recv_data[1024];

// Socket setup and so on ommited...

bytes_recieved = recv(connected, recv_data, 1024, 0);
recv_data[bytes_recieved] = '\0';
Run Code Online (Sandbox Code Playgroud)

client.c:

char send_data[1024];

// Setup ommited...

send(connected, send_data, strlen(send_data), 0);
Run Code Online (Sandbox Code Playgroud)

recv()本身是否提供任何防止缓冲区溢出的保护?例如,如果我将第3个参数更改recv()为高于recv_data(例如4000)指向的缓冲区的某个值- 这是否会导致缓冲区溢出?(我实际上尝试过这样做,但似乎无法触发段错误).

我实际上是在尝试创建一个故意易受攻击的服务器程序来更好地理解这些问题,这就是我试图溢出的原因recv().

修正案:

不无关系,将会发现为什么client.c上面会发送超过1024指定的字节数strlen(send_data).我正在使用gets(send_data)从标准输入填充该缓冲区,但如果我通过标准输入输入超过1024个字节,server.c程序显示它接收所有的字节!:).是否strlen(send_data)send()不限制发送的字节数量?

Jay*_*Jay 9

例如,如果我将第三个参数更改为recv()更高于recv_data指向的缓冲区(例如4000) - 这是否会导致缓冲区溢出?

当然是的.如果网络缓冲区有4000字节的数据,它将把它放在缓冲区中.关键点在于,recv就像任何其他采用缓冲区的C API一样,它的长度相信调用者会传递缓冲区的实际长度,如果调用者传递的长度不正确,那么问题就在于调用者,它可以导致未定义的行为.

在C中,当您将数组传递给函数时,被调用函数无法知道数组的大小.因此,所有API都只依赖于您提供的输入.

char recv_data[1024];

// Socket setup and so on ommited...

bytes_recieved = recv(connected, recv_data, 1024, 0);
recv_data[bytes_recieved] = '\0';
Run Code Online (Sandbox Code Playgroud)

上述代码可能会以多种方式引发麻烦.在以下情况下,它将导致未定义的行为:
(a)如果recv返回-1,则直接索引到recv_data缓冲区而不检查返回值
(b)如果recv返回1024,则再次导致超出绑定的访问权限大小的阵列1024应该从被访问01023.


alk*_*alk 5

这个

recv_data[bytes_recieved] = '\0';
Run Code Online (Sandbox Code Playgroud)

如果收到1024字节,可能会导致缓冲区溢出.

你可能想改变它

bytes_recieved = recv(connected, recv_data, 1024, 0);
Run Code Online (Sandbox Code Playgroud)

成为

bytes_recieved = recv(connected, recv_data, 1024 - 1, 0);
Run Code Online (Sandbox Code Playgroud)

所以bytes_recieved永远不会超过1023,这是最大的有效索引recv_data.


您的系统调用(recv()/ send())也没有错误检查.-1在以任何其他方式使用结果之前测试它们是否已返回.


参考你的修正案:

strlen()尝试返回从其参数指向的字符开始直到第一个NUL/ 0-character 的字符数.此数字可以是任何值,具体取决于放置终止的位置0.

如果这个0-terminator 的seach 在分配给strlen()s参数的内存后面运行,程序肯定会遇到未定义的行为,因此可以返回任何值.

因此,要回答你的问题:如果send_data没有 0终结strlen(),使应用程序运行到未定义behaviuor所以它可能会崩溃或strlen()返回一个值大于1024,那么send()将尝试发送该字符数.