about summary refs log tree commit diff
path: root/src/engine
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2008-02-24 16:03:58 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2008-02-24 16:03:58 +0000
commit4739966e14ca2df24d4f44fb814b6275b9bf2a3c (patch)
tree2398dee3380dfa48582a71a4f2d4278448fa6cb8 /src/engine
parent1ea859c431b33a384727c0016917dde15bceeff3 (diff)
downloadzcatch-4739966e14ca2df24d4f44fb814b6275b9bf2a3c.tar.gz
zcatch-4739966e14ca2df24d4f44fb814b6275b9bf2a3c.zip
larger restructure to improve security
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/client/ec_client.c58
-rw-r--r--src/engine/e_compression.c6
-rw-r--r--src/engine/e_engine.c10
-rw-r--r--src/engine/e_engine.h1
-rw-r--r--src/engine/e_if_other.h17
-rw-r--r--src/engine/e_network.c28
-rw-r--r--src/engine/e_packer.c68
-rw-r--r--src/engine/e_snapshot.c42
-rw-r--r--src/engine/e_snapshot.h5
-rw-r--r--src/engine/e_system.c53
-rw-r--r--src/engine/e_system.h6
-rw-r--r--src/engine/server/es_server.c18
12 files changed, 261 insertions, 51 deletions
diff --git a/src/engine/client/ec_client.c b/src/engine/client/ec_client.c
index 7185c471..0ddcf7d9 100644
--- a/src/engine/client/ec_client.c
+++ b/src/engine/client/ec_client.c
@@ -211,30 +211,48 @@ enum
 	NUM_SNAPSHOT_TYPES=2
 };
 
+/* the game snapshots are modifiable by the game */
 SNAPSTORAGE snapshot_storage;
 static SNAPSTORAGE_HOLDER *snapshots[NUM_SNAPSHOT_TYPES];
+
 static int recived_snapshots;
 static char snapshot_incomming_data[MAX_SNAPSHOT_SIZE];
 
 /* --- */
 
-const void *snap_get_item(int snapid, int index, SNAP_ITEM *item)
+void *snap_get_item(int snapid, int index, SNAP_ITEM *item)
 {
 	SNAPSHOT_ITEM *i;
 	dbg_assert(snapid >= 0 && snapid < NUM_SNAPSHOT_TYPES, "invalid snapid");
-	i = snapshot_get_item(snapshots[snapid]->snap, index);
+	i = snapshot_get_item(snapshots[snapid]->alt_snap, index);
+	item->datasize = snapshot_get_item_datasize(snapshots[snapid]->alt_snap, index);
 	item->type = snapitem_type(i);
 	item->id = snapitem_id(i);
 	return (void *)snapitem_data(i);
 }
 
-const void *snap_find_item(int snapid, int type, int id)
+void snap_invalidate_item(int snapid, int index)
+{
+	SNAPSHOT_ITEM *i;
+	dbg_assert(snapid >= 0 && snapid < NUM_SNAPSHOT_TYPES, "invalid snapid");
+	i = snapshot_get_item(snapshots[snapid]->alt_snap, index);
+	if(i)
+	{
+		if((char *)i < (char *)snapshots[snapid]->alt_snap || (char *)i > (char *)snapshots[snapid]->alt_snap + snapshots[snapid]->snap_size)
+			dbg_msg("ASDFASDFASdf", "ASDFASDFASDF");
+		if((char *)i >= (char *)snapshots[snapid]->snap && (char *)i < (char *)snapshots[snapid]->snap + snapshots[snapid]->snap_size)
+			dbg_msg("ASDFASDFASdf", "ASDFASDFASDF");
+		i->type_and_id = -1;
+	}
+}
+
+void *snap_find_item(int snapid, int type, int id)
 {
 	/* TODO: linear search. should be fixed. */
 	int i;
 	for(i = 0; i < snapshots[snapid]->snap->num_items; i++)
 	{
-		SNAPSHOT_ITEM *itm = snapshot_get_item(snapshots[snapid]->snap, i);
+		SNAPSHOT_ITEM *itm = snapshot_get_item(snapshots[snapid]->alt_snap, i);
 		if(snapitem_type(itm) == type && snapitem_id(itm) == id)
 			return (void *)snapitem_data(itm);
 	}
@@ -762,6 +780,11 @@ static void client_process_packet(NETPACKET *packet)
 				int total_size = msg_unpack_int();
 				int size = msg_unpack_int();
 				const unsigned char *data = msg_unpack_raw(size);
+				
+				/* check fior errors */
+				if(msg_unpack_error() || size <= 0 || total_size <= 0)
+					return;
+				
 				io_write(mapdownload_file, data, size);
 				
 				mapdownload_totalsize = total_size;
@@ -834,7 +857,7 @@ static void client_process_packet(NETPACKET *packet)
 					crc = msg_unpack_int();
 					part_size = msg_unpack_int();
 				}
