检查代码时发现有一个IP地址合法性检查的函数存在一些bug,先贴代码:
static int is_valid_ip(const char *ip) { int section = 0; int dot = 0; int last = -1; while (*ip) //因为\0的ASCII码是0 { if (*ip == '.') {//检测到.则对之前的section进行检验 dot++; if (dot > 3) { return 0; }//最多3个‘.’,超过说明异常 if (section >= 0 && section <= 255) //应该先检验255,因为从下面看,有符号数会被第一时间检测到异常,所以小于0的情况不会出现 { section = 0;//清零 } else { return 0;//无效的section } } else if (*ip >= '0' && *ip <= '9') //该位为数字 { section = section * 10 + *ip - '0';//据此计算section,旧的数字乘以10以后加上现在的数字 if (last == '0') //上一位数字为0 { return 0;//异常,因为不应该出现两位0 } } else//IP异常的情况 { return 0; } last = *ip; ip++; } if (section >= 0 && section <= 255) {//判定第四段section合法 if (3 == dot) { section = 0; return 1; } } return 0; }
问题出在两方面:
第一是,没有对section进行计数,导致形如“.XXX.XXX.XXX”的非法地址能够通过检验;
第二是,last判别非法存在误判,如101这种地址,last为0时,读取到个位的1时,会判定为非法地址;正确的判定方法应该为,如果当前section为0,而当前读到的数字也为0,则判定为非法,这样无论上一位是不是'.',都可以正确的判定了。