[PATCH 3/7] alfred: gpsd: fix counter underflow on leading carriage return

Sven Eckelmann <[email protected]> Tue, 28 Jul 2026 15:32:12 +0200
Newsgroups org.open-mesh.lists.batman
Message-ID <[email protected]>
gpsd_read_gpsd() strips carriage returns from received lines by
decrementing the write position so the next character overwrites the '\r'.
A line starting with a carriage return causes an underflow to SIZE_MAX. The
read is aborted because it will be much larger than the size of the buffer.

Simplify the logic by going through the buffer and only incrementing the
write position on valid characters.

Fixes: 2b901d69d8fb ("alfred: Add support for passing location information over alfred.")
Signed-off-by: Sven Eckelmann <[email protected]>
---
 gpsd/alfred-gpsd.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/gpsd/alfred-gpsd.c b/gpsd/alfred-gpsd.c
index eecf914..6456e74 100644
--- a/gpsd/alfred-gpsd.c
+++ b/gpsd/alfred-gpsd.c
@@ -314,29 +314,33 @@ static void gpsd_read_gpsd(struct globals *globals)
 				sizeof(struct alfred_data) -
 				sizeof(*globals->gpsd_data);
 	bool eol = false;
+	size_t received;
 	char buf[4096];
 	ssize_t ret;
 	size_t cnt;
+	char c;
 
 	cnt = 0;
-	do {
-		ret = read(globals->gpsdata.gps_fd, &buf[cnt], 1);
+	for (received = 0; received < sizeof(buf) - 1 && !eol; received++) {
+		ret = read(globals->gpsdata.gps_fd, &c, 1);
 		if (ret != 1) {
 			gps_close(&globals->gpsdata);
 			globals->gpsdata.gps_fd = -1;
 			return;
 		}
 
-		switch (buf[cnt]) {
+		switch (c) {
 		case '\r':
-			cnt--;
+			/* strip carriage returns */
 			break;
 		case '\n':
 			eol = true;
-			buf[cnt] = '\0';
+			break;
+		default:
+			buf[cnt++] = c;
 			break;
 		}
-	} while (cnt++ < sizeof(buf) - 1 && !eol);
+	}
 
 	if (!eol) {
 		gps_close(&globals->gpsdata);
@@ -344,6 +348,8 @@ static void gpsd_read_gpsd(struct globals *globals)
 		return;
 	}
 
+	buf[cnt] = '\0';
+
 #define STARTSWITH(str, prefix)	strncmp(str, prefix, sizeof(prefix)-1)==0
 	if (STARTSWITH(buf, "{\"class\":\"TPV\"")) {
 		strncpy(globals->gpsd_data->tpv, buf, tpv_size);

-- 
2.47.3