Skip to content
Snippets Groups Projects
Commit 37e89ab2 authored by John Hodge's avatar John Hodge
Browse files

Client - Fix #7 - Buffer oveflow when data cached across ReadLien calls

parent cfcb64f0
No related merge requests found
...@@ -9,9 +9,11 @@ ...@@ -9,9 +9,11 @@
* This file is licenced under the 3-clause BSD Licence. See the file * This file is licenced under the 3-clause BSD Licence. See the file
* COPYING for full details. * COPYING for full details.
*/ */
//#define DEBUG_TRACE_SERVER 2
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include <netdb.h> // gethostbyname #include <netdb.h> // gethostbyname
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
...@@ -1176,15 +1178,15 @@ int Dispense_SetItem(int Socket, const char *Type, int ID, int NewPrice, const c ...@@ -1176,15 +1178,15 @@ int Dispense_SetItem(int Socket, const char *Type, int ID, int NewPrice, const c
// === // ===
// Helpers // Helpers
// === // ===
/// Read from the input socket until a newline is seen
char *ReadLine(int Socket) char *ReadLine(int Socket)
{ {
static char buf[BUFSIZ]; static char buf[BUFSIZ];
static int bufPos = 0;
static int bufValid = 0; static int bufValid = 0;
int len; int len = 0;
char *newline = NULL; char *newline = NULL;
int retLen = 0; int retLen = 0;
char *ret = malloc(10); char *ret = malloc(32);
#if DEBUG_TRACE_SERVER #if DEBUG_TRACE_SERVER
printf("ReadLine: "); printf("ReadLine: ");
...@@ -1193,41 +1195,55 @@ char *ReadLine(int Socket) ...@@ -1193,41 +1195,55 @@ char *ReadLine(int Socket)
ret[0] = '\0'; ret[0] = '\0';
// While a newline hasn't been seen
while( !newline ) while( !newline )
{ {
assert(bufValid < BUFSIZ);
// If there is data left over from a previous call, use the data from that for the first pass
if( bufValid ) { if( bufValid ) {
len = bufValid; len = bufValid;
bufValid = 0;
} }
else { else {
len = recv(Socket, buf+bufPos, BUFSIZ-1-bufPos, 0); // Otherwise read some data
len = recv(Socket, buf, BUFSIZ, 0);
if( len <= 0 ) { if( len <= 0 ) {
free(ret); free(ret);
return strdup("599 Client Connection Error\n"); return strdup("599 Client Connection Error\n");
} }
} }
buf[bufPos+len] = '\0'; assert(len < BUFSIZ);
buf[len] = '\0';
newline = strchr( buf+bufPos, '\n' ); // Search for newline in buffer
newline = strchr( buf, '\n' );
if( newline ) { if( newline ) {
*newline = '\0'; *newline = '\0';
} }
retLen += strlen(buf+bufPos); // Increment return length by amount of data up to newline (or end of read)
retLen += strlen(buf);
ret = realloc(ret, retLen + 1); ret = realloc(ret, retLen + 1);
strcat( ret, buf+bufPos ); assert(ret); // evil NULL check
strcat( ret, buf ); // append buffer data
if( newline ) {
int newLen = newline - (buf+bufPos) + 1;
bufValid = len - newLen;
len = newLen;
}
if( len + bufPos == BUFSIZ - 1 ) bufPos = 0;
else bufPos += len;
} }
#if DEBUG_TRACE_SERVER #if DEBUG_TRACE_SERVER
printf("%i '%s'\n", retLen, ret); printf("%i '%s'\n", retLen, ret);
#endif #endif
// If the newline wasn't the last character in the buffer. (I.e. there's extra data for the next call)
assert(newline - buf + 1 <= len);
if( newline - buf + 1 < len ) {
int extra_bytes = len - (newline - buf + 1);
// Copy `extra_bytes` from end of buffer down to start and set `bufValid` to `extra_bytes`?
memmove(&buf[0], newline + 1, extra_bytes);
bufValid = extra_bytes;
#if DEBUG_TRACE_SERVER > 1
printf("- Caching %i bytes '%.*s'\n", bufValid, bufValid, buf);
#endif
}
return ret; return ret;
} }
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment