/* Import code */
-static int extract_name(char *data, size_t size,
+static int extract_name(pool_t pool, const char *data, size_t size,
const char **value_r, const char **error_r)
{
- char *ptr = memchr(data, '\1', size);
+ if (size == 0) {
+ *error_r = "Missing end of name";
+ return -1;
+ }
+
+ const char *ptr = memchr(data, '\1', size);
if (ptr == NULL) {
*error_r = "Missing end of name";
return -1;
*value_r = NULL;
return 1;
}
- *value_r = data;
- *ptr = '\0';
+ *value_r = p_strdup_until(pool, data, ptr);
return len + 1;
-
}
-static int extract_value(char *data, size_t size,
+static int extract_value(pool_t pool, const char *data, size_t size,
const char **value_r, const char **error_r)
{
- char *ptr = memchr(data, '\r', size);
+ if (size == 0) {
+ *error_r = "Missing end of string";
+ return -1;
+ }
+
+ const char *ptr = memchr(data, '\r', size);
if (ptr == NULL) {
*error_r = "Missing end of string";
return -1;
}
size_t len = ptr - data;
- *ptr = '\0';
- *value_r = str_tabunescape(data);
+ string_t *unescaped = str_new(pool, len);
+ str_append_tabunescaped(unescaped, data, len);
+ *value_r = str_c(unescaped);
/* make sure we end up in right place. */
return len + 1;
}
static int extract_number(const char *data, size_t size, intmax_t *value_r,
const char **error_r)
{
+ if (size == 0) {
+ *error_r = "Too short number";
+ return -1;
+ }
+
const unsigned char *ptr = (const unsigned char*)data;
bool negative;
size_t len = 1;
return 1;
}
+ if (size < 2) {
+ *error_r = "Too short number";
+ return -1;
+ }
+
const char sign = *ptr - 0x80;
if (sign == '+') {
negative = FALSE;
*error_r = "Unknown number";
return -1;
}
+ size--;
ptr++;
intmax_t value = 0;
intmax_t shift = 0;
+ size_t max_size = I_MIN(size, 9);
/* a number can be at most 9 bytes */
- for (size_t i = 0; i < I_MIN(size, 9); i++) {
+ for (size_t i = 0; i < max_size; i++) {
len++;
value |= ((*(ptr) & 0x7fLL) << shift);
/* if high byte is set, the number continues */
break;
shift += 7;
ptr++;
+ size--;
}
- if ((*ptr & 0x80) != 0) {
+ if (size > 0 && (*ptr & 0x80) != 0) {
*error_r = "Unfinished number";
return -1;
}
data = data + (count); \
size = size - (size_t)(count);
-static int var_expand_program_import_stmt(char *data, size_t size,
+static int var_expand_program_import_stmt(const char *data, size_t size,
struct var_expand_program *program,
const char **error_r)
{
size_t orig_size = size;
/* normal program, starts with filter name */
- int ret = extract_name(data, size, &name, error_r);
+ int ret = extract_name(program->pool, data, size, &name, error_r);
if (ret < 0)
return -1;
if (name == NULL) {
param->idx = ++idx;
ADVANCE_INPUT(1);
} else {
- ret = extract_name(data, size,
+ ret = extract_name(program->pool, data, size,
&name, error_r);
if (ret < 0)
return -1;
param->key = name;
}
+ if (size < 1) {
+ *error_r = "Premature end of data";
+ return -1;
+ }
+
/* check the parameter type */
switch (*data) {
case 's':
}
ADVANCE_INPUT(1);
+ if (size == 0) {
+ *error_r = "Premature end of data";
+ return -1;
+ }
+
if (param->value_type == VAR_EXPAND_PARAMETER_VALUE_TYPE_STRING ||
param->value_type == VAR_EXPAND_PARAMETER_VALUE_TYPE_VARIABLE) {
- ret = extract_value(data, size,
+ ret = extract_value(program->pool, data, size,
&value, error_r);
if (ret < 0)
return -1;
prev->next = param;
prev = param;
- if (*data == '\t') {
+ if (size > 0 && *data == '\t') {
break;
- } else if (*data == '\1') {
+ } else if (size > 0 && *data == '\1') {
ADVANCE_INPUT(1);
} else {
*error_r = "Missing parameter end";
}
}
- if (*data != '\t')
+ if (size < 1 || *data != '\t')
*error_r = "Missing parameter statement end";
ADVANCE_INPUT(1);
return orig_size - size;
}
-static int var_expand_program_import_one(char **_data, size_t *_size,
+static int var_expand_program_import_one(const char **_data, size_t *_size,
struct var_expand_program *program,
const char **error_r)
{
- char *data = *_data;
+ const char *data = *_data;
size_t size = *_size;
const char *value;
int ret;
/* Only literal */
if (*data == '\1') {
ADVANCE_INPUT(1);
- ret = extract_value(data, size, &value, error_r);
+ ret = extract_value(program->pool, data, size, &value, error_r);
if (ret < 0)
return -1;
ADVANCE_INPUT(ret);
/* A full program */
} else if (*data == '\2') {
ADVANCE_INPUT(1);
- while (*data != '\t' && size > 0) {
+ while (size > 0 && *data != '\t') {
int ret = var_expand_program_import_stmt(data, size, program, error_r);
if (ret < 0)
return -1;
ADVANCE_INPUT(ret);
- if (*data == '\t') {
+ if (size > 0 && *data == '\t') {
ADVANCE_INPUT(1);
break;
- } else if (*data != '\1') {
+ } else if (size == 0 || *data != '\1') {
*error_r = "Missing statement end";
return -1;
}
ADVANCE_INPUT(1);
}
/* And finally there should be variables */
- if (*data != '\t') {
+ if (size > 0 && *data != '\t') {
const char *ptr = memchr(data, '\t', size);
if (ptr == NULL) {
*error_r = "Missing variables end";
return -1;
}
size_t len = ptr - data;
+ /* ensure data is properly terminated, since
+ p_strsplit() expects a NUL terminated string. */
+ const char *variables = t_strdup_until(data, ptr);
program->variables = (const char *const *)
- p_strsplit(program->pool, data, "\1");
+ p_strsplit(program->pool, variables, "\1");
ADVANCE_INPUT(len + 1);
} else {
ADVANCE_INPUT(1);
struct var_expand_program *prev = NULL;
struct var_expand_program *first = NULL;
int ret;
- char *copy_data = p_strndup(pool, data, size);
while (size > 0) {
struct var_expand_program *program =
p_new(pool, struct var_expand_program, 1);
program->pool = pool;
T_BEGIN {
- ret = var_expand_program_import_one(©_data, &size,
+ ret = var_expand_program_import_one(&data, &size,
program, error_r);
} T_END;
if (ret < 0)
{ "\x01literal", "Missing end of string" },
{ "\x03literal", "Unknown input" },
{ "\x02literal\x01", "Premature end of data" },
- { "\x02literal\x01text\x01", "Unsupported parameter type" },
+ { "\x02literal\x01text\x01", "Premature end of data" },
{ "\x02literal\x01\x01stext\t", "Missing end of string" },
- { "\x02literal\x01\x01i\xa1", "Unknown number" },
+ { "\x02literal\x01\x01i\xa1", "Too short number" },
{ "\x02literal\x01\x01i\xab\xf0\t", "Missing parameter end" },
{
"\x02literal\x01\x01i\xab\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0",
},
{ "\x02literal\x01\x01stext\r", "Missing parameter end" },
{ "\x02literal\x01\x01stext\r\t", "Missing statement end" },
- { "\x02literal\x01\x01stext\r\t\t", "Missing variables end" },
+ { "\x02literal\x01\x01stext\r\t\t", "Premature end of data" },
};
for(size_t i = 0; i < N_ELEMENTS(test_cases_err); i++) {
continue;
}
- test_assert_strcmp(error, t->error);
+ test_assert_strcmp_idx(error, t->error, i);
}
test_end();