New function 'has_prefix_len' works similarly to 'has_prefix' but
accepts a character pointer and length instead of a C string.

Update 16 callers of has_prefix that could more succinctly or more
correctly call has_prefix_len.

 
diff --git a/sbr/utils.h b/sbr/utils.h
index b3ec98b0..4477b1d5 100644
--- a/sbr/utils.h
+++ b/sbr/utils.h
@@ -73,6 +73,7 @@ void abortcpy(char *, const char *, size_t);
 #define ABORTCPY(dest, src) abortcpy(dest, src, sizeof (dest))
 
 bool has_prefix(const char *, const char *) PURE;
+bool has_prefix_len(const char *, size_t, const char *) PURE;
 bool has_suffix(const char *, const char *) PURE;
 bool has_suffix_c(const char *, int) PURE;
 void trim_suffix_c(char *, int);
diff --git a/sbr/utils.c b/sbr/utils.c
index 2951564c..3e84a0af 100644
--- a/sbr/utils.c
+++ b/sbr/utils.c
@@ -457,6 +457,21 @@ has_prefix(const char *s, const char *prefix)
 }
 
 
+/* has_prefix_len returns true if non-NULL s of length len
+ * starts with non-NULL prefix. */
+bool
+has_prefix_len(const char *s, size_t len, const char *prefix)
+{
+    while (len > 0 && *prefix && *s == *prefix) {
+        s++;
+        len--;
+        prefix++;
+    }
+
+    return *prefix == '\0';
+}
+
+
 /* has_suffix returns true if non-NULL s ends with non-NULL suffix. */
 bool
 has_suffix(const char *s, const char *suffix)
