From 24aafa6dacaa03a73674ef049ceeae102693438f Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Mon, 3 Sep 2018 15:43:36 +0100
Subject: [PATCH 1/5] UDP_Socket: Add missing limit checks for s, for client
 and broadcast addresses

---
 src/i_tcp.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/i_tcp.c b/src/i_tcp.c
index 6488e9845..5c6606668 100644
--- a/src/i_tcp.c
+++ b/src/i_tcp.c
@@ -1044,7 +1044,7 @@ static boolean UDP_Socket(void)
 	if (gaie == 0)
 	{
 		runp = ai;
-		while (runp != NULL)
+		while (runp != NULL && s < MAXNETNODES+1)
 		{
 			memcpy(&clientaddress[s], runp->ai_addr, runp->ai_addrlen);
 			s++;
@@ -1064,7 +1064,7 @@ static boolean UDP_Socket(void)
 	if (gaie == 0)
 	{
 		runp = ai;
-		while (runp != NULL)
+		while (runp != NULL && s < MAXNETNODES+1)
 		{
 			memcpy(&broadcastaddress[s], runp->ai_addr, runp->ai_addrlen);
 			s++;
@@ -1087,7 +1087,7 @@ static boolean UDP_Socket(void)
 		if (gaie == 0)
 		{
 			runp = ai;
-			while (runp != NULL)
+			while (runp != NULL && s < MAXNETNODES+1)
 			{
 				memcpy(&broadcastaddress[s], runp->ai_addr, runp->ai_addrlen);
 				s++;

From 846bddfdcf9514e8164bd1157c58ab2ac614ae8a Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Mon, 3 Sep 2018 15:52:22 +0100
Subject: [PATCH 2/5] SOCK_Send: Fix what appears to be a mistaken use of i
 instead of j

---
 src/i_tcp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/i_tcp.c b/src/i_tcp.c
index 5c6606668..3b609914d 100644
--- a/src/i_tcp.c
+++ b/src/i_tcp.c
@@ -707,10 +707,10 @@ static void SOCK_Send(void)
 			{
 				if (myfamily[i] == broadcastaddress[j].any.sa_family)
 				{
-					if (broadcastaddress[i].any.sa_family == AF_INET)
+					if (broadcastaddress[j].any.sa_family == AF_INET)
 						d = d4;
 #ifdef HAVE_IPV6
-					else if (broadcastaddress[i].any.sa_family == AF_INET6)
+					else if (broadcastaddress[j].any.sa_family == AF_INET6)
 						d = d6;
 #endif
 					else

From 7b083f07cd306ca8790427b0257ca1f06f7d3a3e Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Mon, 3 Sep 2018 15:56:02 +0100
Subject: [PATCH 3/5] UDP_Socket: I doubt client addresses are meant to be
 included in the total for broadcast addresses

---
 src/i_tcp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/i_tcp.c b/src/i_tcp.c
index 3b609914d..d11be4285 100644
--- a/src/i_tcp.c
+++ b/src/i_tcp.c
@@ -1059,6 +1059,9 @@ static boolean UDP_Socket(void)
 		clientaddress[s].ip4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); //GetLocalAddress(); // my own ip
 		s++;
 	}
+
+	s = 0;
+
 	// setup broadcast adress to BROADCASTADDR entry
 	gaie = I_getaddrinfo("255.255.255.255", "0", &hints, &ai);
 	if (gaie == 0)

From ea06e8a62b42d4e85112742ca668a7a6495beaf9 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Mon, 3 Sep 2018 20:53:40 +0100
Subject: [PATCH 4/5] SOCK_Send: Split the actual sending data parts into a new
 function, SOCK_SendToAddr, to make everything look a bit neater in general

---
 src/i_tcp.c | 59 ++++++++++++++++++-----------------------------------
 1 file changed, 20 insertions(+), 39 deletions(-)

diff --git a/src/i_tcp.c b/src/i_tcp.c
index d11be4285..16e7bf2f6 100644
--- a/src/i_tcp.c
+++ b/src/i_tcp.c
@@ -686,14 +686,29 @@ static boolean SOCK_CanGet(void)
 #endif
 
 #ifndef NONET
-static void SOCK_Send(void)
+static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr)
 {
-	ssize_t c = ERRSOCKET;
 	socklen_t d4 = (socklen_t)sizeof(struct sockaddr_in);
 #ifdef HAVE_IPV6
 	socklen_t d6 = (socklen_t)sizeof(struct sockaddr_in6);
 #endif
 	socklen_t d, da = (socklen_t)sizeof(mysockaddr_t);
+
+	switch (sockaddr->any.sa_family)
+	{
+		case AF_INET:  d = d4; break;
+#ifdef HAVE_IPV6
+		case AF_INET6: d = d6; break;
+#endif
+		default:       d = da; break;
+	}
+
+	return sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d);
+}
+
+static void SOCK_Send(void)
+{
+	ssize_t c = ERRSOCKET;
 	size_t i, j;
 
 	if (!nodeconnected[doomcom->remotenode])
@@ -706,19 +721,7 @@ static void SOCK_Send(void)
 			for (j = 0; j < broadcastaddresses; j++)
 			{
 				if (myfamily[i] == broadcastaddress[j].any.sa_family)
-				{
-					if (broadcastaddress[j].any.sa_family == AF_INET)
-						d = d4;
-#ifdef HAVE_IPV6
-					else if (broadcastaddress[j].any.sa_family == AF_INET6)
-						d = d6;
-#endif
-					else
-						d = da;
-
-					c = sendto(mysockets[i], (char *)&doomcom->data, doomcom->datalength, 0,
-						&broadcastaddress[j].any, d);
-				}
+					SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]);
 			}
 		}
 		return;
@@ -728,35 +731,13 @@ static void SOCK_Send(void)
 		for (i = 0; i < mysocketses; i++)
 		{
 			if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family)
-			{
-				if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET)
-					d = d4;
-#ifdef HAVE_IPV6
-				else if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET6)
-					d = d6;
-#endif
-				else
-					d = da;
-
-				sendto(mysockets[i], (char *)&doomcom->data, doomcom->datalength, 0,
-					&clientaddress[doomcom->remotenode].any, d);
-			}
+				SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]);
 		}
 		return;
 	}
 	else
 	{
-		if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET)
-			d = d4;
-#ifdef HAVE_IPV6
-		else if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET6)
-			d = d6;
-#endif
-		else
-			d = da;
-
-		c = sendto(nodesocket[doomcom->remotenode], (char *)&doomcom->data, doomcom->datalength, 0,
-			&clientaddress[doomcom->remotenode].any, d);
+		c = SOCK_SendToAddr(nodesocket[doomcom->remotenode], &clientaddress[doomcom->remotenode]);
 	}
 
 	if (c == ERRSOCKET && errno != ECONNREFUSED && errno != EWOULDBLOCK)

