From 3106a92e8b7ffdcec15b1bea3f167ce466da19f0 Mon Sep 17 00:00:00 2001
From: SwitchKaze <azeonus@gmail.com>
Date: Sat, 29 Feb 2020 23:14:49 -0500
Subject: [PATCH] Prohibit modification of built-in colors

In addition, fixes a bug where loading a custom color using command line params exhibits strange behavior.
---
 src/d_main.c      |  4 ++++
 src/dehacked.c    |  4 ++--
 src/info.c        |  1 -
 src/lua_infolib.c | 21 ++++++++++-----------
 src/m_menu.c      |  9 ++++-----
 5 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/src/d_main.c b/src/d_main.c
index 904ab3bf13..9fcf349dbb 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -1151,6 +1151,10 @@ void D_SRB2Main(void)
 
 	if (M_CheckParm("-password") && M_IsNextParm())
 		D_SetPassword(M_GetNextParm());
+	
+	// player setup menu colors must be initialized before
+	// any wad file is added, as they may contain colors themselves
+	M_InitPlayerSetupColors();
 
 	// add any files specified on the command line with -file wadfile
 	// to the wad list
diff --git a/src/dehacked.c b/src/dehacked.c
index 4d12587dde..e2627d2417 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -4629,11 +4629,11 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
 				{
 					if (i == 0 && word2[0] != '0') // If word2 isn't a number
 						i = get_skincolor(word2); // find a skincolor by name
-					if (i < numskincolors && i > 0)
+					if (i < numskincolors && i >= (INT32)SKINCOLOR_FIRSTFREESLOT)
 						readskincolor(f, i);
 					else
 					{
-						deh_warning("Skincolor %d out of range (1 - %d)", i, numskincolors-1);
+						deh_warning("Skincolor %d out of range (%d - %d)", i, SKINCOLOR_FIRSTFREESLOT, numskincolors-1);
 						ignorelines(f);
 					}
 				}
diff --git a/src/info.c b/src/info.c
index d592da8b88..e8e5bc89b3 100644
--- a/src/info.c
+++ b/src/info.c
@@ -21773,7 +21773,6 @@ void P_PatchInfoTables(void)
 		skincolors[i].accessible = false;
 		skincolors[i].name[0] = '\0';
 	}
-	numskincolors = SKINCOLOR_FIRSTFREESLOT;
 	for (i = MT_FIRSTFREESLOT; i <= MT_LASTFREESLOT; i++)
 		mobjinfo[i].doomednum = -1;
 }
diff --git a/src/lua_infolib.c b/src/lua_infolib.c
index fd9cd319f1..372b746d4f 100644
--- a/src/lua_infolib.c
+++ b/src/lua_infolib.c
@@ -1516,8 +1516,8 @@ static int lib_setSkinColor(lua_State *L)
 	lua_remove(L, 1); // don't care about skincolors[] userdata.
 	{
 		cnum = (UINT8)luaL_checkinteger(L, 1);
-		if (!cnum || cnum >= numskincolors)
-			return luaL_error(L, "skincolors[] index %d out of range (1 - %d)", cnum, numskincolors-1);
+		if (cnum < SKINCOLOR_FIRSTFREESLOT || cnum >= numskincolors)
+			return luaL_error(L, "skincolors[] index %d out of range (%d - %d)", cnum, SKINCOLOR_FIRSTFREESLOT, numskincolors-1);
 		info = &skincolors[cnum]; // get the skincolor to assign to.
 	}
 	luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table.
@@ -1615,8 +1615,8 @@ static int skincolor_set(lua_State *L)
 	I_Assert(info != NULL);
 	I_Assert(info >= skincolors);
 
-	if (info-skincolors >= numskincolors)
-		return luaL_error(L, "skincolors[] index %d does not exist", info-skincolors);
+	if (info-skincolors < SKINCOLOR_FIRSTFREESLOT || info-skincolors >= numskincolors)
+		return luaL_error(L, "skincolors[] index %d out of range (%d - %d)", info-skincolors, SKINCOLOR_FIRSTFREESLOT, numskincolors-1);
 
 	if (fastcmp(field,"name")) {
 		const char* n = luaL_checkstring(L, 3);
@@ -1640,13 +1640,9 @@ static int skincolor_set(lua_State *L)
 		info->invshade = (UINT8)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"chatcolor"))
 		info->chatcolor = (UINT16)luaL_checkinteger(L, 3);
-	else if (fastcmp(field,"accessible")) {
-		boolean v = lua_isboolean(L,3) ? lua_toboolean(L, 3) : true;
-		if (info-skincolors < FIRSTSUPERCOLOR && v != info->accessible)
-			return luaL_error(L, "skincolors[] index %d is a standard color; accessibility changes are prohibited.", info-skincolors);
-		else
-			info->accessible = v;
-	} else
+	else if (fastcmp(field,"accessible"))
+		info->accessible = lua_isboolean(L,3);
+	else
 		CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "skincolor_t", field);
 	return 1;
 }
@@ -1678,8 +1674,11 @@ static int colorramp_get(lua_State *L)
 static int colorramp_set(lua_State *L)
 {
 	UINT8 *colorramp = *((UINT8 **)luaL_checkudata(L, 1, META_COLORRAMP));
+	UINT16 cnum = (UINT16)(((uint8_t*)colorramp - (uint8_t*)(skincolors[0].ramp))/sizeof(skincolor_t));
 	UINT32 n = luaL_checkinteger(L, 2);
 	UINT8 i = (UINT8)luaL_checkinteger(L, 3);
+	if (cnum < SKINCOLOR_FIRSTFREESLOT || cnum >= numskincolors)
+		return luaL_error(L, "skincolors[] index %d out of range (%d - %d)", cnum, SKINCOLOR_FIRSTFREESLOT, numskincolors-1);
 	if (n >= COLORRAMPSIZE)
 		return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' index %d out of range (0 - %d)", n, COLORRAMPSIZE-1);
 	if (hud_running)
diff --git a/src/m_menu.c b/src/m_menu.c
index 76ac7e0865..ec3f59b41b 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -3860,8 +3860,6 @@ void M_Init(void)
 #ifndef NONET
 	CV_RegisterVar(&cv_serversort);
 #endif
-
-	M_InitPlayerSetupColors();
 }
 
 void M_InitCharacterTables(void)
@@ -11427,7 +11425,7 @@ void M_AddMenuColor(UINT8 color) {
 		return;
 	}
 
-	c = (menucolor_t *)Z_Malloc(sizeof(menucolor_t), PU_STATIC, NULL);
+	c = (menucolor_t *)malloc(sizeof(menucolor_t));
 	c->color = color;
 	if (menucolorhead == NULL) {
 		c->next = c;
@@ -11561,6 +11559,7 @@ UINT8 M_GetColorAfter(UINT8 color) {
 
 void M_InitPlayerSetupColors(void) {
 	UINT8 i;
+	numskincolors = SKINCOLOR_FIRSTFREESLOT;
 	menucolorhead = menucolortail = NULL;
 	for (i=0; i<numskincolors; i++)
 		M_AddMenuColor(i);
@@ -11576,9 +11575,9 @@ void M_FreePlayerSetupColors(void) {
 		if (look != menucolortail) {
 			tmp = look;
 			look = look->next;
-			Z_Free(tmp);
+			free(tmp);
 		} else {
-			Z_Free(look);
+			free(look);
 			return;
 		}
 	}
-- 
GitLab