From 4497e8a154f53cd5947a6ee5aa65cf99be57152e Mon Sep 17 00:00:00 2001
From: zhailiangliang <zhailiangliang@loongson.cn>
Date: Tue, 7 May 2024 11:35:52 +0000
Subject: [PATCH] Fix potential overflow bug while parsing port in function
 cfg_mark_ports

---
 util/config_file.c | 76 ++++++++++++++++++++++++++++++----------------
 1 file changed, 50 insertions(+), 26 deletions(-)

diff --git a/util/config_file.c b/util/config_file.c
index 2b67d4c1..4a3b7d77 100644
--- a/util/config_file.c
+++ b/util/config_file.c
@@ -42,6 +42,7 @@
 #include "config.h"
 #include <ctype.h>
 #include <stdarg.h>
+#include <errno.h>
 #ifdef HAVE_TIME_H
 #include <time.h>
 #endif
@@ -1772,6 +1773,38 @@ init_outgoing_availports(int* a, int num)
 	}
 }
 
+static int
+extract_port_from_str(const char* str, int max_port) {
+	char* endptr;
+	if (str == NULL || *str == '\0') {
+		log_err("str: '%s' is invalid", str);
+		return -1;
+	}
+
+	long int value = strtol(str, &endptr, 10);
+	if ((endptr == str) || (*endptr != '\0'))  {
+		log_err("cannot parse port number '%s'", str);
+		return -1;
+	}
+
+	if (errno == ERANGE) {
+                log_err("overflow occurred when parsing '%s'", str);
+		return -1;
+	}
+
+	if (value == 0 && strcmp(str, "0") != 0) {
+		log_err("cannot parse port number '%s'", str);
+		return -1;
+	}
+
+	if (value < 0 || value >= max_port) {
+		log_err(" '%s' is out of bounds [0, %d)", str, max_port);
+		return -1;
+	}
+
+	return (int)value;
+}
+
 int 
 cfg_mark_ports(const char* str, int allow, int* avail, int num)
 {
@@ -1782,53 +1815,44 @@ cfg_mark_ports(const char* str, int allow, int* avail, int num)
 		"options");
 #endif
 	if(!mid) {
-		int port = atoi(str);
-		if(port < 0) {
-			log_err("port number is negative: %d", port);
+		int port = extract_port_from_str(str, num);
+		if (port < 0) {
+			log_err("Failed to parse the port number");
 			return 0;
 		}
-		if(port == 0 && strcmp(str, "0") != 0) {
-			log_err("cannot parse port number '%s'", str);
-			return 0;
-		}
-		if(port < num)
-			avail[port] = (allow?port:0);
+		avail[port] = (allow?port:0);
 	} else {
-		int i, low, high = atoi(mid+1);
 		char buf[16];
-		if(high < 0) {
-			log_err("port number is negative: %d", high);
-			return 0;
-		}
-		if(high == 0 && strcmp(mid+1, "0") != 0) {
-			log_err("cannot parse port number '%s'", mid+1);
+		int i, low;
+		int high = extract_port_from_str(mid+1, num);
+		if (high < 0) {
+			log_err("Failed to parse the port number");
 			return 0;
 		}
+
 		if( (int)(mid-str)+1 >= (int)sizeof(buf) ) {
 			log_err("cannot parse port number '%s'", str);
 			return 0;
 		}
+
 		if(mid > str)
 			memcpy(buf, str, (size_t)(mid-str));
 		buf[mid-str] = 0;
-		low = atoi(buf);
-		if(low < 0) {
-			log_err("port number is negative: %d", low);
+		low = extract_port_from_str(buf, num);
+		if (low < 0) {
+			log_err("Failed to parse the port number");
 			return 0;
 		}
-		if(low == 0 && strcmp(buf, "0") != 0) {
-			log_err("cannot parse port number '%s'", buf);
+
+		if (low > high) {
+			log_err("Low value is greater than high value");
 			return 0;
 		}
-		if(high > num) {
-			/* Stop very high values from taking a long time. */
-			high = num;
-		}
+
 		for(i=low; i<=high; i++) {
 			if(i < num)
 				avail[i] = (allow?i:0);
 		}
-		return 1;
 	}
 	return 1;
 }
-- 
2.33.0

