jcs
/subtext
/amendments
/272
serial: Fix maximum input length calculation when reading serial data
This looks like it was copied from somewhere else since 'n' was never
getting used to affect 'len', so len could be a very large number of
outstanding bytes from the serial port (such as during a ZModem
transfer) which would then cause FSRead to write too much data to
ibuf, trashing the session object and possibly other malloc'd data.
Take the smaller of the serial port outstanding count, and the number
of bytes left in ibuf, when reading from the serial port.
Also enable printing of serial port errors since it's useful to see
overruns when the port speed is too high.
jcs made amendment 272 over 2 years ago
--- serial.c Tue Oct 25 16:47:00 2022
+++ serial.c Mon Nov 7 11:52:42 2022
@@ -418,15 +418,13 @@ serial_idle(void)
long count, i;
char *line;
-#if 0
SerStatus(serial_in_refnum, &status);
if (status.ctsHold != 0)
logger_printf("[modem] CTS set");
if (status.xOffHold != 0)
logger_printf("[modem] XOFF set");
if (status.cumErrs != 0)
- logger_printf("[modem] Reported errors %d", status.cumErrs);
-#endif
+ logger_printf("[modem] Reported errors: %d", status.cumErrs);
switch (the_serial_node.state) {
case SERIAL_STATE_IDLE: {
@@ -495,7 +493,7 @@ serial_input(struct session *session)
if (session->ending)
return 0;
-
+
if (serial_input_buf_len) {
/* drain input buf first */
n = MIN(serial_input_buf_len,
@@ -512,11 +510,14 @@ serial_input(struct session *session)
SerGetBuf(serial_in_refnum, &len);
if (!len)
return 0;
-
- n = MAX(len, sizeof(session->ibuf) - session->ibuflen);
- FSRead(serial_in_refnum, &len,
+
+ len = MIN(len, sizeof(session->ibuf) - session->ibuflen);
+ error = FSRead(serial_in_refnum, &len,
&session->ibuf + session->ibuflen);
- session->ibuflen += len;
+ if (error == noErr)
+ session->ibuflen += len;
+ else
+ logger_printf("[modem] Error from FSRead: %d", error);
return len;
}
@@ -528,7 +529,7 @@ serial_output(struct session *session)
return 0;
if (session->obuflen > sizeof(session->obuf)) {
- warn("bogus obuflen %d > %ld", session->obuflen,
+ warn("Bogus obuflen %d > %ld", session->obuflen,
sizeof(session->obuf));
session->ending = true;
session_close(session);