From ba88f8ebb66a55bf6d4966e72649f5151195e258 Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Tue, 11 Sep 2018 15:01:05 -0400
Subject: [PATCH 5/5] Smarter string digit parsing; allow alpha-only values

* GetDefaultColormap and CheckDefaultColormapValues methods
---
 src/p_setup.c |  11 ++-
 src/r_data.c  | 182 +++++++++++++++++++++++++++++++++++++++-----------
 src/r_data.h  |   2 +
 3 files changed, 149 insertions(+), 46 deletions(-)

diff --git a/src/p_setup.c b/src/p_setup.c
index b503b6a58..77d53812c 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1472,12 +1472,11 @@ static void P_LoadRawSideDefs2(void *data)
 			case 606: //SoM: 4/4/2000: Just colormap transfer
 				// SoM: R_CreateColormap will only create a colormap in software mode...
 				// Perhaps we should just call it instead of doing the calculations here.
-				if (
-					((rendermode == render_soft || rendermode == render_none) && (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#'))
-#ifdef HWRENDER
-					|| (msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6])
-					|| (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6])
-#endif
+				if (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#'
+					|| (msd->toptexture[0] >= 'a' && msd->toptexture[0] <= 'z' && !msd->toptexture[1])
+					|| (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'Z' && !msd->toptexture[1])
+					|| (msd->bottomtexture[0] >= 'a' && msd->bottomtexture[0] <= 'z' && !msd->bottomtexture[1])
+					|| (msd->bottomtexture[0] >= 'A' && msd->bottomtexture[0] <= 'Z' && !msd->bottomtexture[1])
 				)
 				{
 					sec->extra_colormap = sec->spawn_extra_colormap = R_CreateColormap(msd->toptexture, msd->midtexture,
diff --git a/src/r_data.c b/src/r_data.c
index 4358f7536..958eeeb37 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1346,6 +1346,49 @@ extracolormap_t *R_CreateDefaultColormap(boolean lighttable)
 	return exc;
 }
 
+//
+// R_GetDefaultColormap()
+//
+extracolormap_t *R_GetDefaultColormap(void)
+{
+#ifdef COLORMAPREVERSELIST
+	extracolormap_t *exc;
+#endif
+
+	if (!extra_colormaps)
+		return (extra_colormaps = R_CreateDefaultColormap(true));
+
+#ifdef COLORMAPREVERSELIST
+	for (exc = extra_colormaps; exc->next; exc = exc->next);
+	return exc;
+#else
+	return extra_colormaps;
+#endif
+}
+
+//
+// R_CheckDefaultColormap()
+//
+boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams)
+{
+	if (!extra_colormap)
+		return true;
+	else
+		return (
+			(!checkparams ? true :
+				(extra_colormap->fadestart == 0
+					&& extra_colormap->fadeend == 31
+					&& !extra_colormap->fog)
+				)
+			&& (!checkrgba ? true : extra_colormap->rgba == 0)
+			&& (!checkfadergba ? true : extra_colormap->fadergba == 0x19000000)
+#ifdef EXTRACOLORMAPLUMPS
+			&& extra_colormap->lump == LUMPERROR
+			&& extra_colormap->lumpname[0] == 0
+#endif
+			);
+}
+
 //
 // R_AddColormapToList
 //
@@ -1562,77 +1605,133 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap)
 
 extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 {
-	boolean fog = false;
 	extracolormap_t *extra_colormap, *exc;
 
-	UINT8 cr, cg, cb, ca, cfr, cfg, cfb, cfa;
+	// default values
+	UINT8 cr = 0, cg = 0, cb = 0, ca = 0, cfr = 0, cfg = 0, cfb = 0, cfa = 25;
 	UINT32 fadestart = 0, fadeend = 31;
-
-	INT32 rgba, fadergba;
+	boolean fog = false;
+	INT32 rgba = 0, fadergba = 0x19000000;
 
 	size_t dbg_i = 0;
 
 #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
 #define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0)
-	if (p1[0] == '#')
-	{
-		cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2]));
-		cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4]));
-		cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6]));
 
