浏览代码

Fix errors in overflow checks for String conversion to int

Current error checks for to_int and to_int64 do not issue overflow error
messages for INT64_MAX + 1, INT64_MAX + 2, and others close to the
limits. Likewise, error checks for hex_to_int, hex_to_int64 and bin_to_int64
issue false positive error messages for INT64_MIN or INT32_MIN. This commit
fixes these error checks.
Maganty Rushyendra 5 年之前
父节点
当前提交
7670e1fc79
共有 1 个文件被更改,包括 14 次插入14 次删除
  1. 14 14
      core/ustring.cpp

+ 14 - 14
core/ustring.cpp

@@ -1682,8 +1682,9 @@ int String::hex_to_int(bool p_with_prefix) const {
 		} else {
 		} else {
 			return 0;
 			return 0;
 		}
 		}
-
-		ERR_FAIL_COND_V_MSG(hex > INT32_MAX / 16, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + *this + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
+		// Check for overflow/underflow, with special case to ensure INT32_MIN does not result in error
+		bool overflow = ((hex > INT32_MAX / 16) && (sign == 1 || (sign == -1 && hex != (INT32_MAX >> 4) + 1))) || (sign == -1 && hex == (INT32_MAX >> 4) + 1 && c > '0');
+		ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + *this + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
 		hex *= 16;
 		hex *= 16;
 		hex += n;
 		hex += n;
 		s++;
 		s++;
@@ -1724,8 +1725,8 @@ int64_t String::hex_to_int64(bool p_with_prefix) const {
 		} else {
 		} else {
 			return 0;
 			return 0;
 		}
 		}
-
-		ERR_FAIL_COND_V_MSG(hex > INT64_MAX / 16, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small."));
+		bool overflow = ((hex > INT64_MAX / 16) && (sign == 1 || (sign == -1 && hex != (INT64_MAX >> 4) + 1))) || (sign == -1 && hex == (INT64_MAX >> 4) + 1 && c > '0');
+		ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small."));
 		hex *= 16;
 		hex *= 16;
 		hex += n;
 		hex += n;
 		s++;
 		s++;
@@ -1764,8 +1765,9 @@ int64_t String::bin_to_int64(bool p_with_prefix) const {
 		} else {
 		} else {
 			return 0;
 			return 0;
 		}
 		}
-
-		ERR_FAIL_COND_V_MSG(binary > INT64_MAX / 2, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small."));
+		// Check for overflow/underflow, with special case to ensure INT64_MIN does not result in error
+		bool overflow = ((binary > INT64_MAX / 2) && (sign == 1 || (sign == -1 && binary != (INT64_MAX >> 1) + 1))) || (sign == -1 && binary == (INT64_MAX >> 1) + 1 && c > '0');
+		ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small."));
 		binary *= 2;
 		binary *= 2;
 		binary += n;
 		binary += n;
 		s++;
 		s++;
@@ -1788,8 +1790,8 @@ int String::to_int() const {
 
 
 		CharType c = operator[](i);
 		CharType c = operator[](i);
 		if (c >= '0' && c <= '9') {
 		if (c >= '0' && c <= '9') {
-
-			ERR_FAIL_COND_V_MSG(integer > INT32_MAX / 10, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + *this + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
+			bool overflow = (integer > INT32_MAX / 10) || (integer == INT32_MAX / 10 && ((sign == 1 && c > '7') || (sign == -1 && c > '8')));
+			ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + *this + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
 			integer *= 10;
 			integer *= 10;
 			integer += c - '0';
 			integer += c - '0';
 
 
@@ -1813,16 +1815,14 @@ int64_t String::to_int64() const {
 	int64_t sign = 1;
 	int64_t sign = 1;
 
 
 	for (int i = 0; i < to; i++) {
 	for (int i = 0; i < to; i++) {
-
 		CharType c = operator[](i);
 		CharType c = operator[](i);
 		if (c >= '0' && c <= '9') {
 		if (c >= '0' && c <= '9') {
-
-			ERR_FAIL_COND_V_MSG(integer > INT64_MAX / 10, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small."));
+			bool overflow = (integer > INT64_MAX / 10) || (integer == INT64_MAX / 10 && ((sign == 1 && c > '7') || (sign == -1 && c > '8')));
+			ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small."));
 			integer *= 10;
 			integer *= 10;
 			integer += c - '0';
 			integer += c - '0';
 
 
 		} else if (integer == 0 && c == '-') {
 		} else if (integer == 0 && c == '-') {
-
 			sign = -sign;
 			sign = -sign;
 		}
 		}
 	}
 	}
@@ -1847,8 +1847,8 @@ int String::to_int(const char *p_str, int p_len) {
 
 
 		char c = p_str[i];
 		char c = p_str[i];
 		if (c >= '0' && c <= '9') {
 		if (c >= '0' && c <= '9') {
-
-			ERR_FAIL_COND_V_MSG(integer > INT32_MAX / 10, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + String(p_str).substr(0, to) + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
+			bool overflow = (integer > INT32_MAX / 10) || (integer == INT32_MAX / 10 && ((sign == 1 && c > '7') || (sign == -1 && c > '8')));
+			ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + String(p_str).substr(0, to) + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
 			integer *= 10;
 			integer *= 10;
 			integer += c - '0';
 			integer += c - '0';