Controller: more HTTP headers and detailed JSON parsing errors.
This commit is contained in:
357
src/nxt_conf.c
357
src/nxt_conf.c
@@ -48,8 +48,8 @@ struct nxt_conf_value_s {
|
||||
double number;
|
||||
|
||||
struct {
|
||||
uint8_t length;
|
||||
u_char start[NXT_CONF_MAX_SHORT_STRING];
|
||||
uint8_t length;
|
||||
} str;
|
||||
|
||||
struct {
|
||||
@@ -93,9 +93,9 @@ struct nxt_conf_op_s {
|
||||
|
||||
static u_char *nxt_conf_json_skip_space(u_char *start, u_char *end);
|
||||
static u_char *nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value,
|
||||
u_char *start, u_char *end);
|
||||
u_char *start, u_char *end, nxt_conf_json_error_t *error);
|
||||
static u_char *nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value,
|
||||
u_char *start, u_char *end);
|
||||
u_char *start, u_char *end, nxt_conf_json_error_t *error);
|
||||
static nxt_int_t nxt_conf_object_hash_add(nxt_mp_t *mp,
|
||||
nxt_lvlhsh_t *lvlhsh, nxt_conf_object_member_t *member);
|
||||
static nxt_int_t nxt_conf_object_hash_test(nxt_lvlhsh_query_t *lhq,
|
||||
@@ -103,11 +103,13 @@ static nxt_int_t nxt_conf_object_hash_test(nxt_lvlhsh_query_t *lhq,
|
||||
static void *nxt_conf_object_hash_alloc(void *data, size_t size);
|
||||
static void nxt_conf_object_hash_free(void *data, void *p);
|
||||
static u_char *nxt_conf_json_parse_array(nxt_mp_t *mp, nxt_conf_value_t *value,
|
||||
u_char *start, u_char *end);
|
||||
u_char *start, u_char *end, nxt_conf_json_error_t *error);
|
||||
static u_char *nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value,
|
||||
u_char *start, u_char *end);
|
||||
u_char *start, u_char *end, nxt_conf_json_error_t *error);
|
||||
static u_char *nxt_conf_json_parse_number(nxt_mp_t *mp, nxt_conf_value_t *value,
|
||||
u_char *start, u_char *end);
|
||||
u_char *start, u_char *end, nxt_conf_json_error_t *error);
|
||||
static void nxt_conf_json_parse_error(nxt_conf_json_error_t *error, u_char *pos,
|
||||
const char *detail);
|
||||
|
||||
static nxt_int_t nxt_conf_copy_value(nxt_mp_t *mp, nxt_conf_op_t *op,
|
||||
nxt_conf_value_t *dst, nxt_conf_value_t *src);
|
||||
@@ -192,8 +194,8 @@ nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count)
|
||||
}
|
||||
|
||||
|
||||
nxt_int_t
|
||||
nxt_conf_set_object_member(nxt_conf_value_t *object, nxt_str_t *name,
|
||||
void
|
||||
nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name,
|
||||
nxt_conf_value_t *value, uint32_t index)
|
||||
{
|
||||
nxt_conf_value_t *name_value;
|
||||
@@ -215,8 +217,71 @@ nxt_conf_set_object_member(nxt_conf_value_t *object, nxt_str_t *name,
|
||||
}
|
||||
|
||||
member->value = *value;
|
||||
}
|
||||
|
||||
return NXT_OK;
|
||||
|
||||
void
|
||||
nxt_conf_set_member_string(nxt_conf_value_t *object, nxt_str_t *name,
|
||||
nxt_str_t *value, uint32_t index)
|
||||
{
|
||||
nxt_conf_value_t *set;
|
||||
nxt_conf_object_member_t *member;
|
||||
|
||||
member = &object->u.object->members[index];
|
||||
set = &member->name;
|
||||
|
||||
if (name->length > NXT_CONF_MAX_SHORT_STRING) {
|
||||
set->type = NXT_CONF_VALUE_STRING;
|
||||
set->u.string.length = name->length;
|
||||
set->u.string.start = name->start;
|
||||
|
||||
} else {
|
||||
set->type = NXT_CONF_VALUE_SHORT_STRING;
|
||||
set->u.str.length = name->length;
|
||||
|
||||
nxt_memcpy(set->u.str.start, name->start, name->length);
|
||||
}
|
||||
|
||||
set = &member->value;
|
||||
|
||||
if (value->length > NXT_CONF_MAX_SHORT_STRING) {
|
||||
set->type = NXT_CONF_VALUE_STRING;
|
||||
set->u.string.length = value->length;
|
||||
set->u.string.start = value->start;
|
||||
|
||||
} else {
|
||||
set->type = NXT_CONF_VALUE_SHORT_STRING;
|
||||
set->u.str.length = value->length;
|
||||
|
||||
nxt_memcpy(set->u.str.start, value->start, value->length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_conf_set_member_integer(nxt_conf_value_t *object, nxt_str_t *name,
|
||||
int64_t value, uint32_t index)
|
||||
{
|
||||
nxt_conf_value_t *name_value;
|
||||
nxt_conf_object_member_t *member;
|
||||
|
||||
member = &object->u.object->members[index];
|
||||
name_value = &member->name;
|
||||
|
||||
if (name->length > NXT_CONF_MAX_SHORT_STRING) {
|
||||
name_value->type = NXT_CONF_VALUE_STRING;
|
||||
name_value->u.string.length = name->length;
|
||||
name_value->u.string.start = name->start;
|
||||
|
||||
} else {
|
||||
name_value->type = NXT_CONF_VALUE_SHORT_STRING;
|
||||
name_value->u.str.length = name->length;
|
||||
|
||||
nxt_memcpy(name_value->u.str.start, name->start, name->length);
|
||||
}
|
||||
|
||||
member->value.u.integer = value;
|
||||
member->value.type = NXT_CONF_VALUE_INTEGER;
|
||||
}
|
||||
|
||||
|
||||
@@ -802,7 +867,8 @@ nxt_conf_copy_object(nxt_mp_t *mp, nxt_conf_op_t *op, nxt_conf_value_t *dst,
|
||||
|
||||
|
||||
nxt_conf_value_t *
|
||||
nxt_conf_json_parse(nxt_mp_t *mp, u_char *start, u_char *end)
|
||||
nxt_conf_json_parse(nxt_mp_t *mp, u_char *start, u_char *end,
|
||||
nxt_conf_json_error_t *error)
|
||||
{
|
||||
u_char *p;
|
||||
nxt_conf_value_t *value;
|
||||
@@ -815,10 +881,17 @@ nxt_conf_json_parse(nxt_mp_t *mp, u_char *start, u_char *end)
|
||||
p = nxt_conf_json_skip_space(start, end);
|
||||
|
||||
if (nxt_slow_path(p == end)) {
|
||||
|
||||
nxt_conf_json_parse_error(error, start,
|
||||
"An empty JSON isn't allowed. It must be either literal "
|
||||
"(null, true, or false), number, string (in double quotes \"\"), "
|
||||
"array (with brackets []), or object (with braces {})."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = nxt_conf_json_parse_value(mp, value, p, end);
|
||||
p = nxt_conf_json_parse_value(mp, value, p, end, error);
|
||||
|
||||
if (nxt_slow_path(p == NULL)) {
|
||||
return NULL;
|
||||
@@ -827,6 +900,11 @@ nxt_conf_json_parse(nxt_mp_t *mp, u_char *start, u_char *end)
|
||||
p = nxt_conf_json_skip_space(p, end);
|
||||
|
||||
if (nxt_slow_path(p != end)) {
|
||||
|
||||
nxt_conf_json_parse_error(error, p,
|
||||
"Unexpected character after the end of valid JSON value."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -858,21 +936,21 @@ nxt_conf_json_skip_space(u_char *start, u_char *end)
|
||||
|
||||
static u_char *
|
||||
nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
u_char *end)
|
||||
u_char *end, nxt_conf_json_error_t *error)
|
||||
{
|
||||
u_char ch;
|
||||
u_char ch, *p;
|
||||
|
||||
ch = *start;
|
||||
|
||||
switch (ch) {
|
||||
case '{':
|
||||
return nxt_conf_json_parse_object(mp, value, start, end);
|
||||
return nxt_conf_json_parse_object(mp, value, start, end, error);
|
||||
|
||||
case '[':
|
||||
return nxt_conf_json_parse_array(mp, value, start, end);
|
||||
return nxt_conf_json_parse_array(mp, value, start, end, error);
|
||||
|
||||
case '"':
|
||||
return nxt_conf_json_parse_string(mp, value, start, end);
|
||||
return nxt_conf_json_parse_string(mp, value, start, end, error);
|
||||
|
||||
case 't':
|
||||
if (nxt_fast_path(end - start >= 4
|
||||
@@ -884,7 +962,7 @@ nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
return start + 4;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
goto error;
|
||||
|
||||
case 'f':
|
||||
if (nxt_fast_path(end - start >= 5
|
||||
@@ -896,7 +974,7 @@ nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
return start + 5;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
goto error;
|
||||
|
||||
case 'n':
|
||||
if (nxt_fast_path(end - start >= 4
|
||||
@@ -906,13 +984,47 @@ nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
return start + 4;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
goto error;
|
||||
|
||||
case '-':
|
||||
if (nxt_fast_path(end - start > 1)) {
|
||||
ch = start[1];
|
||||
break;
|
||||
}
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (nxt_fast_path(ch == '-' || (ch - '0') <= 9)) {
|
||||
return nxt_conf_json_parse_number(mp, value, start, end);
|
||||
if (nxt_fast_path((ch - '0') <= 9)) {
|
||||
p = nxt_conf_json_parse_number(mp, value, start, end, error);
|
||||
|
||||
if (p == end) {
|
||||
return end;
|
||||
}
|
||||
|
||||
switch (*p) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
case ',':
|
||||
case '}':
|
||||
case ']':
|
||||
case '{':
|
||||
case '[':
|
||||
case '"':
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
error:
|
||||
|
||||
nxt_conf_json_parse_error(error, start,
|
||||
"A valid JSON value is expected here. It must be either literal "
|
||||
"(null, true, or false), number, string (in double quotes \"\"), "
|
||||
"array (with brackets []), or object (with braces {})."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -929,9 +1041,9 @@ static const nxt_lvlhsh_proto_t nxt_conf_object_hash_proto
|
||||
|
||||
static u_char *
|
||||
nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
u_char *end)
|
||||
u_char *end, nxt_conf_json_error_t *error)
|
||||
{
|
||||
u_char *p;
|
||||
u_char *p, *name;
|
||||
nxt_mp_t *mp_temp;
|
||||
nxt_int_t rc;
|
||||
nxt_uint_t count;
|
||||
@@ -954,6 +1066,12 @@ nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
p = nxt_conf_json_skip_space(p + 1, end);
|
||||
|
||||
if (nxt_slow_path(p == end)) {
|
||||
|
||||
nxt_conf_json_parse_error(error, p,
|
||||
"Unexpected end of JSON. There's an object without closing "
|
||||
"brace (})."
|
||||
);
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -962,9 +1080,17 @@ nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
break;
|
||||
}
|
||||
|
||||
nxt_conf_json_parse_error(error, p,
|
||||
"A double quote (\") is expected here. There must be a valid "
|
||||
"JSON object member starts with a name, which is a string "
|
||||
"enclosed in double quotes."
|
||||
);
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
name = p;
|
||||
|
||||
count++;
|
||||
|
||||
member = nxt_mp_get(mp_temp, sizeof(nxt_conf_object_member_t));
|
||||
@@ -972,7 +1098,7 @@ nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
goto error;
|
||||
}
|
||||
|
||||
p = nxt_conf_json_parse_string(mp, &member->name, p, end);
|
||||
p = nxt_conf_json_parse_string(mp, &member->name, p, end, error);
|
||||
|
||||
if (nxt_slow_path(p == NULL)) {
|
||||
goto error;
|
||||
@@ -981,22 +1107,52 @@ nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
rc = nxt_conf_object_hash_add(mp_temp, &hash, member);
|
||||
|
||||
if (nxt_slow_path(rc != NXT_OK)) {
|
||||
|
||||
if (rc == NXT_DECLINED) {
|
||||
nxt_conf_json_parse_error(error, name,
|
||||
"Duplicate object member. All JSON object members must "
|
||||
"have unique names."
|
||||
);
|
||||
}
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
p = nxt_conf_json_skip_space(p, end);
|
||||
|
||||
if (nxt_slow_path(p == end || *p != ':')) {
|
||||
if (nxt_slow_path(p == end)) {
|
||||
|
||||
nxt_conf_json_parse_error(error, p,
|
||||
"Unexpected end of JSON. There's an object member without "
|
||||
"value."
|
||||
);
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (nxt_slow_path(*p != ':')) {
|
||||
|
||||
nxt_conf_json_parse_error(error, p,
|
||||
"A colon (:) is expected here. There must be a colon between "
|
||||
"JSON member name and value."
|
||||
);
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
p = nxt_conf_json_skip_space(p + 1, end);
|
||||
|
||||
if (nxt_slow_path(p == end)) {
|
||||
|
||||
nxt_conf_json_parse_error(error, p,
|
||||
"Unexpected end of JSON. There's an object member without "
|
||||
"value."
|
||||
);
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
p = nxt_conf_json_parse_value(mp, &member->value, p, end);
|
||||
p = nxt_conf_json_parse_value(mp, &member->value, p, end, error);
|
||||
|
||||
if (nxt_slow_path(p == NULL)) {
|
||||
goto error;
|
||||
@@ -1005,6 +1161,12 @@ nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
p = nxt_conf_json_skip_space(p, end);
|
||||
|
||||
if (nxt_slow_path(p == end)) {
|
||||
|
||||
nxt_conf_json_parse_error(error, p,
|
||||
"Unexpected end of JSON. There's an object without closing "
|
||||
"brace (})."
|
||||
);
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1013,6 +1175,12 @@ nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
break;
|
||||
}
|
||||
|
||||
nxt_conf_json_parse_error(error, p,
|
||||
"Either a closing brace (}) or a comma (,) is expected here. "
|
||||
"In JSON, all object members must be enclosed in braces and "
|
||||
"separated by commas."
|
||||
);
|
||||
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@@ -1081,11 +1249,7 @@ nxt_conf_object_hash_test(nxt_lvlhsh_query_t *lhq, void *data)
|
||||
|
||||
nxt_conf_get_string(&member->name, &str);
|
||||
|
||||
if (nxt_strstr_eq(&lhq->key, &str)) {
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
return NXT_DECLINED;
|
||||
return nxt_strstr_eq(&lhq->key, &str) ? NXT_OK : NXT_DECLINED;
|
||||
}
|
||||
|
||||
|
||||
@@ -1105,7 +1269,7 @@ nxt_conf_object_hash_free(void *data, void *p)
|
||||
|
||||
static u_char *
|
||||
nxt_conf_json_parse_array(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
u_char *end)
|
||||
u_char *end, nxt_conf_json_error_t *error)
|
||||
{
|
||||
u_char *p;
|
||||
nxt_mp_t *mp_temp;
|
||||
@@ -1131,6 +1295,12 @@ nxt_conf_json_parse_array(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
p = nxt_conf_json_skip_space(p + 1, end);
|
||||
|
||||
if (nxt_slow_path(p == end)) {
|
||||
|
||||
nxt_conf_json_parse_error(error, p,
|
||||
"Unexpected end of JSON. There's an array without closing "
|
||||
"bracket (])."
|
||||
);
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1145,7 +1315,7 @@ nxt_conf_json_parse_array(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
goto error;
|
||||
}
|
||||
|
||||
p = nxt_conf_json_parse_value(mp, element, p, end);
|
||||
p = nxt_conf_json_parse_value(mp, element, p, end, error);
|
||||
|
||||
if (nxt_slow_path(p == NULL)) {
|
||||
goto error;
|
||||
@@ -1154,6 +1324,12 @@ nxt_conf_json_parse_array(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
p = nxt_conf_json_skip_space(p, end);
|
||||
|
||||
if (nxt_slow_path(p == end)) {
|
||||
|
||||
nxt_conf_json_parse_error(error, p,
|
||||
"Unexpected end of JSON. There's an array without closing "
|
||||
"bracket (])."
|
||||
);
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1162,6 +1338,12 @@ nxt_conf_json_parse_array(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
break;
|
||||
}
|
||||
|
||||
nxt_conf_json_parse_error(error, p,
|
||||
"Either a closing bracket (]) or a comma (,) is expected here. "
|
||||
"In JSON, all array members must be enclosed in brackets and "
|
||||
"separated by commas."
|
||||
);
|
||||
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@@ -1195,7 +1377,7 @@ error:
|
||||
|
||||
static u_char *
|
||||
nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
u_char *end)
|
||||
u_char *end, nxt_conf_json_error_t *error)
|
||||
{
|
||||
u_char *p, ch, *last, *s;
|
||||
size_t size, surplus;
|
||||
@@ -1235,6 +1417,11 @@ nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
continue;
|
||||
}
|
||||
|
||||
nxt_conf_json_parse_error(error, p,
|
||||
"Unexpected character in string. All control characters must "
|
||||
"be escaped in JSON strings."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
|
||||
case sw_escape:
|
||||
@@ -1265,6 +1452,12 @@ nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
continue;
|
||||
}
|
||||
|
||||
nxt_conf_json_parse_error(error, p - 1,
|
||||
"Unexpected reverse solidus in string. Reverse solidus in "
|
||||
"JSON strings must be escaped with a second reverse solidus "
|
||||
"(\\\\)."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
|
||||
case sw_encoded1:
|
||||
@@ -1280,6 +1473,12 @@ nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
continue;
|
||||
}
|
||||
|
||||
nxt_conf_json_parse_error(error, p,
|
||||
"Invalid escape sequence. In JSON, escape sequences start "
|
||||
"with a reverse solidus, followed by the lowercase letter u, "
|
||||
"followed by four hexadecimal digits (\\uXXXX)."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1287,6 +1486,12 @@ nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
}
|
||||
|
||||
if (nxt_slow_path(p == end)) {
|
||||
|
||||
nxt_conf_json_parse_error(error, p,
|
||||
"Unexpected end of JSON. There's a string without ending double "
|
||||
"quote (\")."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1298,6 +1503,12 @@ nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
if (size > NXT_CONF_MAX_SHORT_STRING) {
|
||||
|
||||
if (nxt_slow_path(size > NXT_CONF_MAX_STRING)) {
|
||||
|
||||
nxt_conf_json_parse_error(error, start,
|
||||
"Too long string. Such a big JSON string values are not "
|
||||
"supported."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1377,6 +1588,13 @@ nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
|
||||
if (utf_high != 0) {
|
||||
if (nxt_slow_path(utf < 0xdc00 || utf > 0xdfff)) {
|
||||
|
||||
nxt_conf_json_parse_error(error, p - 12,
|
||||
"Invalid JSON encoding sequence. There's a 12 bytes "
|
||||
"sequence that composes an illegal UTF-16 surrogate "
|
||||
"pair."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1390,6 +1608,12 @@ nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
}
|
||||
|
||||
if (utf > 0xdbff || p[0] != '\\' || p[1] != 'u') {
|
||||
|
||||
nxt_conf_json_parse_error(error, p - 6,
|
||||
"Invalid JSON encoding sequence. There's a 6 bytes "
|
||||
"sequence that doesn't represent a valid character."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1416,7 +1640,7 @@ nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
|
||||
static u_char *
|
||||
nxt_conf_json_parse_number(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
u_char *end)
|
||||
u_char *end, nxt_conf_json_error_t *error)
|
||||
{
|
||||
u_char *p, ch;
|
||||
uint64_t integer;
|
||||
@@ -1454,13 +1678,23 @@ nxt_conf_json_parse_number(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
if (nxt_slow_path(integer >= cutoff
|
||||
&& (integer > cutoff || ch > cutlim)))
|
||||
{
|
||||
return NULL;
|
||||
nxt_conf_json_parse_error(error, start,
|
||||
"Too big integer. Such a big JSON integer values are not "
|
||||
"supported."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
integer = integer * 10 + ch;
|
||||
}
|
||||
|
||||
if (nxt_slow_path(p == start || (p - start > 1 && *start == '0'))) {
|
||||
if (nxt_slow_path(p - start > 1 && *start == '0')) {
|
||||
|
||||
nxt_conf_json_parse_error(error, start,
|
||||
"Leading zeros are not allowed in JSON numbers."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1549,12 +1783,32 @@ nxt_conf_json_parse_number(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start,
|
||||
if (nxt_fast_path(isfinite(value->u.number))) {
|
||||
return p;
|
||||
}
|
||||
#else
|
||||
|
||||
nxt_conf_json_parse_error(error, start,
|
||||
"Invalid number. Only integer JSON numbers without fraction and "
|
||||
"exponent parts are supported."
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nxt_conf_json_parse_error(nxt_conf_json_error_t *error, u_char *pos,
|
||||
const char *detail)
|
||||
{
|
||||
if (error == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
error->pos = pos;
|
||||
error->detail = (u_char *) detail;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
nxt_conf_json_length(nxt_conf_value_t *value, nxt_conf_json_pretty_t *pretty)
|
||||
{
|
||||
@@ -1983,3 +2237,32 @@ nxt_conf_json_escape(u_char *dst, u_char *src, size_t size)
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_conf_json_position(u_char *start, u_char *pos, nxt_uint_t *line,
|
||||
nxt_uint_t *column)
|
||||
{
|
||||
u_char *p;
|
||||
ssize_t symbols;
|
||||
nxt_uint_t lines;
|
||||
|
||||
lines = 1;
|
||||
|
||||
for (p = start; p != pos; p++) {
|
||||
|
||||
if (*p != '\n') {
|
||||
continue;
|
||||
}
|
||||
|
||||
lines++;
|
||||
start = p + 1;
|
||||
}
|
||||
|
||||
symbols = nxt_utf8_length(start, p - start);
|
||||
|
||||
if (symbols != -1) {
|
||||
*line = lines;
|
||||
*column = 1 + symbols;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user