-		if (p1[7] >= 'a' && p1[7] <= 'z')
-			ca = (p1[7] - 'a');
-		else if (p1[7] >= 'A' && p1[7] <= 'Z')
-			ca = (p1[7] - 'A');
+	// Get base colormap value
+	// First alpha-only, then full value
+	if (p1[0] >= 'a' && p1[0] <= 'z' && !p1[1])
+		ca = (p1[0] - 'a');
+	else if (p1[0] == '#' && p1[1] >= 'a' && p1[1] <= 'z' && !p1[2])
+		ca = (p1[1] - 'a');
+	else if (p1[0] >= 'A' && p1[0] <= 'Z' && !p1[1])
+		ca = (p1[0] - 'A');
+	else if (p1[0] == '#' && p1[1] >= 'A' && p1[1] <= 'Z' && !p1[2])
+		ca = (p1[1] - 'A');
+	else if (p1[0] == '#')
+	{
+		// For each subsequent value, the value before it must exist
+		// If we don't get every value, then set alpha to max
+		if (p1[1] && p1[2])
+		{
+			cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2]));
+			if (p1[3] && p1[4])
+			{
+				cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4]));
+				if (p1[5] && p1[6])
+				{
+					cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6]));
+
+					if (p1[7] >= 'a' && p1[7] <= 'z')
+						ca = (p1[7] - 'a');
+					else if (p1[7] >= 'A' && p1[7] <= 'Z')
+						ca = (p1[7] - 'A');
+					else
+						ca = 25;
+				}
+				else
+					ca = 25;
+			}
+			else
+				ca = 25;
+		}
 		else
 			ca = 25;
-
-		rgba = cr + (cg << 8) + (cb << 16) + (ca << 24);
-	}
-	else
-	{
-		cr = cg = cb = ca = 0;
-		rgba = 0;
 	}
 
 #define NUMFROMCHAR(c) (c >= '0' && c <= '9' ? c - '0' : 0)
