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

lept_parse_number无法处理一些异常情况

Open alberttom opened this issue 9 years ago • 3 comments

lept_parse_number无法处理诸如12a.2这类错误,是否应该用状态机实现?

alberttom avatar Sep 21 '16 12:09 alberttom

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 != '\0' && *p != '.' && *p != 'e' && *p != 'E')
            return LEPT_PARSE_INVALID_VALUE;
    }
    if (*p == '.') {
        p++;
        if (!ISDIGIT(*p)) 
            return LEPT_PARSE_INVALID_VALUE;
        for (p++; ISDIGIT(*p); p++);
        if(*p != '\0' && *p != 'e' && *p != 'E')
            return LEPT_PARSE_INVALID_VALUE;
    }
    if (*p == 'e' || *p == 'E') {
        p++;
        if (*p == '+' || *p == '-')
            p++;
        if (!ISDIGIT(*p))
            return LEPT_PARSE_INVALID_VALUE;
        for (p++; ISDIGIT(*p); p++);
        if(*p != '\0')
            return LEPT_PARSE_INVALID_VALUE;
    }
    errno = 0;
    v->n = strtod(c->json, NULL);
    if (errno == ERANGE && (v->n == HUGE_VAL || v->n == -HUGE_VAL)) 
        return LEPT_PARSE_NUMBER_TOO_BIG;
    v->type = LEPT_NUMBER;
    c->json = p;
    return LEPT_PARSE_OK;
}

这样可以处理

    TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "112a.0");
    TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "112.0a");
    TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "112.012e12a");

alberttom avatar Sep 21 '16 12:09 alberttom

此问题与 #21 相同, 因为解析数字的时候一般设计成尽可能多的转换合法字符(例如标准库中的strtod()), 而不是遇到一个不合法字符就抛出错误. 所以 112a.0 的解析结果是 112, 同时也会返回 LEPT_PARSE_ROOT_NOT_SINGULAR 错误.

j178 avatar Sep 21 '16 13:09 j178

这样做的话,还要考虑之后的字符可能是 ,]}, ws 等。 建议只需要按照 number 的规则,只解析所有合法的字符。

miloyip avatar Sep 21 '16 13:09 miloyip