Skip to content

Commit 65bda75

Browse files
committed
fix: keys should be escaped
1 parent b4b266b commit 65bda75

File tree

1 file changed

+67
-65
lines changed

1 file changed

+67
-65
lines changed

json-build.h

Lines changed: 67 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,68 @@ jsonb_pop_object(jsonb *b, char buf[], size_t bufsize)
330330
return code;
331331
}
332332

333+
static long
334+
_jsonb_escape(
335+
size_t *pos, char buf[], size_t bufsize, const char str[], size_t len)
336+
{
337+
char *esc_tok = NULL, _esc_tok[8] = "\\u00";
338+
char *esc_buf = NULL;
339+
int extra_bytes = 0;
340+
size_t i;
341+
second_iter:
342+
/* 1st iteration, esc_buf is NULL and count extra_bytes needed for escaping
343+
* 2st iteration, esc_buf is not NULL, and does escaping. */
344+
for (i = 0; i < len; ++i) {
345+
unsigned char c = str[i];
346+
esc_tok = NULL;
347+
switch (c) {
348+
case 0x22: esc_tok = "\\\""; break;
349+
case 0x5C: esc_tok = "\\\\"; break;
350+
case '\b': esc_tok = "\\b"; break;
351+
case '\f': esc_tok = "\\f"; break;
352+
case '\n': esc_tok = "\\n"; break;
353+
case '\r': esc_tok = "\\r"; break;
354+
case '\t': esc_tok = "\\t"; break;
355+
default: if (c <= 0x1F) {
356+
static const char tohex[] = "0123456789abcdef";
357+
_esc_tok[4] = tohex[c >> 4];
358+
_esc_tok[5] = tohex[c & 0xF];
359+
_esc_tok[6] = 0;
360+
esc_tok = _esc_tok;
361+
}
362+
}
363+
if (esc_tok) {
364+
int j;
365+
for (j = 0; esc_tok[j]; j++) {
366+
if (!esc_buf) /* count how many extra bytes are needed */
367+
continue;
368+
*esc_buf++ = esc_tok[j];
369+
}
370+
extra_bytes += j - 1;
371+
}
372+
else if (esc_buf) {
373+
*esc_buf++ = c;
374+
}
375+
}
376+
377+
if (*pos + len + extra_bytes > bufsize) return JSONB_ERROR_NOMEM;
378+
379+
if (esc_buf) {
380+
*pos += len + extra_bytes;
381+
return JSONB_OK;
382+
}
383+
if (!extra_bytes) {
384+
size_t j;
385+
for (j = 0; j < len; ++j)
386+
buf[*pos + j] = str[j];
387+
*pos += len;
388+
return JSONB_OK;
389+
}
390+
esc_buf = buf + *pos;
391+
extra_bytes = 0;
392+
goto second_iter;
393+
}
394+
333395
jsonbcode
334396
jsonb_push_key(
335397
jsonb *b, char buf[], size_t bufsize, const char key[], size_t len)
@@ -339,12 +401,14 @@ jsonb_push_key(
339401
case JSONB_OBJECT_NEXT_KEY_OR_CLOSE:
340402
BUFFER_COPY_CHAR(b, ',', pos, buf, bufsize);
341403
/* fall-through */
342-
case JSONB_OBJECT_KEY_OR_CLOSE:
404+
case JSONB_OBJECT_KEY_OR_CLOSE: {
405+
enum jsonbcode ret;
343406
BUFFER_COPY_CHAR(b, '"', pos, buf, bufsize);
344-
BUFFER_COPY(b, key, len, pos, buf, bufsize);
407+
ret = _jsonb_escape(&pos, buf + b->pos, bufsize, key, len);
408+
if (ret != JSONB_OK) return ret;
345409
BUFFER_COPY(b, "\":", 2, pos, buf, bufsize);
346410
STACK_HEAD(b, JSONB_OBJECT_VALUE);
347-
break;
411+
} break;
348412
default:
349413
STACK_HEAD(b, JSONB_ERROR);
350414
/* fall-through */
@@ -466,68 +530,6 @@ jsonb_push_null(jsonb *b, char buf[], size_t bufsize)
466530
return jsonb_push_token(b, buf, bufsize, "null", 4);
467531
}
468532

469-
static long
470-
_jsonb_escape(
471-
size_t *pos, char buf[], size_t bufsize, const char str[], size_t len)
472-
{
473-
char *esc_tok = NULL, _esc_tok[8] = "\\u00";
474-
char *esc_buf = NULL;
475-
int extra_bytes = 0;
476-
size_t i;
477-
second_iter:
478-
/* 1st iteration, esc_buf is NULL and count extra_bytes needed for escaping
479-
* 2st iteration, esc_buf is not NULL, and does escaping. */
480-
for (i = 0; i < len; ++i) {
481-
unsigned char c = str[i];
482-
esc_tok = NULL;
483-
switch (c) {
484-
case 0x22: esc_tok = "\\\""; break;
485-
case 0x5C: esc_tok = "\\\\"; break;
486-
case '\b': esc_tok = "\\b"; break;
487-
case '\f': esc_tok = "\\f"; break;
488-
case '\n': esc_tok = "\\n"; break;
489-
case '\r': esc_tok = "\\r"; break;
490-
case '\t': esc_tok = "\\t"; break;
491-
default: if (c <= 0x1F) {
492-
static const char tohex[] = "0123456789abcdef";
493-
_esc_tok[4] = tohex[c >> 4];
494-
_esc_tok[5] = tohex[c & 0xF];
495-
_esc_tok[6] = 0;
496-
esc_tok = _esc_tok;
497-
}
498-
}
499-
if (esc_tok) {
500-
int j;
501-
for (j = 0; esc_tok[j]; j++) {
502-
if (!esc_buf) /* count how many extra bytes are needed */
503-
continue;
504-
*esc_buf++ = esc_tok[j];
505-
}
506-
extra_bytes += j - 1;
507-
}
508-
else if (esc_buf) {
509-
*esc_buf++ = c;
510-
}
511-
}
512-
513-
if (*pos + len + extra_bytes > bufsize) return JSONB_ERROR_NOMEM;
514-
515-
if (esc_buf) {
516-
*pos += len + extra_bytes;
517-
return JSONB_OK;
518-
}
519-
if (!extra_bytes) {
520-
size_t j;
521-
for (j = 0; j < len; ++j)
522-
buf[*pos + j] = str[j];
523-
*pos += len;
524-
return JSONB_OK;
525-
}
526-
esc_buf = buf + *pos;
527-
extra_bytes = 0;
528-
goto second_iter;
529-
}
530-
531533
jsonbcode
532534
jsonb_push_string(
533535
jsonb *b, char buf[], size_t bufsize, const char str[], size_t len)

0 commit comments

Comments
 (0)