diff --git a/networking/ifupdown.c b/networking/ifupdown.c index f72e653b3..d4e49c4c1 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c @@ -125,6 +125,7 @@ static int count_netmask_bits(char *dotted_quad) /* Found a netmask... Check if it is dotted quad */ if (sscanf(dotted_quad, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) return -1; + // FIXME: will be confused by e.g. 255.0.255.0 result = count_bits(a); result += count_bits(b); result += count_bits(c); @@ -133,32 +134,27 @@ static int count_netmask_bits(char *dotted_quad) } #endif -static void addstr(char **buf, size_t *len, size_t *pos, const char *str, size_t str_length) +static void addstr(char **bufp, const char *str, size_t str_length) { - if (*pos + str_length >= *len) { - char *newbuf; - - newbuf = xrealloc(*buf, *len * 2 + str_length + 1); - *buf = newbuf; - *len = *len * 2 + str_length + 1; - } - - while (str_length-- >= 1) { - (*buf)[(*pos)++] = *str; - str++; - } - (*buf)[*pos] = '\0'; + /* xasprintf trick will be smaller, but we are often + * called with str_length == 1 - don't want to have + * THAT much of malloc/freeing! */ + char *buf = *bufp; + int len = (buf ? strlen(buf) : 0); + str_length++; + buf = xrealloc(buf, len + str_length); + /* copies at most str_length-1 chars! */ + safe_strncpy(buf + len, str, str_length); + *bufp = buf; } static int strncmpz(const char *l, const char *r, size_t llen) { int i = strncmp(l, r, llen); - if (i == 0) { + if (i == 0) return -r[llen]; - } else { - return i; - } + return i; } static char *get_var(const char *id, size_t idlen, struct interface_defn_t *ifd) @@ -168,31 +164,27 @@ static char *get_var(const char *id, size_t idlen, struct interface_defn_t *ifd) if (strncmpz(id, "iface", idlen) == 0) { char *result; static char label_buf[20]; - strncpy(label_buf, ifd->iface, 19); - label_buf[19]=0; + safe_strncpy(label_buf, ifd->iface, sizeof(label_buf)); result = strchr(label_buf, ':'); if (result) { - *result=0; + *result = '\0'; } return label_buf; - } else if (strncmpz(id, "label", idlen) == 0) { + } + if (strncmpz(id, "label", idlen) == 0) { return ifd->iface; - } else { - for (i = 0; i < ifd->n_options; i++) { - if (strncmpz(id, ifd->option[i].name, idlen) == 0) { - return ifd->option[i].value; - } + } + for (i = 0; i < ifd->n_options; i++) { + if (strncmpz(id, ifd->option[i].name, idlen) == 0) { + return ifd->option[i].value; } } - return NULL; } static char *parse(const char *command, struct interface_defn_t *ifd) { - char *result = NULL; - size_t pos = 0, len = 0; size_t old_pos[MAX_OPT_DEPTH] = { 0 }; int okay[MAX_OPT_DEPTH] = { 1 }; int opt_depth = 1; @@ -200,26 +192,26 @@ static char *parse(const char *command, struct interface_defn_t *ifd) while (*command) { switch (*command) { default: - addstr(&result, &len, &pos, command, 1); + addstr(&result, command, 1); command++; break; case '\\': if (command[1]) { - addstr(&result, &len, &pos, command + 1, 1); + addstr(&result, command + 1, 1); command += 2; } else { - addstr(&result, &len, &pos, command, 1); + addstr(&result, command, 1); command++; } break; case '[': if (command[1] == '[' && opt_depth < MAX_OPT_DEPTH) { - old_pos[opt_depth] = pos; + old_pos[opt_depth] = strlen(result); okay[opt_depth] = 1; opt_depth++; command += 2; } else { - addstr(&result, &len, &pos, "[", 1); + addstr(&result, "[", 1); command++; } break; @@ -227,12 +219,11 @@ static char *parse(const char *command, struct interface_defn_t *ifd) if (command[1] == ']' && opt_depth > 1) { opt_depth--; if (!okay[opt_depth]) { - pos = old_pos[opt_depth]; - result[pos] = '\0'; + result[old_pos[opt_depth]] = '\0'; } command += 2; } else { - addstr(&result, &len, &pos, "]", 1); + addstr(&result, "]", 1); command++; } break; @@ -252,18 +243,17 @@ static char *parse(const char *command, struct interface_defn_t *ifd) varvalue = get_var(command, nextpercent - command, ifd); if (varvalue) { - addstr(&result, &len, &pos, varvalue, strlen(varvalue)); + addstr(&result, varvalue, strlen(varvalue)); } else { #ifdef CONFIG_FEATURE_IFUPDOWN_IP /* Sigh... Add a special case for 'ip' to convert from * dotted quad to bit count style netmasks. */ if (strncmp(command, "bnmask", 6)==0) { - int res; + unsigned res; varvalue = get_var("netmask", 7, ifd); - if (varvalue && (res=count_netmask_bits(varvalue)) > 0) { - char argument[255]; - sprintf(argument, "%d", res); - addstr(&result, &len, &pos, argument, strlen(argument)); + if (varvalue && (res = count_netmask_bits(varvalue)) > 0) { + const char *argument = utoa(res); + addstr(&result, argument, strlen(argument)); command = nextpercent + 1; break; } @@ -567,7 +557,7 @@ static char *next_word(char **buf) unsigned short length; char *word; - if ((buf == NULL) || (*buf == NULL) || (**buf == '\0')) { + if (!buf || !*buf || !**buf) { return NULL; }