简体   繁体   中英

max size_t value on send() in C

I'm writing a tcp server in C but I'm facing problems on send. I read local file and send data back to the client, when the file is small I have no problems, but when it becomes bigger I have this strange situation:

server tcp:

 // create socket, bind, listen accept

// read file
fseek(fptr, 0, SEEK_SET);
// malloc for the sending buffer
ssize_t read = fread(sbuf, 1, file_size, fptr);

while(to_send>0) {
  sent = send(socket, sbuf, buf_size, 0);
  sbuf += sent;
  to_send -= sent;
}

On huge files sent becomes equals to the max value of size_t, I think that I have a buffer overflow. How can I prevent this? What is the best practice to read from a file and send it back?

The problem is that you send buf_size bytes every time, even if there aren't that many left.

For example, pretend buf_size is 8 and you are sending 10 bytes (So initially, to_send is also 10). The first send sends 8 bytes, so you need to send 2 more. The second time, you also send 8 bytes (Which probably reads out of bounds). Then, to_send will be will be -6, which is the same as SIZE_MAX - 5 .

Simple fix is to send to_send if it is smaller:

sent = send(socket, sbuf, to_send < buf_size ? to_send : buf_size, 0);

Also, send returns -1 if it is unsuccessful. This is the same as SIZE_MAX when it is assigned to a size_t . You would need some error handling to fix this.

On huge files sent becomes equals to the max value of size_t, I think that I have a buffer overflow.

Since sent gets its value as the return value of send() , and send() returns ssize_t , which is a signed type unlikely to be wider than size_t , it is virtually certain that what is actually happening is that send() is indicating an error by returning -1. In that case, it will also be setting errno to a value indicative of the error. It cannot return the maximum value of size_t on any system I've ever had my hands on.

How can I prevent this?

In the first place, before you worry about preventing it, you should be sure to detect it by

  1. declaring sent as a ssize_t to match the return type of send() , not a size_t , and
  2. checking the value returned into sent for such error conditions.

Second, if you are really dealing with files longer than can be represented by a ssize_t (much less a size_t ), then it is a poor idea to load the whole thing into memory before sending any of it. Instead, load it in (much) smaller blocks, and send the data one such block at a time. Not only will this tend to have lower perceived latency, but it will also avoid any risk associated with approaching the limits of the data types involved.

Additionally, when you do so, be careful to do it right. You have done well to wrap your send() call in a loop to account for short writes, but as @Artyer describes in his answer, you don't quite get that right because you do not reduce the number of bytes you try to send on the second and subsequent calls.

What is the best practice to read from a file and send it back?

As above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM