SDL_net UDP overflow

On the SDL_net doc page (http://www.libsdl.org/projects/SDL_net/docs/SDL_net_frame.html), it says the packet passed into UDP_Recv must have big enough buffer allocated for the data expected.

Does that mean the only safe way to use it is to allocate maximum UDP packet size? Since anyone can send a packet to an open UDP port, and there would be no way to stop someone from sending a huge packet and overflow whatever buffer you have?

Thanks!

That would make sense, but it’s not what the documentation says, though. http://www.libsdl.org/projects/SDL_net/docs/SDL_net_52.html#SEC52>

Code:
maxlen
This is size of the data buffer, which may be larger than the meaningful length. This is only used for packet creation on the senders side.

What are you trying to accomplish? There are two cases to consider:

  1. Fixed-length data: you are sending information back and forth that is
    either a constant or predictable size. If that’s the case, you shouldn’t
    have a problem.

  2. Variable length: you are sending information back and forth with
    unpredictable sizes. Is it possible for you to chunk up the data into
    predictable sizes and send it?

Presuming that you’re sending variable length, and possibly a string,
you’ll want to chunk things up into something like this:

#define UDP_STRING_CHUNK_SIZE 5
// Hurray, this is a predictable size
struct UDPStringChunk {
char pieces[UDP_STRING_CHUNK_SIZE];
unsigned int order;
unsigned int max;
};

unsigned int string_chunkify( const char *data, UDPStringChunk *chunks ) {
unsigned int num = (unsigned int)ceil( float(strlen( data )
/ UDP_STRING_CHUNK_SIZE ) );
chunks = (UDPStringChunk *)calloc( num, sizeof( UDPStringChunk ) );
for(unsigned int i=0; i < num; i++) {
chunks[i].order = i;
chunks[i].max = (num - 1);
int cindex = i * UDP_STRING_CHUNK_SIZE;
for(int c=0; c < UDP_STRING_CHUNK_SIZE; c++) {
unsigned int id = cindex + c;
if( id >= num ) break;
chunks[i].pieces[c] = data[id];
}
}

// Also, you may want to check your
endianness; SDL_BYTEORDER==SDL_BIG_ENDIAN

return num;
}

UDPStringChunk *my_data;
unsigned int n = string_chunkify( “This is a test string”, my_data );
for(unsigned int i=0; i < n; i++) {
UDPpacket *packet = SDLNet_AllocPacket( sizeof( my_data[i] ) );
if( packet ) {
SDLNet_UDP_Send( your_socket, your_channel, packet)
SDLNet_FreePacket( packet );
}
}

This sort of concept is transferable to any sort of dynamically sized data
being sent over UDP. Your packets should always be predictable. If they
can’t be, then you’ll need to size your packet, as stated, to the maximum
size just in case.
I don’t know if the packet is dynamically resized if it’s too big, so I
can’t say definitively if that’s the case.

Hopefully this helps,
-AlexOn Tue, Jun 12, 2012 at 12:52 PM, cyberfish wrote:

**
That would make sense, but it’s not what the documentation says, though.
http://www.libsdl.org/projects/SDL_net/docs/SDL_net_52.html#SEC52

Quote:

Code:

maxlen
This is size of the data buffer, which may be larger than the meaningful
length. This is only used for packet creation on the senders side.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

I think the enet library handles chunking large data streams automatically… But haven’t used it myself, still I hear many recommendations for it.

Depending on your use case, SDL_net may be higher or lower level than you desire, enet is aimed at realtime games, which is what most people seem to want :)On 06/12/2012 06:40 PM, Alex Barry wrote:

What are you trying to accomplish? There are two cases to consider:

  1. Fixed-length data: you are sending information back and forth that is either a constant or predictable size. If that’s the case, you shouldn’t have a problem.

  2. Variable length: you are sending information back and forth with unpredictable sizes. Is it possible for you to chunk up the data into predictable sizes and send it?

Presuming that you’re sending variable length, and possibly a string, you’ll want to chunk things up into something like this:

#define UDP_STRING_CHUNK_SIZE 5
// Hurray, this is a predictable size
struct UDPStringChunk {
char pieces[UDP_STRING_CHUNK_SIZE];
unsigned int order;
unsigned int max;
};

unsigned int string_chunkify( const char *data, UDPStringChunk *chunks ) {
unsigned int num = (unsigned int)ceil( float(strlen( data ) / UDP_STRING_CHUNK_SIZE ) );
chunks = (UDPStringChunk *)calloc( num, sizeof( UDPStringChunk ) );
for(unsigned int i=0; i < num; i++) {
chunks[i].order = i;
chunks[i].max = (num - 1);
int cindex = i * UDP_STRING_CHUNK_SIZE;
for(int c=0; c < UDP_STRING_CHUNK_SIZE; c++) {
unsigned int id = cindex + c;
if( id >= num ) break;
chunks[i].pieces[c] = data[id];
}
}

// Also, you may want to check your endianness; SDL_BYTEORDER==SDL_BIG_ENDIAN

return num;
}