-
+				
 				data = (const char *)msg_unpack_raw(part_size);
 				
 				if(msg_unpack_error())
@@ -882,6 +905,7 @@ static void client_process_packet(NETPACKET *packet)
 						
 						complete_size = (num_parts-1) * MAX_SNAPSHOT_PACKSIZE + part_size;
 
+						/* reset snapshoting */
 						snapshot_part = 0;
 						
 						/* find snapshot that we should use as delta */
@@ -891,7 +915,7 @@ static void client_process_packet(NETPACKET *packet)
 						/* find delta */
 						if(delta_tick >= 0)
 						{
-							int deltashot_size = snapstorage_get(&snapshot_storage, delta_tick, 0, &deltashot);
+							int deltashot_size = snapstorage_get(&snapshot_storage, delta_tick, 0, &deltashot, 0);
 							
 							if(deltashot_size < 0)
 							{
@@ -912,17 +936,28 @@ static void client_process_packet(NETPACKET *packet)
 						deltasize = sizeof(int)*3;
 
 						if(complete_size)
-						{
+						{	
+							int intsize;
 							int compsize = zerobit_decompress(snapshot_incomming_data, complete_size, tmpbuffer);
-							int intsize = intpack_decompress(tmpbuffer, compsize, tmpbuffer2);
+							
+							if(compsize < 0) /* failure during decompression, bail */
+								return;
+								
+							intsize = intpack_decompress(tmpbuffer, compsize, tmpbuffer2);
+
+							if(intsize < 0) /* failure during decompression, bail */
+								return;
+
 							deltadata = tmpbuffer2;
 							deltasize = intsize;
 						}
-
-						/*dbg_msg("UNPACK", "%d unpacked with %d", game_tick, delta_tick); */
 						
+						/* unpack delta */
 						purgetick = delta_tick;
 						snapsize = snapshot_unpack_delta(deltashot, (SNAPSHOT*)tmpbuffer3, deltadata, deltasize);
+						if(snapsize < 0)
+							return;
+							
 						if(msg != NETMSG_SNAPEMPTY && snapshot_crc((SNAPSHOT*)tmpbuffer3) != crc)
 						{
 							if(config.debug)
@@ -950,10 +985,9 @@ static void client_process_packet(NETPACKET *packet)
 						if(snapshots[SNAP_CURRENT] && snapshots[SNAP_CURRENT]->tick < purgetick)
 							purgetick = snapshots[SNAP_PREV]->tick;
 						snapstorage_purge_until(&snapshot_storage, purgetick);
-						/*client_snapshot_purge_until(game_tick-50); */
 						
 						/* add new */
-						snapstorage_add(&snapshot_storage, game_tick, time_get(), snapsize, (SNAPSHOT*)tmpbuffer3);
+						snapstorage_add(&snapshot_storage, game_tick, time_get(), snapsize, (SNAPSHOT*)tmpbuffer3, 1);
 						
 						/* apply snapshot, cycle pointers */
 						recived_snapshots++;
diff --git a/src/engine/e_compression.c b/src/engine/e_compression.c
index fa7d7866..0a16d0b4 100644
--- a/src/engine/e_compression.c
+++ b/src/engine/e_compression.c
@@ -125,9 +125,8 @@ long zerobit_decompress(const void *src_, int size, void *dst_)
 	unsigned char *src = (unsigned char *)src_;
 	unsigned char *dst = (unsigned char *)dst_;
 	unsigned char *end = src + size;
-
 	
-	while(src != end)
+	while(src < end)
 	{
 		unsigned char bit = 0x80;
 		unsigned char mask = *src++;
@@ -140,6 +139,9 @@ long zerobit_decompress(const void *src_, int size, void *dst_)
 			else
 				*dst++ = 0;
 		}
+
+		if(src > end)
+			return -1;
 	}
 	
 	return (long)(dst-(unsigned char *)dst_);
diff --git a/src/engine/e_engine.c b/src/engine/e_engine.c
index c5cb3616..6fe61efe 100644
--- a/src/engine/e_engine.c
+++ b/src/engine/e_engine.c
@@ -1,6 +1,7 @@
 /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
 #include <string.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 #include <engine/e_system.h>
 #include <engine/e_server_interface.h>
@@ -25,6 +26,15 @@ const char *engine_savepath(const char *filename, char *buffer, int max)
 }
 
 
+int engine_stress(float probability)
+{
+	if(!config.dbg_stress)
+		return 0;
+	if(rand()/(float)RAND_MAX < probability)
+		return 1;
+	return 0;
+}
+
 void engine_init(const char *appname)
 {
 	dbg_msg("engine", "running on %s-%s-%s", CONF_FAMILY_STRING, CONF_PLATFORM_STRING, CONF_ARCH_STRING);
diff --git a/src/engine/e_engine.h b/src/engine/e_engine.h
index 6974db1d..6818d96d 100644
--- a/src/engine/e_engine.h
+++ b/src/engine/e_engine.h
@@ -4,6 +4,7 @@ const char *engine_savepath(const char *filename, char *buffer, int max);
 void engine_init(const char *appname);
 void engine_parse_arguments(int argc, char **argv);
 void engine_writeconfig();
+int engine_stress(float probability);
 
 
 enum
diff --git a/src/engine/e_if_other.h b/src/engine/e_if_other.h
index 931df64d..b3a61e7f 100644
--- a/src/engine/e_if_other.h
+++ b/src/engine/e_if_other.h
@@ -34,6 +34,7 @@ typedef struct
 {
 	int type;
 	int id;
+	int datasize;
 } SNAP_ITEM;
 
 /*
@@ -234,7 +235,7 @@ int snap_num_items(int snapid);
 	Returns:
 		Returns a pointer to the item if it exists, otherwise NULL.
 */
-const void *snap_get_item(int snapid, int index, SNAP_ITEM *item);
+void *snap_get_item(int snapid, int index, SNAP_ITEM *item);
 
 /*
 	Function: snap_find_item
@@ -250,7 +251,19 @@ const void *snap_get_item(int snapid, int index, SNAP_ITEM *item);
 	Returns:
 		Returns a pointer to the item if it exists, otherwise NULL.
 */
-const void *snap_find_item(int snapid, int type, int id);
+void *snap_find_item(int snapid, int type, int id);
+
+/*
+	Function: snap_invalidate_item
+		Marks an item as invalid byt setting type and id to 0xffffffff.
+	
+	Arguments:
+		snapid - Snapshot ID to the data to fetch.
+			* SNAP_PREV for previous snapshot.
+			* SNAP_CUR for current snapshot.
+		index - Index of the item.
+*/
+void snap_invalidate_item(int snapid, int index);
 
 /*
 	Function: snap_input
diff --git a/src/engine/e_network.c b/src/engine/e_network.c
index acf723ba..9211726f 100644
--- a/src/engine/e_network.c
+++ b/src/engine/e_network.c
@@ -54,7 +54,6 @@ typedef struct
 	unsigned char *data;
 } NETPACKETDATA;
 
-
 static void send_packet(NETSOCKET socket, NETADDR4 *addr, NETPACKETDATA *packet)
 {
 	unsigned char buffer[NETWORK_MAX_PACKET_SIZE];
@@ -356,7 +355,18 @@ static int conn_feed(NETCONNECTION *conn, NETPACKETDATA *p, NETADDR4 *addr)
 		conn->remote_closed = 1;
 		
 		if(p->data_size)
-			conn_set_error(conn, (char *)p->data);
+		{
+			/* make sure to sanitize the error string form the other party*/
+			char str[128];
+			if(p->data_size < 128)
+				str_copy(str, (char *)p->data, p->data_size);
+			else
+				str_copy(str, (char *)p->data, 128);
+			str_sanitize_strong(str);
+			
+			/* set the error string */
+			conn_set_error(conn, str);
+		}
 		else
 			conn_set_error(conn, "no reason given");
 		if(config.debug)
@@ -739,7 +749,7 @@ int netserver_recv(NETSERVER *s, NETPACKET *packet)
 		else
 		{
 			/* errornous packet, drop it */
-			dbg_msg("server", "crazy packet");
+			/* dbg_msg("server", "crazy packet"); */
 		}
 		
 		/* read header */
@@ -751,7 +761,11 @@ int netserver_recv(NETSERVER *s, NETPACKET *packet)
 
 int netserver_send(NETSERVER *s, NETPACKET *packet)
 {
-	dbg_assert(packet->data_size < NETWORK_MAX_PAYLOAD, "packet payload too big");
+	if(packet->data_size >= NETWORK_MAX_PAYLOAD)
+	{
+		dbg_msg("netserver", "packet payload too big. %d. dropping packet", packet->data_size);
+		return -1;
+	}
 	
 	if(packet->flags&PACKETFLAG_CONNLESS)
 	{
@@ -898,7 +912,11 @@ int netclient_recv(NETCLIENT *c, NETPACKET *packet)
 
 int netclient_send(NETCLIENT *c, NETPACKET *packet)
 {
-	dbg_assert(packet->data_size < NETWORK_MAX_PAYLOAD, "packet payload too big");
+	if(packet->data_size >= NETWORK_MAX_PAYLOAD)
+	{
+		dbg_msg("netclient", "packet payload too big. %d. dropping packet", packet->data_size);
+		return -1;
+	}
 	
 	if(packet->flags&PACKETFLAG_CONNLESS)
 	{
diff --git a/src/engine/e_packer.c b/src/engine/e_packer.c
index 9e77927d..fa5d54cf 100644
--- a/src/engine/e_packer.c
+++ b/src/engine/e_packer.c
@@ -1,12 +1,39 @@
 /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+#include <stdlib.h>
 
 #include "e_system.h"
 #include "e_packer.h"
 #include "e_compression.h"
+#include "e_engine.h"
 
 /* useful for debugging */
-#define packing_error(p) p->error = 1
-/* #define packing_error(p) p->error = 1; dbg_break() */
+#if 0
+	#define packing_error(p) p->error = 1; dbg_break()
+#else
+	#define packing_error(p) p->error = 1
+#endif
+
+int stress_get_int()
+{
+	static const int nasty[] = {-1, 0, 1, 66000, -66000, (-1<<31), 0x7fffffff};
+	if(rand()&1)
+		return rand();
+	return nasty[rand()%6];
+}
+
+const char *stress_get_string(int *size)
+{
+	static char noise[1024];
+	int i;
+	int s;
+	s = (rand()%1024)-1;
+	for(i = 0; i < s; i++)
+		noise[i] = (rand()%254)+1;
+	noise[s] = 0;
+	if(size)
+		*size = s;
+	return noise;
+}
 
 void packer_reset(PACKER *p)
 {
@@ -19,6 +46,9 @@ void packer_add_int(PACKER *p, int i)
 {
 	if(p->error)
 		return;
+		
+	/*if(engine_stress(0.05f))
+		i = stress_get_int();*/
 	
 	/* make sure that we have space enough */
 	if(p->end - p->current < 6)
@@ -35,6 +65,15 @@ void packer_add_string(PACKER *p, const char *str, int limit)
 	if(p->error)
 		return;
 		
+	/* STRESS: do this better */
+	/*
+	if(engine_stress(0.1f))
+	{
+		str = stress_get_string(0);
+		limit = 0;
+	}*/
+	
+	/* */
 	if(limit > 0)
 	{
 		while(*str && limit != 0)
@@ -105,8 +144,14 @@ void unpacker_reset(UNPACKER *p, const unsigned char *data, int size)
 int unpacker_get_int(UNPACKER *p)
 {
 	int i;
-	if(p->error || p->current >= p->end)
+	if(p->error)
 		return 0;
+	if(p->current >= p->end)
+	{
+		packing_error(p);
+		return 0;
+	}
+	
 	p->current = vint_unpack(p->current, &i);
 	if(p->current > p->end)
 	{
@@ -118,11 +163,11 @@ int unpacker_get_int(UNPACKER *p)
 
 const char *unpacker_get_string(UNPACKER *p)
 {
-	const char *ptr;
+	char *ptr;
 	if(p->error || p->current >= p->end)
 		return "";
 		
-	ptr = (const char *)p->current;
+	ptr = (char *)p->current;
 	while(*p->current) /* skip the string */
 	{
 		p->current++;
@@ -133,17 +178,26 @@ const char *unpacker_get_string(UNPACKER *p)
 		}
 	}
 	p->current++;
+	
+	/* sanitize all strings */
+	str_sanitize(ptr);
 	return ptr;
 }
 
 const unsigned char *unpacker_get_raw(UNPACKER *p, int size)
 {
 	const unsigned char *ptr = p->current;
-	p->current += size;
-	if(p->current > p->end)
+	if(p->error)
+		return 0;
+	
+	/* check for nasty sizes */
+	if(size < 0 || p->current+size > p->end)
 	{
 		packing_error(p);
 		return 0;
 	}
+
+	/* "unpack" the data */	
+	p->current += size;
 	return ptr;
 }
diff --git a/src/engine/e_snapshot.c b/src/engine/e_snapshot.c
index 6c908518..9dc64ae8 100644
--- a/src/engine/e_snapshot.c
+++ b/src/engine/e_snapshot.c
@@ -1,6 +1,7 @@
 /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
 #include <stdlib.h>
 #include "e_snapshot.h"
+#include "e_engine.h"
 #include "e_compression.h"
 #include "e_common_interface.h"
 
@@ -317,6 +318,8 @@ int snapshot_unpack_delta(SNAPSHOT *from, SNAPSHOT *to, void *srcdata, int data_
 	SNAPBUILD builder;
 	SNAPSHOT_DELTA *delta = (SNAPSHOT_DELTA *)srcdata;
 	int *data = (int *)delta->data;
+	int *end = (int *)(((char *)srcdata + data_size));
+	
 	SNAPSHOT_ITEM *fromitem;
 	int i, d, keep, itemsize;
 	int *deleted;
@@ -329,6 +332,8 @@ int snapshot_unpack_delta(SNAPSHOT *from, SNAPSHOT *to, void *srcdata, int data_
 	/* unpack deleted stuff */
 	deleted = data;
 	data += delta->num_deleted_items;
+	if(data > end)
+		return -1;
 
 	/* copy all non deleted stuff */
 	for(i = 0; i < from->num_items; i++)
@@ -358,11 +363,17 @@ int snapshot_unpack_delta(SNAPSHOT *from, SNAPSHOT *to, void *srcdata, int data_
 	/* unpack updated stuff */
 	for(i = 0; i < delta->num_update_items; i++)
 	{
+		if(data+3 > end)
+			return -1;
+		
 		itemsize = *data++;
 		type = *data++;
 		id = *data++;
 		snapshot_current = type;
 		
+		if(data+itemsize/4 > end)
+			return -1;
+		
 		key = (type<<16)|id;
 		
 		/* create the item if needed */
@@ -442,10 +453,16 @@ void snapstorage_purge_until(SNAPSTORAGE *ss, int tick)
 	ss->last = 0;
 }
 
-void snapstorage_add(SNAPSTORAGE *ss, int tick, int64 tagtime, int data_size, void *data)
+void snapstorage_add(SNAPSTORAGE *ss, int tick, int64 tagtime, int data_size, void *data, int create_alt)
 {
 	/* allocate memory for holder + snapshot_data */
-	SNAPSTORAGE_HOLDER *h = (SNAPSTORAGE_HOLDER *)mem_alloc(sizeof(SNAPSTORAGE_HOLDER)+data_size, 1);
+	SNAPSTORAGE_HOLDER *h;
+	int total_size = sizeof(SNAPSTORAGE_HOLDER)+data_size;
+	
+	if(create_alt)
+		total_size += data_size;
+	
+	h = (SNAPSTORAGE_HOLDER *)mem_alloc(total_size, 1);
 	
 	/* set data */
 	h->tick = tick;
@@ -453,6 +470,15 @@ void snapstorage_add(SNAPSTORAGE *ss, int tick, int64 tagtime, int data_size, vo
 	h->snap_size = data_size;
 	h->snap = (SNAPSHOT*)(h+1);
 	mem_copy(h->snap, data, data_size);
+
+	if(create_alt) /* create alternative if wanted */
+	{
+		h->alt_snap = (SNAPSHOT*)(((char *)h->snap) + data_size);
+		mem_copy(h->alt_snap, data, data_size);
+	}
+	else
+		h->alt_snap = 0;
+		
 	
 	/* link */
 	h->next = 0;
@@ -464,7 +490,7 @@ void snapstorage_add(SNAPSTORAGE *ss, int tick, int64 tagtime, int data_size, vo
 	ss->last = h;
 }
 
-int snapstorage_get(SNAPSTORAGE *ss, int tick, int64 *tagtime, SNAPSHOT **data)
+int snapstorage_get(SNAPSTORAGE *ss, int tick, int64 *tagtime, SNAPSHOT **data, SNAPSHOT **alt_data)
 {
 	SNAPSTORAGE_HOLDER *h = ss->first;
 	
@@ -476,6 +502,8 @@ int snapstorage_get(SNAPSTORAGE *ss, int tick, int64 *tagtime, SNAPSHOT **data)
 				*tagtime = h->tagtime;
 			if(data)
 				*data = h->snap;
+			if(alt_data)
+				*alt_data = h->alt_snap;
 			return h->snap_size;
 		}
 		
@@ -524,6 +552,14 @@ int snapbuild_finish(SNAPBUILD *sb, void *snapdata)
 void *snapbuild_new_item(SNAPBUILD *sb, int type, int id, int size)
 {
 	SNAPSHOT_ITEM *obj = (SNAPSHOT_ITEM *)(sb->data+sb->data_size);
+
+	if(engine_stress(0.01f))
+	{
+		size += ((rand()%5) - 2)*4;
+		if(size < 0)
+			size = 0;
+	}
+
 	mem_zero(obj, sizeof(SNAPSHOT_ITEM) + size);
 	obj->type_and_id = (type<<16)|id;
 	sb->offsets[sb->num_items] = sb->data_size;
diff --git a/src/engine/e_snapshot.h b/src/engine/e_snapshot.h
index 1396f6ee..9527cb24 100644
--- a/src/engine/e_snapshot.h
+++ b/src/engine/e_snapshot.h
@@ -52,6 +52,7 @@ typedef struct SNAPSTORAGE_HOLDER_t
 	
 	int snap_size;
 	SNAPSHOT *snap;
+	SNAPSHOT *alt_snap;
 } SNAPSTORAGE_HOLDER;
  
 typedef struct SNAPSTORAGE_t
@@ -63,8 +64,8 @@ typedef struct SNAPSTORAGE_t
 void snapstorage_init(SNAPSTORAGE *ss);
 void snapstorage_purge_all(SNAPSTORAGE *ss);
 void snapstorage_purge_until(SNAPSTORAGE *ss, int tick);
-void snapstorage_add(SNAPSTORAGE *ss, int tick, int64 tagtime, int data_size, void *data);
-int snapstorage_get(SNAPSTORAGE *ss, int tick, int64 *tagtime, SNAPSHOT **data);
+void snapstorage_add(SNAPSTORAGE *ss, int tick, int64 tagtime, int data_size, void *data, int create_alt);
+int snapstorage_get(SNAPSTORAGE *ss, int tick, int64 *tagtime, SNAPSHOT **data, SNAPSHOT **alt_data);
 
 /* SNAPBUILD */
 
diff --git a/src/engine/e_system.c b/src/engine/e_system.c
index d2fb4eeb..044b48a2 100644
--- a/src/engine/e_system.c
+++ b/src/engine/e_system.c
@@ -47,6 +47,10 @@
 extern "C" {
 #endif
 
+IOHANDLE io_stdin() { return (IOHANDLE)stdin; }
+IOHANDLE io_stdout() { return (IOHANDLE)stdout; }
+IOHANDLE io_stderr() { return (IOHANDLE)stderr; }
+
 IOHANDLE logfile = 0;
 
 void dbg_assert_imp(const char *filename, int line, int test, const char *msg)
@@ -462,19 +466,21 @@ int net_addr4_cmp(const NETADDR4 *a, const NETADDR4 *b)
 
 int net_host_lookup(const char *hostname, unsigned short port, NETADDR4 *addr)
 {
-	struct hostent* ip = gethostbyname(hostname);
+	struct addrinfo hints;
+	struct addrinfo *result;
+	int e;
+	
+	mem_zero(&hints, sizeof(hints));
+	hints.ai_family = AF_INET;
 
-	if(ip && ip->h_length > 0)
-	{
-		addr->ip[0] = ip->h_addr_list[0][0];
-		addr->ip[1] = ip->h_addr_list[0][1];
-		addr->ip[2] = ip->h_addr_list[0][2];
-		addr->ip[3] = ip->h_addr_list[0][3];
-		addr->port = port;
-		return 0;
-	}
+	e = getaddrinfo(hostname, NULL, &hints, &result);
+	if(e != 0 || !result)
+		return -1;
 
-	return -1;
+	sockaddr_to_netaddr4(result->ai_addr, addr);
+	freeaddrinfo(result);
+	addr->port = port;
+	return 0;
 }
 
 NETSOCKET net_udp4_create(NETADDR4 bindaddr)
@@ -842,6 +848,31 @@ void str_format(char *buffer, int buffer_size, const char *format, ...)
 	buffer[buffer_size-1] = 0; /* assure null termination */
 }
 
+
+
+/* makes sure that the string only contains the characters between 32 and 127 */
+void str_sanitize_strong(char *str)
+{
+	while(*str)
+	{
+		*str &= 0x7f;
+		if(*str < 32)
+			*str = 32;
+		str++;
+	}
+}
+
+/* makes sure that the string only contains the characters between 32 and 255 + \r\n\t */
+void str_sanitize(char *str)
+{
+	while(*str)
+	{
+		if(*str < 32 && !(*str == '\r') && !(*str == '\n') && !(*str == '\t'))
+			*str = ' ';
+		str++;
+	}
+}
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/src/engine/e_system.h b/src/engine/e_system.h
index 1fd929e8..d524382b 100644
--- a/src/engine/e_system.h
+++ b/src/engine/e_system.h
@@ -526,6 +526,12 @@ void pstr_format(pstr *str, )*/
 void str_append(char *dst, const char *src, int dst_size);
 void str_copy(char *dst, const char *src, int dst_size);
 void str_format(char *buffer, int buffer_size, const char *format, ...);
+void str_sanitize_strong(char *str);
+void str_sanitize(char *str);
+
+IOHANDLE io_stdin();
+IOHANDLE io_stdout();
+IOHANDLE io_stderr();
 
 #ifdef __cplusplus
 }
diff --git a/src/engine/server/es_server.c b/src/engine/server/es_server.c
index d8b8d978..9fe75e39 100644
--- a/src/engine/server/es_server.c
+++ b/src/engine/server/es_server.c
@@ -371,14 +371,14 @@ static void server_do_snap()
 			snapstorage_purge_until(&clients[i].snapshots, current_tick-SERVER_TICK_SPEED);
 			
 			/* save it the snapshot */
-			snapstorage_add(&clients[i].snapshots, current_tick, time_get(), snapshot_size, data);
+			snapstorage_add(&clients[i].snapshots, current_tick, time_get(), snapshot_size, data, 0);
 			
 			/* find snapshot that we can preform delta against */
 			emptysnap.data_size = 0;
 			emptysnap.num_items = 0;
 			
 			{
-				deltashot_size = snapstorage_get(&clients[i].snapshots, clients[i].last_acked_snapshot, 0, &deltashot);
+				deltashot_size = snapstorage_get(&clients[i].snapshots, clients[i].last_acked_snapshot, 0, &deltashot, 0);
 				if(deltashot_size >= 0)
 					delta_tick = clients[i].last_acked_snapshot;
 				else
@@ -625,15 +625,19 @@ static void server_process_client_packet(NETPACKET *packet)
 			int64 tagtime;
 
 			clients[cid].last_acked_snapshot = msg_unpack_int();
+			tick = msg_unpack_int();
+			size = msg_unpack_int();
+			
+			/* check for errors */
+			if(msg_unpack_error() || size/4 > MAX_INPUT_SIZE)
+				return;
+			
 			if(clients[cid].last_acked_snapshot > 0)
 				clients[cid].snap_rate = SRVCLIENT_SNAPRATE_FULL;
 				
-			if(snapstorage_get(&clients[cid].snapshots, clients[cid].last_acked_snapshot, &tagtime, 0) >= 0)
+			if(snapstorage_get(&clients[cid].snapshots, clients[cid].last_acked_snapshot, &tagtime, 0, 0) >= 0)
 				clients[cid].latency = (int)(((time_get()-tagtime)*1000)/time_freq());
-			
-			tick = msg_unpack_int();
-			size = msg_unpack_int();
-			
+
 			input = &clients[cid].inputs[clients[cid].current_input];
 			input->timeleft = server_tick_start_time(tick)-time_get();
 			input->pred_tick = tick;