(svn r4142) - Fix [FS#74]: Incorrectly loaded settings from the config file when the signed uint32 variable would be negative.
authorDarkvater
Tue, 28 Mar 2006 21:51:14 +0000
changeset 3352 49d580a11385
parent 3351 79a35ca72b84
child 3353 2f6e03bd3c29
(svn r4142) - Fix [FS#74]: Incorrectly loaded settings from the config file when the signed uint32 variable would be negative.
macros.h
settings.c
--- a/macros.h	Mon Mar 27 14:28:56 2006 +0000
+++ b/macros.h	Tue Mar 28 21:51:14 2006 +0000
@@ -35,6 +35,12 @@
 	return a;
 }
 
+static inline uint clampu(uint a, uint min, uint max)
+{
+	if (a <= min) return min;
+	if (a >= max) return max;
+	return a;
+}
 
 static inline int32 BIGMULSS(int32 a, int32 b, int shift) {
 	return (int32)(((int64)(a) * (int64)(b)) >> (shift));
--- a/settings.c	Mon Mar 27 14:28:56 2006 +0000
+++ b/settings.c	Tue Mar 28 21:51:14 2006 +0000
@@ -583,15 +583,39 @@
 static void Write_ValidateSetting(void *ptr, const SettingDesc *sd, int32 val)
 {
 	const SettingDescBase *sdb = &sd->desc;
-	int32 min;
 
 	if (sdb->cmd != SDT_BOOLX && sdb->cmd != SDT_NUMX &&
 		  sdb->cmd != SDT_ONEOFMANY && sdb->cmd != SDT_MANYOFMANY) return;
 
-	/* Override the minimum value. No value below sdb->min, except special value 0 */
-	min = ((sdb->flags & SGF_0ISDISABLED) && val <= sdb->min) ? 0 : sdb->min;
 	/* We cannot know the maximum value of a bitset variable, so just have faith */
-	val = (sdb->cmd == SDT_MANYOFMANY) ? val : clamp(val, min, sdb->max);
+	if (sdb->cmd != SDT_MANYOFMANY) {
+		/* We need to take special care of the uint32 type as we receive from the function
+		 * a signed integer. While here also bail out on 64-bit settings as those are not
+		 * supported. Unsigned 8 and 16-bit variables are safe since they fit into a signed
+		 * 32-bit variable
+		 * TODO: Support 64-bit settings/variables */
+		switch (GetVarMemType(sd->save.conv)) {
+			case SLE_VAR_BL:
+			case SLE_VAR_I8:
+			case SLE_VAR_U8:
+			case SLE_VAR_I16:
+			case SLE_VAR_U16:
+			case SLE_VAR_I32: {
+				/* Override the minimum value. No value below sdb->min, except special value 0 */
+				int32 min = ((sdb->flags & SGF_0ISDISABLED) && val <= sdb->min) ? 0 : sdb->min;
+				val = clamp(val, min, sdb->max);
+			} break;
+			case SLE_VAR_U32: {
+				/* Override the minimum value. No value below sdb->min, except special value 0 */
+				uint min = ((sdb->flags & SGF_0ISDISABLED) && (uint)val <= (uint)sdb->min) ? 0 : sdb->min;
+				WriteValue(ptr, SLE_VAR_U32, (int64)clampu(val, min, sdb->max));
+				return;
+			}
+			case SLE_VAR_I64:
+			case SLE_VAR_U64:
+			default: NOT_REACHED(); break;
+		}
+	}
 
 	WriteValue(ptr, sd->save.conv, (int64)val);
 }