UDPStringChunk *my_data;
unsigned int n = string_chunkify( “This is a test string”, my_data );
for(unsigned int i=0; i < n; i++) {
UDPpacket *packet = SDLNet_AllocPacket( sizeof( my_data[i] ) );
if( packet ) {
SDLNet_UDP_Send( your_socket, your_channel, packet)
SDLNet_FreePacket( packet );
}
}

This sort of concept is transferable to any sort of dynamically sized data being sent over UDP. Your packets should always be predictable. If they can’t be, then you’ll need to size your packet, as
stated, to the maximum size just in case.
I don’t know if the packet is dynamically resized if it’s too big, so I can’t say definitively if that’s the case.

Hopefully this helps,
-Alex

On Tue, Jun 12, 2012 at 12:52 PM, cyberfish <m at matthewlai.ca <mailto:m at matthewlai.ca>> wrote:

__
That would make sense, but it's not what the documentation says, though. http://www.libsdl.org/projects/SDL_net/docs/SDL_net_52.html#SEC52




Quote:	




Code:	

[i]maxlen[/i]
This is size of the data buffer, which may be larger than the meaningful length. This is only used for packet creation on the senders side.	

	


_______________________________________________
SDL mailing list
SDL at lists.libsdl.org <mailto:SDL at lists.libsdl.org>
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


LordHavoc
Author of DarkPlaces Quake1 engine - http://icculus.org/twilight/darkplaces
Co-designer of Nexuiz - http://alientrap.org/nexuiz
"War does not prove who is right, it proves who is left." - Unknown
"Any sufficiently advanced technology is indistinguishable from a rigged demo." - James Klass
"A game is a series of interesting choices." - Sid Meier

Ah! I am aware I need to know the size of the packet in advance. That’s
reasonable.

The question is what will happen if a packet comes in that’s beyond the
buffer size? (a malicious packet from an attacker?) Will the buffer
overflow?

The logical solution is for UDP_recv to discard everything beyond
max_length, and according to the source code, that is what it does.

But the documentation is inaccurate and does not make any mentioning of
that (it says the max_length is only used in packet creation at sender,
and nothing else). It makes it sound like if a bigger packet comes in,
the buffer will overflow.

Thanks
MatthewOn 6/12/2012 8:12 PM, Forest Hale wrote:

I think the enet library handles chunking large data streams automatically… But haven’t used it myself, still I hear many recommendations for it.

Depending on your use case, SDL_net may be higher or lower level than you desire, enet is aimed at realtime games, which is what most people seem to want :slight_smile:

On 06/12/2012 06:40 PM, Alex Barry wrote:

What are you trying to accomplish? There are two cases to consider:

  1. Fixed-length data: you are sending information back and forth that is either a constant or predictable size. If that’s the case, you shouldn’t have a problem.

  2. Variable length: you are sending information back and forth with unpredictable sizes. Is it possible for you to chunk up the data into predictable sizes and send it?

Presuming that you’re sending variable length, and possibly a string, you’ll want to chunk things up into something like this:

#define UDP_STRING_CHUNK_SIZE 5
// Hurray, this is a predictable size
struct UDPStringChunk {
char pieces[UDP_STRING_CHUNK_SIZE];
unsigned int order;
unsigned int max;
};

unsigned int string_chunkify( const char *data, UDPStringChunk *chunks ) {
unsigned int num = (unsigned int)ceil( float(strlen( data ) / UDP_STRING_CHUNK_SIZE ) );
chunks = (UDPStringChunk *)calloc( num, sizeof( UDPStringChunk ) );
for(unsigned int i=0; i< num; i++) {
chunks[i].order = i;
chunks[i].max = (num - 1);
int cindex = i * UDP_STRING_CHUNK_SIZE;
for(int c=0; c< UDP_STRING_CHUNK_SIZE; c++) {
unsigned int id = cindex + c;
if( id>= num ) break;
chunks[i].pieces[c] = data[id];
}
}

// Also, you may want to check your endianness; SDL_BYTEORDER==SDL_BIG_ENDIAN

return num;
}

UDPStringChunk *my_data;
unsigned int n = string_chunkify( “This is a test string”, my_data );
for(unsigned int i=0; i< n; i++) {
UDPpacket *packet = SDLNet_AllocPacket( sizeof( my_data[i] ) );
if( packet ) {
SDLNet_UDP_Send( your_socket, your_channel, packet)
SDLNet_FreePacket( packet );
}
}

This sort of concept is transferable to any sort of dynamically sized data being sent over UDP. Your packets should always be predictable. If they can’t be, then you’ll need to size your packet, as
stated, to the maximum size just in case.
I don’t know if the packet is dynamically resized if it’s too big, so I can’t say definitively if that’s the case.

Hopefully this helps,
-Alex

