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;
}