aboutsummaryrefslogtreecommitdiff
path: root/format.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2013-08-03 21:06:38 +0100
committerNicholas Marriott <nicholas.marriott@gmail.com>2013-08-03 21:06:38 +0100
commit84c22d053b5ec1cd25e1694fa3889922b9cbe11b (patch)
treecc2a16f9740fdf784459b06fead42323bbcc7b8d /format.c
parent7581762c8e07b18726933616ac92458f9e74d4c6 (diff)
downloadrtmux-84c22d053b5ec1cd25e1694fa3889922b9cbe11b.tar.gz
rtmux-84c22d053b5ec1cd25e1694fa3889922b9cbe11b.tar.bz2
rtmux-84c22d053b5ec1cd25e1694fa3889922b9cbe11b.zip
Add length limit operator for formats.
Diffstat (limited to 'format.c')
-rw-r--r--format.c40
1 files changed, 34 insertions, 6 deletions
diff --git a/format.c b/format.c
index 0845df6d..ee3339dc 100644
--- a/format.c
+++ b/format.c
@@ -18,6 +18,8 @@
#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
#include <netdb.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -188,18 +190,40 @@ format_find(struct format_tree *ft, const char *key)
* #{?blah,a,b} is replace with a if blah exists and is nonzero else b.
*/
int
-format_replace(struct format_tree *ft,
- const char *key, size_t keylen, char **buf, size_t *len, size_t *off)
+format_replace(struct format_tree *ft, const char *key, size_t keylen,
+ char **buf, size_t *len, size_t *off)
{
- char *copy, *ptr;
+ char *copy, *copy0, *endptr, *ptr;
const char *value;
size_t valuelen;
+ u_long limit = ULONG_MAX;
/* Make a copy of the key. */
- copy = xmalloc(keylen + 1);
+ copy0 = copy = xmalloc(keylen + 1);
memcpy(copy, key, keylen);
copy[keylen] = '\0';
+ /* Is there a length limit or whatnot? */
+ if (!islower((u_char) *copy) && *copy != '?') {
+ while (*copy != ':' && *copy != '\0') {
+ switch (*copy) {
+ case '=':
+ errno = 0;
+ limit = strtoul(copy + 1, &endptr, 10);
+ if (errno == ERANGE && limit == ULONG_MAX)
+ goto fail;
+ copy = endptr;
+ break;
+ default:
+ copy++;
+ break;
+ }
+ }
+ if (*copy != ':')
+ goto fail;
+ copy++;
+ }
+
/*
* Is this a conditional? If so, check it exists and extract either the
* first or second element. If not, look up the key directly.
@@ -230,6 +254,10 @@ format_replace(struct format_tree *ft,
}
valuelen = strlen(value);
+ /* Truncate the value if needed. */
+ if (valuelen > limit)
+ valuelen = limit;
+
/* Expand the buffer and copy in the value. */
while (*len - *off < valuelen + 1) {
*buf = xrealloc(*buf, 2, *len);
@@ -238,11 +266,11 @@ format_replace(struct format_tree *ft,
memcpy(*buf + *off, value, valuelen);
*off += valuelen;
- free(copy);
+ free(copy0);
return (0);
fail:
- free(copy);
+ free(copy0);
return (-1);
}