ngx_int_t
-ngx_json_unescape_string(ngx_str_t *str)
+ngx_json_unescape_string(ngx_str_t *dst, ngx_str_t *src)
{
size_t size;
- u_char *d, *s, *start, ch;
+ u_char *d, *s, ch;
uint32_t codepoint, high_surrogate;
ngx_int_t n;
ngx_uint_t hex_left;
* The pair decodes to U+10000 + (high - 0xD800) * 0x400
* + (low - 0xDC00).
* The input is an unquoted JSON string body (the bytes between the
- * surrounding double quotes); it is decoded in place.
+ * surrounding double quotes).
*/
- if (str->len == 0) {
+ if (src->len == 0) {
+ dst->len = 0;
return NGX_OK;
}
- if (str->data == NULL) {
+ if (dst->len < src->len) {
return NGX_ERROR;
}
- start = str->data;
- size = str->len;
+ s = src->data;
+ d = dst->data;
+ size = src->len;
- d = s = start;
state = sw_usual;
codepoint = 0;
return NGX_ERROR;
}
- str->data = start;
- str->len = d - start;
+ dst->len = d - dst->data;
return NGX_OK;
}
/*
- * Decode JSON escape sequences (RFC 8259, Section 7) in place. The input
- * is an unquoted JSON string body (no surrounding double quotes); on success
- * str->len is updated to the decoded length. Returns NGX_OK, or NGX_ERROR
- * on a malformed escape or invalid input.
+ * Decode JSON escape sequences (RFC 8259, Section 7). The input
+ * is an unquoted JSON string body (no surrounding double quotes).
+ *
+ * On entry, dst->len is the capacity of dst->data and must be at least
+ * src->len.
+ * On success, dst->len is the decoded length.
+ *
+ * Returns NGX_OK, or NGX_ERROR on a malformed escape or invalid input.
*/
-ngx_int_t ngx_json_unescape_string(ngx_str_t *str);
+ngx_int_t ngx_json_unescape_string(ngx_str_t *dst, ngx_str_t *src);
+
ngx_int_t ngx_json_hex_digit(u_char ch);
{
u_char *p, *last, *start, *dst;
ngx_int_t index;
+ ngx_str_t raw;
ngx_uint_t *term;
ngx_http_json_seg_t seg;
ngx_http_json_node_t *node;
return NGX_CONF_ERROR;
}
- ngx_memcpy(dst, start, p - start);
+ raw.data = start;
+ raw.len = p - start;
seg.is_index = 0;
seg.key.data = dst;
seg.key.len = p - start;
seg.index = 0;
- if (ngx_json_unescape_string(&seg.key) != NGX_OK) {
+ if (ngx_json_unescape_string(&seg.key, &raw) != NGX_OK) {
goto invalid;
}
state->current_key = *token;
} else {
- state->current_key.data = ngx_pstrdup(ctx->pool, token);
+ state->current_key.data = ngx_pnalloc(ctx->pool, token->len);
if (state->current_key.data == NULL) {
return NGX_ERROR;
}
state->current_key.len = token->len;
- if (ngx_json_unescape_string(&state->current_key) != NGX_OK) {
+ if (ngx_json_unescape_string(&state->current_key, token) != NGX_OK)
+ {
return NGX_ERROR;
}
}
val.len = 0;
val.data = (u_char *) "";
- } else {
- val.data = ngx_pstrdup(state->r->pool, value);
+ } else if (unescape) {
+ val.data = ngx_pnalloc(state->r->pool, value->len);
if (val.data == NULL) {
return NGX_ERROR;
}
val.len = value->len;
- if (unescape && ngx_json_unescape_string(&val) != NGX_OK) {
+ if (ngx_json_unescape_string(&val, value) != NGX_OK) {
return NGX_ERROR;
}
+
+ } else {
+ val.data = ngx_pstrdup(state->r->pool, value);
+ if (val.data == NULL) {
+ return NGX_ERROR;
+ }
+
+ val.len = value->len;
}
for (i = 0; i < node->ndests; i++) {