Thank you for the code review, Robert.

I have moved the buffer length check first, so I no longer
need the second 'has_prefix_len'.

I limit the 'atoi' replacement to 3 digits.  I have also added
a check for 'isascii', as is done four lines earlier.

I have restored the newline that removing 'puts' removed.
Good catch.

>   personally I'd question using any strcmp() type function for checking
>   just two chars:

Using strncmp seems more readable because the search string
appears together as "+ ", and it also looks more like the old code.
(But I see your point, and if you feel strongly about it,
I'm also happy to substitute your rewrite.)

Here is patch version 2:

diff --git a/mts/smtp/smtp.c b/mts/smtp/smtp.c
index 00efde50..e6b34e08 100644
--- a/mts/smtp/smtp.c
+++ b/mts/smtp/smtp.c
@@ -819,14 +819,15 @@ again: ;
     for (more = false; (buffer = netsec_readline(nsc, &buflen,
 						 &errstr)) != NULL ; ) {
 
 	if (doingEHLO
+	        && buflen > 4
 	        && has_prefix_len(buffer, buflen, "250")
-	        && (buffer[3] == '-' || doingEHLO == 2)
-	        && buffer[4]) {
+	        && (buffer[3] == '-' || doingEHLO == 2)) {
 	    if (doingEHLO == 2) {
-		if ((*ehlo = malloc ((size_t) (strlen (buffer + 4) + 1)))) {
-		    strcpy (*ehlo++, buffer + 4);
+		if ((*ehlo = malloc (buflen - 4 + 1))) {
+		    memcpy (*ehlo, buffer + 4, buflen - 4);
+		    *(*ehlo++ + buflen - 4) = '\0';
 		    *ehlo = NULL;
 		    if (ehlo >= EHLOkeys + MAXEHLO)
 			doingEHLO = 0;
 		} else
@@ -840,10 +841,14 @@ again: ;
 	for (; buflen > 0 && (!isascii (*bp) || !isdigit (*bp)); bp++, buflen--)
 	    continue;
 
 	cont = false;
-	code = atoi ((char *) bp);
-	bp += 3, buflen -= 3;
+	size_t len_limit = buflen < 3 ? 0 : buflen - 3;
+	for (code = 0;
+	     buflen > len_limit && isascii (*bp) && isdigit (*bp);
+	     bp++, buflen--) {
+	    code = code * 10 + (*bp - '0');
+	}
 	for (; buflen > 0 && isspace (*bp); bp++, buflen--)
 	    continue;
 	if (buflen > 0 && *bp == '-') {
 	    cont = true;
@@ -879,9 +884,9 @@ again: ;
 	if (more)
 	    continue;
 	if (sm_reply.code < 100) {
 	    if (sm_verbose) {
-		puts(sm_reply.text);
+		printf("%.*s\n", sm_reply.length, sm_reply.text);
 		fflush (stdout);
 	    }
 	    goto again;
 	}
@@ -1046,9 +1051,10 @@ sm_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
 	    return NOTOK;
 	}
 
 	if (!has_prefix_len(line, len, "334 ")) {
-	    netsec_err(errstr, "Improper SASL protocol response: %s", line);
+	    netsec_err(errstr, "Improper SASL protocol response: %.*s",
+	               (int) len, line);
 	    return NOTOK;
 	}
 
 	if (len == 4) {
@@ -1098,11 +1104,13 @@ sm_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
 	    return NOTOK;
 
 	if (!has_prefix_len(line, len, "235 ")) {
 	    if (len > 4)
-		netsec_err(errstr, "Authentication failed: %s", line + 4);
+		netsec_err(errstr, "Authentication failed: %.*s",
+		           (int) len - 4, line + 4);
 	    else
-		netsec_err(errstr, "Authentication failed: %s", line);
+		netsec_err(errstr, "Authentication failed: %.*s",
+		           (int) len, line);
 	    return NOTOK;
 	}
 	break;
 
diff --git a/uip/popsbr.c b/uip/popsbr.c
index d0059cb2..86fe019e 100644
--- a/uip/popsbr.c
+++ b/uip/popsbr.c
@@ -391,9 +391,9 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
 		/*
 		 * If the protocol is being followed correctly, should just
 		 * be a "+ ", nothing else.
 		 */
-		if (len != 2 || strcmp(line, "+ ") != 0) {
+		if (len != 2 || strncmp(line, "+ ", 2) != 0) {
 		    netsec_err(errstr, "Did not get expected blank response "
 			       "for initial challenge response");
 		    return NOTOK;
 		}
@@ -446,9 +446,9 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
 	 * If we get an -ERR reply, bubble that back up
 	 */
 
 	if (has_prefix_len(line, len, "-ERR")) {
-	    netsec_err(errstr, "%s", line);
+	    netsec_err(errstr, "%.*s", (int) len, line);
 	    return NOTOK;
 	}
 
 	/*
@@ -508,9 +508,9 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
 	if (line == NULL)
 	    return NOTOK;
 
 	if (!has_prefix_len(line, len, "+OK")) {
-	    netsec_err(errstr, "Authentication failed: %s", line);
+	    netsec_err(errstr, "Authentication failed: %.*s", (int) len, line);
 	    return NOTOK;
 	}
 	break;
 

Reply via email to