diff --git a/mts/smtp/smtp.c b/mts/smtp/smtp.c
index a9adfcc5..cf16250b 100644
--- a/mts/smtp/smtp.c
+++ b/mts/smtp/smtp.c
@@ -820,7 +820,7 @@ again: ;
 						 &errstr)) != NULL ; ) {
 
 	if (doingEHLO
-	        && has_prefix(buffer, "250")
+	        && has_prefix_len(buffer, buflen, "250")
 	        && (buffer[3] == '-' || doingEHLO == 2)
 	        && buffer[4]) {
 	    if (doingEHLO == 2) {
@@ -1046,7 +1046,7 @@ sm_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
 	    return NOTOK;
 	}
 
-	if (!has_prefix(line, "334 ")) {
+	if (!has_prefix_len(line, len, "334 ")) {
 	    netsec_err(errstr, "Improper SASL protocol response: %s", line);
 	    return NOTOK;
 	}
@@ -1097,7 +1097,7 @@ sm_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
 	if (line == NULL)
 	    return NOTOK;
 
-	if (!has_prefix(line, "235 ")) {
+	if (!has_prefix_len(line, len, "235 ")) {
 	    if (len > 4)
 		netsec_err(errstr, "Authentication failed: %s", line + 4);
 	    else
diff --git a/uip/imaptest.c b/uip/imaptest.c
index 9e19aac6..d4cf78d6 100644
--- a/uip/imaptest.c
+++ b/uip/imaptest.c
@@ -295,18 +295,20 @@ main (int argc, char **argv)
 	die("%s", errstr);
     }
 
-    if (has_prefix(cp, "* BYE")) {
+    if (has_prefix_len(cp, len, "* BYE")) {
 	fprintf(stderr, "Connection rejected: %s\n", cp + 5);
 	goto finish;
     }
 
-    if (!has_prefix(cp, "* OK") && !has_prefix(cp, "* PREAUTH")) {
+    if (!has_prefix_len(cp, len, "* OK") &&
+        !has_prefix_len(cp, len, "* PREAUTH")) {
 	fprintf(stderr, "Invalid server response: %s\n", cp);
 	goto finish;
     }
 
-    if ((p = strchr(cp + 2, ' ')) && *(p + 1) != '\0' &&
-	has_prefix(p + 1, "[CAPABILITY ")) {
+    if (len > 2 && (p = memrchr(cp + 2, ' ', len - 2)) &&
+	len > (unsigned long int) (p + 1 - cp) &&
+	has_prefix_len(p + 1, len - (p + 1 - cp), "[CAPABILITY ")) {
 	/*
 	 * Parse the capability list out to the end
 	 */
@@ -911,6 +913,7 @@ get_imap_response(netsec_context *nsc, const char *token, char **tokenresponse,
 		  char **status, bool condok, bool failerr, char **errstr)
 {
     char *line;
+    size_t len;
     struct imap_cmd *cmd;
     bool numerrs = false;
 
@@ -919,15 +922,16 @@ get_imap_response(netsec_context *nsc, const char *token, char **tokenresponse,
 
 getline:
     while (cmdqueue) {
-	if (!(line = netsec_readline(nsc, NULL, errstr)))
+	if (!(line = netsec_readline(nsc, &len, errstr)))
 	    return NOTOK;
-	if (has_prefix(line, "* ") && *(line + 2) != '\0') {
-	    if (token && tokenresponse && has_prefix(line + 2, token)) {
+	if (has_prefix_len(line, len, "* ")) {
+	    if (token && tokenresponse &&
+                has_prefix_len(line + 2, len - 2, token)) {
 		if (*tokenresponse)
 		    free(*tokenresponse);
 		*tokenresponse = getcpy(line + 2);
 	    }
-	} if (condok && has_prefix(line, "+")) {
+	} if (condok && has_prefix_len(line, len, "+")) {
 	    if (status) {
 		*status = getcpy(line);
 	    }
@@ -938,7 +942,7 @@ getline:
 	    return OK;
 	} else {
 
-	    if (has_prefix(line, cmdqueue->tag)) {
+	    if (has_prefix_len(line, len, cmdqueue->tag)) {
 		cmd = cmdqueue;
 		if (timestamp)
 		    ts_report(&cmd->start, "Command (%s) execution time",
@@ -947,7 +951,7 @@ getline:
 		free(cmd);
 	    } else {
 		for (cmd = cmdqueue; cmd->next != NULL; cmd = cmd->next) {
-		    if (has_prefix(line, cmd->next->tag)) {
+		    if (has_prefix_len(line, len, cmd->next->tag)) {
 		        struct imap_cmd *cmd2 = cmd->next;
 			cmd->next = cmd->next->next;
 			if (failerr && strncmp(line + strlen(cmd2->tag),
diff --git a/uip/mhoutsbr.c b/uip/mhoutsbr.c
index 6f80bafc..4cc01908 100644
--- a/uip/mhoutsbr.c
+++ b/uip/mhoutsbr.c
@@ -347,7 +347,7 @@ writeQuoted (CT ct, FILE *out)
 	 * doesn't falsely match an mbox delimiter.
 	 */
 	cp = bufp;
-	if (gotlen >= 5 && has_prefix(cp, "From ")) {
+	if (has_prefix_len(cp, gotlen, "From ")) {
 	    fprintf(out, "=%02X", (unsigned)'F');
 	    cp++;
 	    n += 3;
diff --git a/uip/popsbr.c b/uip/popsbr.c
index 89fc4cac..1df16d09 100644
--- a/uip/popsbr.c
+++ b/uip/popsbr.c
@@ -446,7 +446,7 @@ 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(line, "-ERR")) {
+	if (has_prefix_len(line, len, "-ERR")) {
 	    netsec_err(errstr, "%s", line);
 	    return NOTOK;
 	}
@@ -455,7 +455,7 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
 	 * Make sure we get someting back a valid response
 	 */
 
-	if (!has_prefix(line, "+ ")) {
+	if (!has_prefix_len(line, len, "+ ")) {
 	    netsec_err(errstr, "Invalid format for SASL response");
 	    return NOTOK;
 	}
@@ -508,7 +508,7 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata,
 	if (line == NULL)
 	    return NOTOK;
 
-	if (!has_prefix(line, "+OK")) {
+	if (!has_prefix_len(line, len, "+OK")) {
 	    netsec_err(errstr, "Authentication failed: %s", line);
 	    return NOTOK;
 	}

Reply via email to