+
+	// Get parameters like fadestart, fadeend, and the fogflag
 	if (p2[0] == '#')
 	{
-		// Get parameters like fadestart, fadeend, and the fogflag
-		fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10);
-		fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10);
+		if (p2[1])
+		{
+			fog = (boolean)NUMFROMCHAR(p2[1]);
+			if (p2[2] && p2[3])
+			{
+				fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10);
+				if (p2[4] && p2[5])
+					fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10);
+			}
+		}
+
 		if (fadestart > 30)
 			fadestart = 0;
 		if (fadeend > 31 || fadeend < 1)
 			fadeend = 31;
-		fog = (boolean)NUMFROMCHAR(p2[1]);
 	}
+
 #undef NUMFROMCHAR
 
-	if (p3[0] == '#')
+	// Get fade (dark) colormap value
+	// First alpha-only, then full value
+	if (p3[0] >= 'a' && p3[0] <= 'z' && !p3[1])
+		cfa = (p3[0] - 'a');
+	else if (p3[0] == '#' && p3[1] >= 'a' && p3[1] <= 'z' && !p3[2])
+		cfa = (p3[1] - 'a');
+	else if (p3[0] >= 'A' && p3[0] <= 'Z' && !p3[1])
+		cfa = (p3[0] - 'A');
+	else if (p3[0] == '#' && p3[1] >= 'A' && p3[1] <= 'Z' && !p3[2])
+		cfa = (p3[1] - 'A');
+	else if (p3[0] == '#')
 	{
-		cfr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2]));
-		cfg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4]));
-		cfb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6]));
+		// For each subsequent value, the value before it must exist
+		// If we don't get every value, then set alpha to max
+		if (p3[1] && p3[2])
+		{
+			cfr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2]));
+			if (p3[3] && p3[4])
+			{
+				cfg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4]));
+				if (p3[5] && p3[6])
+				{
+					cfb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6]));
 
-		if (p1[7] >= 'a' && p1[7] <= 'z')
-			cfa = (p1[7] - 'a');
-		else if (p1[7] >= 'A' && p1[7] <= 'Z')
-			cfa = (p1[7] - 'A');
+					if (p3[7] >= 'a' && p3[7] <= 'z')
+						cfa = (p3[7] - 'a');
+					else if (p3[7] >= 'A' && p3[7] <= 'Z')
+						cfa = (p3[7] - 'A');
+					else
+						cfa = 25;
+				}
+				else
+					cfa = 25;
+			}
+			else
+				cfa = 25;
+		}
 		else
 			cfa = 25;
-
-		fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24);
-	}
-	else
-	{
-		cfr = cfg = cfb = 0;
-		cfa = 25;
-		fadergba = 0x19000000; // default alpha for fade, (25 << 24)
 	}
 #undef ALPHA2INT
 #undef HEX2INT
 
+	// Pack rgba values into combined var
+	// OpenGL also uses this instead of lighttables for rendering
+	rgba = cr + (cg << 8) + (cb << 16) + (ca << 24);
+	fadergba = cfr + (cfg << 8) + (cfb << 16) + (cfa << 24);
+
+	// Look for existing colormaps
 	for (exc = extra_colormaps; exc; exc = exc->next)
 	{
 #ifdef EXTRACOLORMAPLUMPS
@@ -1672,6 +1771,9 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
 	extra_colormap->lumpname[0] = 0;
 #endif
 
+	// Having lighttables for alpha-only entries is kind of pointless,
+	// but if there happens to be a matching rgba entry that is NOT alpha-only (but has same rgb values),
+	// then it needs this lighttable because we share matching entries.
 	extra_colormap->colormap = R_CreateLightTable(extra_colormap);
 
 	R_AddColormapToList(extra_colormap);
diff --git a/src/r_data.h b/src/r_data.h
index 718abeccc..95ea44a83 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -106,6 +106,8 @@ INT32 R_CheckTextureNumForName(const char *name);
 void R_ReInitColormaps(UINT16 num);
 void R_ClearColormaps(void);
 extracolormap_t *R_CreateDefaultColormap(boolean lighttable);
+extracolormap_t *R_GetDefaultColormap(void);
+boolean R_CheckDefaultColormapValues(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams);
 void R_AddColormapToList(extracolormap_t *extra_colormap);
 lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap);
 extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3);