On Tue, Jun 12, 2012 at 12:52 PM, cyberfish<@Matthew_Laimailto:Matthew_Lai> wrote:

 __
 That would make sense, but it's not what the documentation says, though. http://www.libsdl.org/projects/SDL_net/docs/SDL_net_52.html#SEC52




 Quote:	




 Code:	

 [i]maxlen[/i]
 This is size of the data buffer, which may be larger than the meaningful length. This is only used for packet creation on the senders side.	

 	


 _______________________________________________
 SDL mailing list
 SDL at lists.libsdl.org<mailto:SDL at lists.libsdl.org>
 http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

I’m pretty sure it will overflow, and I recommend using the technique you
suggest; if the packet is over the size you’re expecting, discard it. I
don’t know SDL’s exact behaviour, but I think SDLNet_UDP_Recv will return
-1 if the buffer overflowed/you didn’t have enough space. My best
suggestion is to try it out locally, and report back with your findings (i
recommend running with gdb or something).

-AlexOn Wed, Jun 13, 2012 at 3:29 AM, Matthew Lai wrote:

Ah! I am aware I need to know the size of the packet in advance. That’s
reasonable.

The question is what will happen if a packet comes in that’s beyond the
buffer size? (a malicious packet from an attacker?) Will the buffer
overflow?

The logical solution is for UDP_recv to discard everything beyond
max_length, and according to the source code, that is what it does.

But the documentation is inaccurate and does not make any mentioning of
that (it says the max_length is only used in packet creation at sender, and
nothing else). It makes it sound like if a bigger packet comes in, the
buffer will overflow.

Thanks
Matthew

On 6/12/2012 8:12 PM, Forest Hale wrote:

I think the enet library handles chunking large data streams
automatically… But haven’t used it myself, still I hear many
recommendations for it.

Depending on your use case, SDL_net may be higher or lower level than you
desire, enet is aimed at realtime games, which is what most people seem to
want :slight_smile:

On 06/12/2012 06:40 PM, Alex Barry wrote:

What are you trying to accomplish? There are two cases to consider:

  1. Fixed-length data: you are sending information back and forth that is
    either a constant or predictable size. If that’s the case, you shouldn’t
    have a problem.

  2. Variable length: you are sending information back and forth with
    unpredictable sizes. Is it possible for you to chunk up the data into
    predictable sizes and send it?

Presuming that you’re sending variable length, and possibly a string,
you’ll want to chunk things up into something like this:

#define UDP_STRING_CHUNK_SIZE 5
// Hurray, this is a predictable size
struct UDPStringChunk {
char pieces[UDP_STRING_CHUNK_SIZE];
unsigned int order;
unsigned int max;
};

unsigned int string_chunkify( const char *data, UDPStringChunk *chunks )
{
unsigned int num = (unsigned int)ceil( float(strlen( data ) /
UDP_STRING_CHUNK_SIZE ) );
chunks = (UDPStringChunk *)calloc( num, sizeof( UDPStringChunk ) );
for(unsigned int i=0; i< num; i++) {
chunks[i].order = i;
chunks[i].max = (num - 1);
int cindex = i * UDP_STRING_CHUNK_SIZE;
for(int c=0; c< UDP_STRING_CHUNK_SIZE; c++) {
unsigned int id = cindex + c;
if( id>= num ) break;
chunks[i].pieces[c] = data[id];
}
}

// Also, you may want to check your endianness;
SDL_BYTEORDER==SDL_BIG_ENDIAN

return num;
}

UDPStringChunk *my_data;
unsigned int n = string_chunkify( “This is a test string”, my_data );
for(unsigned int i=0; i< n; i++) {
UDPpacket *packet = SDLNet_AllocPacket( sizeof( my_data[i] ) );
if( packet ) {
SDLNet_UDP_Send( your_socket, your_channel, packet)
SDLNet_FreePacket( packet );
}
}

This sort of concept is transferable to any sort of dynamically sized
data being sent over UDP. Your packets should always be predictable. If
they can’t be, then you’ll need to size your packet, as
stated, to the maximum size just in case.
I don’t know if the packet is dynamically resized if it’s too big, so I
can’t say definitively if that’s the case.

Hopefully this helps,
-Alex

On Tue, Jun 12, 2012 at 12:52 PM, cyberfish<m at matthewlai.ca<**mailto: m at matthewlai.ca>> wrote:

__
That would make sense, but it's not what the documentation says,

though. http://www.libsdl.org/projects/SDL_net/docs/SDL_net_
52.html#SEC52http://www.libsdl.org/projects/SDL_net/docs/SDL_net_52.html#SEC52

Quote:




Code:

[i]maxlen[/i]
This is size of the data buffer, which may be larger than the

meaningful length. This is only used for packet creation on the senders
side.

______________________________**_________________
SDL mailing list
SDL at lists.libsdl.org<mailto:SD**L at lists.libsdl.org<SDL at lists.libsdl.org>
http://lists.libsdl.org/**listinfo.cgi/sdl-libsdl.org<http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org>

_____________**
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/**listinfo.cgi/sdl-libsdl.orghttp://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

_____________**
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/**listinfo.cgi/sdl-libsdl.orghttp://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org