};
int
-parse_obj_list(cmdline_parse_token_hdr_t *tk, const char *buf, void *res)
+parse_obj_list(cmdline_parse_token_hdr_t *tk, const char *buf, void *res,
+ unsigned ressize)
{
struct token_obj_list *tk2 = (struct token_obj_list *)tk;
struct token_obj_list_data *tkd = &tk2->obj_list_data;
struct object *o;
unsigned int token_len = 0;
+ if (res && ressize < sizeof(struct object *))
+ return -1;
+
token_len = strlen(buf);
SLIST_FOREACH(o, tkd->list, next) {
extern struct cmdline_token_ops token_obj_list_ops;
-int parse_obj_list(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res);
+int parse_obj_list(cmdline_parse_token_hdr_t *tk, const char *srcbuf,
+ void *res, unsigned ressize);
int complete_get_nb_obj_list(cmdline_parse_token_hdr_t *tk);
-int complete_get_elt_obj_list(cmdline_parse_token_hdr_t *tk, int idx,
+int complete_get_elt_obj_list(cmdline_parse_token_hdr_t *tk, int idx,
char *dstbuf, unsigned int size);
int get_help_obj_list(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size);
}
int
-parse_conf_node(cmdline_parse_token_hdr_t *tk, const char *buf, void *res)
+parse_conf_node(cmdline_parse_token_hdr_t *tk, const char *buf, void *res,
+ unsigned ressize)
{
struct token_conf_node *tk2 = (struct token_conf_node *)tk;
struct token_conf_node_data *tkd = &tk2->conf_node_data;
unsigned int token_len = 0;
char token[CMDLINE_MAX_TOKEN_SIZE];
+ if (res && ressize < sizeof(struct confnode *))
+ return -1;
+
/* if token is too big... */
token_len = snprintf(token, sizeof(token), "%s", buf);
if (token_len >= sizeof(token))
extern struct cmdline_token_ops token_conf_node_ops;
-int parse_conf_node(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res);
+int parse_conf_node(cmdline_parse_token_hdr_t *tk, const char *srcbuf,
+ void *res, unsigned ressize);
int complete_get_nb_conf_node(cmdline_parse_token_hdr_t *tk);
int complete_get_elt_conf_node(cmdline_parse_token_hdr_t *tk, int idx,
char *dstbuf, unsigned int size);
*/
static int
match_inst(cmdline_parse_inst_t *inst, const char *buf,
- unsigned int nb_match_token, void * result_buf)
+ unsigned int nb_match_token, void *resbuf, unsigned resbuf_size)
{
unsigned int token_num=0;
cmdline_parse_token_hdr_t * token_p;
if (n == -EINVAL)
return -EINVAL;
- if (result_buf)
+ if (resbuf == NULL)
+ res = token_hdr.ops->parse(token_p, token_str, NULL, 0);
+ else {
+ unsigned rb_sz;
+ void *rb = (char *)resbuf + token_hdr.offset;
+ if (token_hdr.offset > resbuf_size)
+ return -ENOBUFS;
+ rb_sz = resbuf_size - token_hdr.offset;
res = token_hdr.ops->parse(token_p, token_str,
- (char *)result_buf +
- token_hdr.offset);
- else
- res = token_hdr.ops->parse(token_p, token_str, NULL);
+ rb, rb_sz);
+ }
+
if (res < 0)
break;
unsigned int inst_num=0;
cmdline_parse_inst_t *inst;
const char *curbuf;
- char result_buf[BUFSIZ];
+ char result_buf[CMDLINE_MAX_DSTBUF_SIZE];
void (*f)(void *, struct cmdline *, void *) = NULL;
void *data = NULL;
int comment = 0;
debug_printf("INST %d\n", inst_num);
/* fully parsed */
- tok = match_inst(inst, buf, 0, result_buf);
+ tok = match_inst(inst, buf, 0, result_buf, sizeof(result_buf));
if (tok > 0) /* we matched at least one token */
err = CMDLINE_PARSE_BAD_ARGS;
inst = ctx[inst_num];
while (inst) {
/* parse the first tokens of the inst */
- if (nb_token && match_inst(inst, buf, nb_token, NULL))
+ if (nb_token && match_inst(inst, buf, nb_token, NULL, 0))
goto next;
debug_printf("instruction match \n");
/* we need to redo it */
inst = ctx[inst_num];
- if (nb_token && match_inst(inst, buf, nb_token, NULL))
+ if (nb_token && match_inst(inst, buf, nb_token, NULL, 0))
goto next2;
token_p = inst->tokens[nb_token];
#define CMDLINE_PARSE_COMPLETED_BUFFER 2
#define CMDLINE_MAX_TOKEN_SIZE 128 /* including '\0' */
+#define CMDLINE_MAX_DSTBUF_SIZE 1024
/**
* Stores a pointer to the ops struct, and the offset: the place to
*
* parse() takes the token as first argument, then the source buffer
* starting at the token we want to parse. The 3rd arg is a pointer
- * where we store the parsed data (as binary). It returns the number of
- * parsed chars on success and a negative value on error.
+ * where we store the parsed data (as binary), and the 4th arg is the
+ * size of this area. It returns 0 on success and a negative value on
+ * error.
*
* complete_get_nb() returns the number of possible values for this
* token if completion is possible. If it is NULL or if it returns 0,
* no completion is possible.
*
* complete_get_elt() copy in dstbuf (the size is specified in the
- * parameter) the i-th possible completion for this token. returns 0
- * on success or and a negative value on error.
+ * parameter) the i-th possible completion for this token. Return 0
+ * on success or a negative value on error.
*
* get_help() fills the dstbuf with the help for the token. It returns
* -1 on error and 0 on success.
*/
struct cmdline_token_ops {
/** parse(token ptr, buf, res pts) */
- int (*parse)(cmdline_parse_token_hdr_t *, const char *, void *);
+ int (*parse)(cmdline_parse_token_hdr_t *, const char *, void *,
+ unsigned int);
/** return the num of possible choices for this token */
int (*complete_get_nb)(cmdline_parse_token_hdr_t *);
/** return the elt x for this token (token, idx, dstbuf, size) */
- int (*complete_get_elt)(cmdline_parse_token_hdr_t *, int, char *, unsigned int);
+ int (*complete_get_elt)(cmdline_parse_token_hdr_t *, int, char *,
+ unsigned int);
/** get help for this token (token, dstbuf, size) */
int (*get_help)(cmdline_parse_token_hdr_t *, char *, unsigned int);
};
int
cmdline_parse_etheraddr(__attribute__((unused)) cmdline_parse_token_hdr_t *tk,
- const char *buf, void *res)
+ const char *buf, void *res, unsigned ressize)
{
unsigned int token_len = 0;
char ether_str[ETHER_ADDRSTRLEN];
struct ether_addr *etheraddr = res;
struct ether_addr *tmp;
+ if (res && ressize < sizeof(struct ether_addr))
+ return -1;
+
/* if token is too big... */
token_len = snprintf(ether_str, sizeof(ether_str), "%s", buf);
if (token_len >= sizeof(ether_str))
extern struct cmdline_token_ops cmdline_token_etheraddr_ops;
int cmdline_parse_etheraddr(cmdline_parse_token_hdr_t *tk, const char *srcbuf,
- void *res);
+ void *res, unsigned ressize);
int cmdline_get_help_etheraddr(cmdline_parse_token_hdr_t *tk, char *dstbuf,
unsigned int size);
}
int
-cmdline_parse_ipaddr(cmdline_parse_token_hdr_t *tk, const char *buf, void *res)
+cmdline_parse_ipaddr(cmdline_parse_token_hdr_t *tk, const char *buf, void *res,
+ unsigned ressize)
{
struct cmdline_token_ipaddr *tk2 = (struct cmdline_token_ipaddr *)tk;
unsigned int token_len = 0;
char *prefix, *prefix_end;
long prefixlen;
+ if (res && ressize < sizeof(cmdline_ipaddr_t))
+ return -1;
+
/* if token is too big... */
token_len = snprintf(ip_str, sizeof(ip_str), "%s", buf);
if (token_len >= sizeof(ip_str))
extern struct cmdline_token_ops cmdline_token_ipaddr_ops;
int cmdline_parse_ipaddr(cmdline_parse_token_hdr_t *tk, const char *srcbuf,
- void *res);
+ void *res, unsigned ressize);
int cmdline_get_help_ipaddr(cmdline_parse_token_hdr_t *tk, char *dstbuf,
unsigned int size);
return 0;
}
+static int check_res_size(struct cmdline_token_num_data *nd, unsigned ressize)
+{
+ switch (nd->type) {
+ case INT8:
+ case UINT8:
+ if (ressize < sizeof(int8_t))
+ return -1;
+ break;
+ case INT16:
+ case UINT16:
+ if (ressize < sizeof(int16_t))
+ return -1;
+ break;
+ case INT32:
+ case UINT32:
+ if (ressize < sizeof(int32_t))
+ return -1;
+ break;
+ case INT64:
+ case UINT64:
+ if (ressize < sizeof(int64_t))
+ return -1;
+ break;
+#ifdef CMDLINE_HAVE_FLOAT
+ case FLOAT:
+ if (ressize < sizeof(float))
+ return -1;
+ break;
+#endif
+ default:
+ return -1;
+ }
+ return 0;
+}
/* parse an int or a float */
int
-cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res)
+cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const char *srcbuf,
+ void *res, unsigned ressize)
{
struct cmdline_token_num_data nd;
enum num_parse_state_t st = START;
memcpy(&nd, &((struct cmdline_token_num *)tk)->num_data, sizeof(nd));
+ /* check that we have enough room in res */
+ if (res) {
+ if (check_res_size(&nd, ressize) < 0)
+ return -1;
+ }
+
while (st != ERROR && c != '\0') {
debug_printf("%c %x -> ", c, c);
switch (st) {
extern struct cmdline_token_ops cmdline_token_num_ops;
int cmdline_parse_num(cmdline_parse_token_hdr_t *tk,
- const char *srcbuf, void *res);
+ const char *srcbuf, void *res, unsigned ressize);
int cmdline_get_help_num(cmdline_parse_token_hdr_t *tk,
char *dstbuf, unsigned int size);
}
int
-cmdline_parse_string(cmdline_parse_token_hdr_t *tk, const char *buf, void *res)
+cmdline_parse_string(cmdline_parse_token_hdr_t *tk, const char *buf, void *res,
+ unsigned ressize)
{
struct cmdline_token_string *tk2 = (struct cmdline_token_string *)tk;
struct cmdline_token_string_data *sd = &tk2->string_data;;
unsigned int token_len;
+ if (res && ressize < STR_TOKEN_SIZE)
+ return -1;
+
token_len = strlen(buf);
if (token_len >= (STR_TOKEN_SIZE - 1) || token_len == 0)
#include "cmdline_parse.h"
/* size of a parsed string */
-#define STR_TOKEN_SIZE 128
+#define STR_TOKEN_SIZE CMDLINE_MAX_TOKEN_SIZE
typedef char cmdline_fixed_string_t[STR_TOKEN_SIZE];
extern struct cmdline_token_ops cmdline_token_string_ops;
int cmdline_parse_string(cmdline_parse_token_hdr_t *tk, const char *srcbuf,
- void *res);
+ void *res, unsigned ressize);
int cmdline_complete_get_nb_string(cmdline_parse_token_hdr_t *tk);
int cmdline_complete_get_elt_string(cmdline_parse_token_hdr_t *tk, int idx,
char *dstbuf, unsigned int size);