json-tutorial icon indicating copy to clipboard operation
json-tutorial copied to clipboard

整数部分如果是 0 开始,只能是单个 0的问题

Open Andrewpqc opened this issue 6 years ago • 2 comments

按照教程中提到的JSON标准,JSON数字整数部分如果是 0 开始,只能是单个 0.也就是说形如00.1.-00.1这样的数字在解析时应该返回LEPT_PARSE_INVALID_VALUE才对。但是目前lept_parse_number的校验过程没有实现这一点。

下面是原始代码:

static int lept_parse_number(lept_context* c, lept_value* v) {
    const char* p = c->json;
    if (*p == '-') p++;
    if (*p == '0') p++;
    else {
        if (!ISDIGIT1TO9(*p)) return LEPT_PARSE_INVALID_VALUE;
        for (p++; ISDIGIT(*p); p++);
    }
    if (*p == '.') {
        p++;
        if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE;
        for (p++; ISDIGIT(*p); p++);
    }
    if (*p == 'e' || *p == 'E') {
        p++;
        if (*p == '+' || *p == '-') p++;
        if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE;
        for (p++; ISDIGIT(*p); p++);
    }
    errno = 0;
    v->u.n = strtod(c->json, NULL);
    if (errno == ERANGE && (v->u.n == HUGE_VAL || v->u.n == -HUGE_VAL))
        return LEPT_PARSE_NUMBER_TOO_BIG;
    v->type = LEPT_NUMBER;
    c->json = p;
    return LEPT_PARSE_OK;
}

建议改成下面这样:

static int lept_parse_number(lept_context* c, lept_value* v) {
    const char* p = c->json;
    if (*p == '-') p++;
    if (*p == '0') p++;
    else {
        if (!ISDIGIT1TO9(*p)) return LEPT_PARSE_INVALID_VALUE;
        for (p++; ISDIGIT(*p); p++);
    }
    if (*p == '.') {
        p++;
        if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE;
        for (p++; ISDIGIT(*p); p++);
    }
    if (*p == 'e' || *p == 'E') {
        p++;
        if (*p == '+' || *p == '-') p++;
        if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE;
        for (p++; ISDIGIT(*p); p++);
    }
    
    // added
    if(*p=='0') return LEPT_PARSE_INVALID_VALUE;

    errno = 0;
    v->u.n = strtod(c->json, NULL);
    if (errno == ERANGE && (v->u.n == HUGE_VAL || v->u.n == -HUGE_VAL))
        return LEPT_PARSE_NUMBER_TOO_BIG;
    v->type = LEPT_NUMBER;
    c->json = p;
    return LEPT_PARSE_OK;
}

然后在test_parse_invalid_value中加上下面两条测试:

TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "00.1");
TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "-00.1");

Andrewpqc avatar Sep 02 '18 03:09 Andrewpqc

see https://github.com/miloyip/json-tutorial/issues/15

imba-tjd avatar Sep 03 '18 07:09 imba-tjd

我也是刚写到这发现差点,我是直接在检测到0后看后面是不是数字:

if(*p == '-') p++;
    if(*p == '0') {
        p++;
        if(ISDIGIT(*p))
            return LC_PARSE_INVALID_VALUE;
    } else {
        if(!ISDIGIT1TO9(*p)) return LC_PARSE_INVALID_VALUE;
        for(p++; ISDIGIT(*p); p++);
    }

    if(*p == '.'){
        p++;
        if(!ISDIGIT(*p))    return LC_PARSE_INVALID_VALUE;
        for(p++; ISDIGIT(*p); p++);
    }
    if(*p == 'e' || *p == 'E'){
        p++;
        if(*p == '+' || *p == '-')  p++;
        if(!ISDIGIT(*p)) return LC_PARSE_INVALID_VALUE;
        for(p++; ISDIGIT(*p); p++);
    }

imarvinle avatar Dec 27 '18 12:12 imarvinle