We only need to check for expansion strings if there's at least one $. Once we find a $, we only need to scan from that point forward for the replacement as well. Similar changes would then apply to httpd as well. We could also apply the same trick recursively to the remaining strstr calls, but I didn't want to tear the code up too much at once. This change is mostly reindentation with the occasional variable rename.
Since I was reading the code, change calloc to malloc in expand_string. We only need one nul to terminate the string. There are quite a few other calloc calls that get immediately overwritten, only including one for now because it's in a related function. Index: relay_http.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/relay_http.c,v retrieving revision 1.43 diff -u -p -r1.43 relay_http.c --- relay_http.c 22 Jan 2015 17:42:09 -0000 1.43 +++ relay_http.c 13 Feb 2015 03:47:25 -0000 @@ -997,54 +997,58 @@ relay_expand_http(struct ctl_relay_event struct rsession *con = cre->con; struct relay *rlay = con->se_relay; char ibuf[128]; + char *start; + size_t remlen; if (strlcpy(buf, val, len) >= len) return (NULL); - - if (strstr(val, "$REMOTE_") != NULL) { - if (strstr(val, "$REMOTE_ADDR") != NULL) { - if (print_host(&cre->ss, ibuf, sizeof(ibuf)) == NULL) - return (NULL); - if (expand_string(buf, len, - "$REMOTE_ADDR", ibuf) != 0) - return (NULL); - } - if (strstr(val, "$REMOTE_PORT") != NULL) { - snprintf(ibuf, sizeof(ibuf), "%u", ntohs(cre->port)); - if (expand_string(buf, len, - "$REMOTE_PORT", ibuf) != 0) - return (NULL); - } - } - if (strstr(val, "$SERVER_") != NULL) { - if (strstr(val, "$SERVER_ADDR") != NULL) { - if (print_host(&rlay->rl_conf.ss, - ibuf, sizeof(ibuf)) == NULL) - return (NULL); - if (expand_string(buf, len, - "$SERVER_ADDR", ibuf) != 0) - return (NULL); + start = buf; + if ((start = strchr(start, '$')) != NULL) { + remlen = len - (start - buf); + if (strstr(start, "$REMOTE_") != NULL) { + if (strstr(start, "$REMOTE_ADDR") != NULL) { + if (print_host(&cre->ss, ibuf, sizeof(ibuf)) == NULL) + return (NULL); + if (expand_string(start, remlen, + "$REMOTE_ADDR", ibuf) != 0) + return (NULL); + } + if (strstr(start, "$REMOTE_PORT") != NULL) { + snprintf(ibuf, sizeof(ibuf), "%u", ntohs(cre->port)); + if (expand_string(start, remlen, + "$REMOTE_PORT", ibuf) != 0) + return (NULL); + } } - if (strstr(val, "$SERVER_PORT") != NULL) { - snprintf(ibuf, sizeof(ibuf), "%u", - ntohs(rlay->rl_conf.port)); - if (expand_string(buf, len, - "$SERVER_PORT", ibuf) != 0) - return (NULL); + if (strstr(start, "$SERVER_") != NULL) { + if (strstr(start, "$SERVER_ADDR") != NULL) { + if (print_host(&rlay->rl_conf.ss, + ibuf, sizeof(ibuf)) == NULL) + return (NULL); + if (expand_string(start, remlen, + "$SERVER_ADDR", ibuf) != 0) + return (NULL); + } + if (strstr(start, "$SERVER_PORT") != NULL) { + snprintf(ibuf, sizeof(ibuf), "%u", + ntohs(rlay->rl_conf.port)); + if (expand_string(start, remlen, + "$SERVER_PORT", ibuf) != 0) + return (NULL); + } + if (strstr(start, "$SERVER_NAME") != NULL) { + if (expand_string(start, remlen, + "$SERVER_NAME", RELAYD_SERVERNAME) != 0) + return (NULL); + } } - if (strstr(val, "$SERVER_NAME") != NULL) { - if (expand_string(buf, len, - "$SERVER_NAME", RELAYD_SERVERNAME) != 0) + if (strstr(start, "$TIMEOUT") != NULL) { + snprintf(ibuf, sizeof(ibuf), "%lld", + (long long)rlay->rl_conf.timeout.tv_sec); + if (expand_string(start, remlen, "$TIMEOUT", ibuf) != 0) return (NULL); } } - if (strstr(val, "$TIMEOUT") != NULL) { - snprintf(ibuf, sizeof(ibuf), "%lld", - (long long)rlay->rl_conf.timeout.tv_sec); - if (expand_string(buf, len, "$TIMEOUT", ibuf) != 0) - return (NULL); - } - return (buf); } Index: relayd.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/relayd.c,v retrieving revision 1.138 diff -u -p -r1.138 relayd.c --- relayd.c 22 Jan 2015 17:42:09 -0000 1.138 +++ relayd.c 13 Feb 2015 03:52:08 -0000 @@ -1265,10 +1265,11 @@ expand_string(char *label, size_t len, c char *tmp; char *p, *q; - if ((tmp = calloc(1, len)) == NULL) { + if ((tmp = malloc(len)) == NULL) { log_debug("%s: calloc", __func__); return (-1); } + tmp[0] = '\0'; p = q = label; while ((q = strstr(p, srch)) != NULL) { *q = '\0';