From 709a46ac676cb9010490f9c67efc5a65fedb15f7 Mon Sep 17 00:00:00 2001 From: Lynus Vaz Date: Thu, 11 Jun 2009 23:56:24 +0530 Subject: [PATCH] Bugs fixed. Fixed memory leaks (hopefully). --- src/hci/arith.c | 285 +++++++++++++++++++++---------------- src/include/gpxe/errfile.h | 1 + 2 files changed, 167 insertions(+), 119 deletions(-) diff --git a/src/hci/arith.c b/src/hci/arith.c index fc37899b..e7a2983d 100644 --- a/src/hci/arith.c +++ b/src/hci/arith.c @@ -17,10 +17,12 @@ Ops: !, ~ (Highest) || (Lowest) */ -#include -#include #include +#include #include +#include +#include +#include #ifndef __ARITH_TEST__ #include @@ -39,8 +41,9 @@ char *inp, *prev; int tok; int err_val; //skip, parse_num, eval long tok_value; +int brackets; -char *op_table = "!@@" "~@@" "*@@" "/@@" "%@@" "+@@" "-@@" "<@@" "<=@" "<<@" ">@@" ">=@" ">>@" "!=@" "==@" "&@@" "|@@" "^@@" "&&@" "||@"; +char *op_table = "!@@" "~@@" "*@@" "/@@" "%@@" "+@@" "-@@" "=@@" "<@@" "<=@" "<<@" ">@@" ">=@" ">>@" "!=@" "&@@" "|@@" "^@@" "&&@" "||@"; char *keyword_table = " \t\v()!~*/%+-<=>&|^"; //Characters that cannot appear in a string signed char op_prio[NUM_OPS] = { 10, 10, 9, 9, 9, 8, 8, 6, 6, 7, 6, 6, 7, 5, 5, 4, 3, 2, 1, 0 }; @@ -54,10 +57,8 @@ signed char op_prio[NUM_OPS] = { 10, 10, 9, 9, 9, 8, 8, 6, 6, 7, 6, 6, 7, 5, 5, */ static void ignore_whitespace(void); -//static long get_value(char *var, int size); -static void input() -{ +static void input(void) { char t_op[3] = { '\0', '\0', '\0'}; char *p1, *p2; size_t len; @@ -68,10 +69,8 @@ static void input() prev = inp; ignore_whitespace(); - if(*inp != '\0') - { - if(isdigit(*inp)) - { + if(*inp != '\0') { + if(isdigit(*inp)) { tok_value = 0; tok = TOK_NUMBER; tok_value = strtoul(inp, &inp, 0); @@ -80,12 +79,13 @@ static void input() len = strcspn(inp, keyword_table); - if(len > 0) - { + if(len > 0) { char str_val[len + 1]; strncpy(str_val, inp, len); str_val[len] = '\0'; - asprintf((char **)&tok_value, "%s", str_val); + if(asprintf((char **)&tok_value, "%s", str_val) < 0) { + err_val = -ENOMEM; + } inp += len; tok = TOK_STRING; return; @@ -93,15 +93,13 @@ static void input() t_op[0] = *inp++; p1 = strstr(op_table, t_op); - if(!p1) - { + if(!p1) { tok = *t_op; return; } t_op[1] = *inp; p2 = strstr(op_table, t_op); - if(!p2 || p1 == p2) - { + if(!p2 || p1 == p2) { tok = MIN_TOK + (p1 - op_table)/3; return; } @@ -109,20 +107,18 @@ static void input() tok = MIN_TOK + (p2 - op_table)/3; } else - tok = -1; + tok = -1; } static int parse_expr(char **buffer); -static void ignore_whitespace(void) -{ +static void ignore_whitespace(void) { while (isspace(*inp)) { inp++; } } -static int accept(int ch) -{ +static int accept(int ch) { if (tok == ch) { input(); return 1; @@ -130,79 +126,98 @@ static int accept(int ch) return 0; } -static void skip(int ch) -{ +static void skip(int ch) { if (!accept(ch)) { err_val = -1; - printf("expected '%c', got '%c'\n", ch, tok); + printf("expected '%c', got '%c'\n", (char)ch, (char)tok); } } -static int parse_num(char **buffer) -{ +static int parse_num(char **buffer) { long num = 0; int flag = 1; - if(accept(TOK_MINUS)) //Handle -NUM and +NUM - flag = -1; - else if(accept(TOK_PLUS)) {} + if(tok == TOK_MINUS || tok == TOK_PLUS || tok == '(' || tok == TOK_NUMBER) { - if (accept('(')) { - parse_expr(buffer); - skip(')'); - if(flag < 0) - { - if(**buffer == '-') - **buffer = '+'; - else - { - char t[strlen(*buffer) + 2]; - t[0] = '-'; - strcpy(t + 1, *buffer); + if(accept(TOK_MINUS)) //Handle -NUM and +NUM + flag = -1; + else if(accept(TOK_PLUS)) {} + + if (accept('(')) { + brackets++; + parse_expr(buffer); + if(err_val) { + return -1; + } + skip(')'); + brackets--; + if(err_val) { free(*buffer); - return asprintf(buffer, "%s", t); - } + return -1; + } + if(flag < 0) { + if(**buffer == '-') { + **buffer = '+'; + } else { + char t[strlen(*buffer) + 2]; + t[0] = '-'; + strcpy(t + 1, *buffer); + free(*buffer); + if(asprintf(buffer, "%s", t) < 0) { + err_val = -ENOMEM; + return -ENOMEM; + } + } + } + return strlen(*buffer); } - return strlen(*buffer); + if(tok == TOK_NUMBER) { + num = flag * tok_value; + input(); + if(asprintf(buffer, "%ld", num) < 0) { + err_val = -ENOMEM; + return err_val; + } + return strlen(*buffer); + } + err_val = -1; + return -1; } - if(tok == TOK_NUMBER) - { - num = flag * tok_value; - input(); - return asprintf(buffer, "%ld", num); - } else if (tok == TOK_STRING) - { + if (tok == TOK_STRING) { *buffer = (char *)tok_value; input(); return strlen(*buffer); } - err_val = -1; - return 0; + err_val = -1; + return -1; } //"!" "~" "*" "/" "%" "+" "-" "<" "<=" "<<" ">" ">=" ">>" "!=" "==" "&" "|" "^" "&&" "||"; -static int eval(int op, char *op1, char *op2, char **buffer) -{ + +static int eval(int op, char *op1, char *op2, char **buffer) { long value; long lhs, rhs; int flag1 = 0, flag2 = 0; + char *o1 = op1, *o2 = op2; - if(*op1 == '-') - { + if(op1 && *op1 == '-') { flag1 = 1; - op1++; + o1++; } - if(*op2 == '-') - { + if(*op2 == '-') { flag2 = 1; - op2++; + o2++; + } + lhs = op1 ? strtoul(o1, NULL, 0) : 0; + if(flag1) { + lhs = -lhs; + } + rhs = strtoul(o2, NULL, 0); + if(flag2) { + rhs = -rhs; } - lhs = strtoul(op1, NULL, 0); - if(flag1) lhs = -lhs; - rhs = strtoul(op2, NULL, 0); - if(flag2) rhs = -rhs; switch(op) { @@ -216,7 +231,11 @@ static int eval(int op, char *op1, char *op2, char **buffer) value = lhs * rhs; break; case 3: - value = lhs / rhs; + if(rhs != 0) + value = lhs / rhs; + else { + err_val = -2; + } break; case 4: value = lhs % rhs; @@ -227,29 +246,29 @@ static int eval(int op, char *op1, char *op2, char **buffer) case 6: value = lhs - rhs; break; - case 7: - value = lhs < rhs; + case 7: + value = !strcmp(op1, op2); break; case 8: - value = lhs <= rhs; + value = lhs < rhs; break; case 9: - value = lhs << rhs; + value = lhs <= rhs; break; case 10: - value = lhs > rhs; + value = lhs << rhs; break; case 11: - value = lhs >= rhs; + value = lhs > rhs; break; case 12: - value = lhs >> rhs; + value = lhs >= rhs; break; - case 13: - value = strcmp(op1, op2) ? 1 : 0; + case 13: + value = lhs >> rhs; break; case 14: - value = !strcmp(op1, op2); + value = strcmp(op1, op2) ? 1 : 0; break; case 15: value = lhs & rhs; @@ -267,91 +286,119 @@ static int eval(int op, char *op1, char *op2, char **buffer) value = lhs || rhs; break; - default: - err_val = -1; - return 0; - //printf("Undefined operator\n"); + default: //This should not happen + *buffer = NULL; + err_val = -3; + return err_val; } - return asprintf(buffer, "%ld", value); + if(asprintf(buffer, "%ld", value) < 0) { + err_val = -ENOMEM; + return err_val; + } + return strlen(*buffer); } -static int parse_prio(int prio, char **buffer) -{ +static int parse_prio(int prio, char **buffer) { int op; char *lc, *rc; - - if(tok < MIN_TOK || tok == TOK_MINUS || tok == TOK_PLUS) //All operators are >= 128. If it is not an operator, look for number - { + + if(tok < MIN_TOK || tok == TOK_MINUS || tok == TOK_PLUS) { parse_num(&lc); + } else { + if(tok < MIN_TOK + 2) { + lc = NULL; + } else { + err_val = -1; + return -1; + } } - else asprintf(&lc, " "); - if(err_val) - return 0; - while(tok != -1 && tok >= MIN_TOK && (op_prio[tok - MIN_TOK] > prio - (tok - MIN_TOK <= 1) ? 1 : 0) ) - { + + if(err_val) { + return -1; + } + while(tok != -1 && tok != ')') { long lhs; + if(tok < MIN_TOK) { + err_val = -1; + if(lc) free(lc); + return -1; + } + if(op_prio[tok - MIN_TOK] <= prio - (tok - MIN_TOK <= 1) ? 1 : 0) { + break; + } + op = tok; input(); parse_prio(op_prio[op - MIN_TOK], &rc); - if(err_val) - return 0; + if(err_val) { + if(lc) free(lc); + return -1; + } lhs = eval(op - MIN_TOK, lc, rc, buffer); free(rc); - free(lc); + if(lc) free(lc); + if(err_val) { + return -1; + } lc = *buffer; - - if(err_val) - return 0; } *buffer = lc; return strlen(*buffer); } -static int parse_expr(char **buffer) -{ +static int parse_expr(char **buffer) { return parse_prio(-1, buffer); } -int parse_arith(char *inp_string, char **end, char **buffer) -{ +int parse_arith(char *inp_string, char **end, char **buffer) { err_val = tok = 0; inp = inp_string; + brackets = 0; input(); + *buffer = NULL; + skip('('); + brackets++; parse_expr(buffer); + if(!err_val) { + skip(')'); + } - if(err_val) //Read till we get a ')' - { + if(err_val) { //Read till we get a ')' *end = strchr(inp, ')'); - if(!*end) + if(!*end) { *end = inp; - else end++; - } - else - *end = prev; - - if(err_val) - { - printf("parse error\n"); - return 0; + } else { + (*end) += 1; + } + switch (err_val) { + case -1: + printf("parse error\n"); + break; + case -2: + printf("division by 0\n"); + break; + case -ENOMEM: + printf("out of memory\n"); + break; + } + return -1; } + *end = prev; return strlen(*buffer); - - return -1; } #ifdef __ARITH_TEST__ -int main(int argc, char *argv[]) -{ +int main(int argc, char *argv[]) { char *ret_val; int r; char *tail; r = parse_arith(argv[1], &tail, &ret_val); if(r < 0) - printf("%d Tail: %s\n", r, tail); + printf("%d %s Tail: %s\n", r, ret_val, tail); else printf("%s Tail:%s\n", ret_val, tail); return 0; diff --git a/src/include/gpxe/errfile.h b/src/include/gpxe/errfile.h index 7ca9c998..5b80439c 100644 --- a/src/include/gpxe/errfile.h +++ b/src/include/gpxe/errfile.h @@ -174,6 +174,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_pxemenu ( ERRFILE_OTHER | 0x00150000 ) #define ERRFILE_x509 ( ERRFILE_OTHER | 0x00160000 ) #define ERRFILE_login_ui ( ERRFILE_OTHER | 0x00170000 ) +#define ERRFILE_arith ( ERRFILE_OTHER | 0x00180000 ) /** @} */ -- 2.17.1