Skip to content

Commit 4024e37

Browse files
committed
feat: add nul-terminator char in input token for extra safety and easier
debugging
1 parent 459e303 commit 4024e37

File tree

1 file changed

+22
-26
lines changed

1 file changed

+22
-26
lines changed

json-build.h

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Special thanks to Christopher Wellons (aka skeeto) for giving valuable
2+
* Special thanks to Christopher Wellons (aka skeeto) for giving valuable
33
* feedback that helped improve this lib.
44
*
55
* See: https://www.reddit.com/r/C_Programming/comments/sf95m3/comment/huojrjn
@@ -237,26 +237,28 @@ _jsonb_eval_state(enum jsonbstate state)
237237
#define DECORATOR(d) d
238238
#endif /* JSONB_DEBUG */
239239

240+
#define STACK_HEAD(b, state) *(b)->top = (state)
240241
#define STACK_PUSH(b, state) TRACE(*(b)->top, *++(b)->top = (state))
241242
#define STACK_POP(b) TRACE(*(b)->top, DECORATOR(*)--(b)->top)
242-
#define STACK_HEAD(b, state) TRACE(*(b)->top, *(b)->top = (state))
243243

244244
#define BUFFER_COPY_CHAR(b, c, _pos, buf, bufsize) \
245245
do { \
246-
if ((b)->pos + (_pos) + 1 > (bufsize)) { \
246+
if ((b)->pos + (_pos) + 1 + 1 > (bufsize)) { \
247247
return JSONB_ERROR_NOMEM; \
248248
} \
249249
(buf)[(b)->pos + (_pos)++] = (c); \
250+
(buf)[(b)->pos + (_pos)] = '\0'; \
250251
} while (0)
251252
#define BUFFER_COPY(b, value, len, _pos, buf, bufsize) \
252253
do { \
253254
size_t i; \
254-
if ((b)->pos + (_pos) + (len) > (bufsize)) { \
255+
if ((b)->pos + (_pos) + (len) + 1 > (bufsize)) { \
255256
return JSONB_ERROR_NOMEM; \
256257
} \
257258
for (i = 0; i < (len); ++i) \
258259
(buf)[(b)->pos + (_pos) + i] = (value)[i]; \
259260
(_pos) += (len); \
261+
(buf)[(b)->pos + (_pos)] = '\0'; \
260262
} while (0)
261263

262264
void
@@ -270,23 +272,22 @@ jsonb_init(jsonb *b)
270272
jsonbcode
271273
jsonb_push_object(jsonb *b, char buf[], size_t bufsize)
272274
{
273-
enum jsonbstate next_state;
275+
enum jsonbstate new_state;
274276
size_t pos = 0;
275-
if (b->top - b->stack >= JSONB_MAX_DEPTH)
276-
return JSONB_ERROR_STACK;
277+
if (b->top - b->stack >= JSONB_MAX_DEPTH) return JSONB_ERROR_STACK;
277278
switch (*b->top) {
278279
case JSONB_ARRAY_NEXT_VALUE_OR_CLOSE:
279280
BUFFER_COPY_CHAR(b, ',', pos, buf, bufsize);
280281
/* fall-through */
281282
case JSONB_OBJECT_VALUE:
282283
case JSONB_ARRAY_VALUE_OR_CLOSE:
283284
if (*b->top <= JSONB_OBJECT_NEXT_KEY_OR_CLOSE)
284-
next_state = JSONB_OBJECT_NEXT_KEY_OR_CLOSE;
285+
new_state = JSONB_OBJECT_NEXT_KEY_OR_CLOSE;
285286
else if (*b->top <= JSONB_ARRAY_NEXT_VALUE_OR_CLOSE)
286-
next_state = JSONB_ARRAY_NEXT_VALUE_OR_CLOSE;
287+
new_state = JSONB_ARRAY_NEXT_VALUE_OR_CLOSE;
287288
break;
288289
case JSONB_ARRAY_OR_OBJECT_OR_VALUE:
289-
next_state = JSONB_DONE;
290+
new_state = JSONB_DONE;
290291
break;
291292
default:
292293
STACK_HEAD(b, JSONB_ERROR);
@@ -296,7 +297,7 @@ jsonb_push_object(jsonb *b, char buf[], size_t bufsize)
296297
return JSONB_ERROR_INPUT;
297298
}
298299
BUFFER_COPY_CHAR(b, '{', pos, buf, bufsize);
299-
STACK_HEAD(b, next_state);
300+
STACK_HEAD(b, new_state);
300301
STACK_PUSH(b, JSONB_OBJECT_KEY_OR_CLOSE);
301302
b->pos += pos;
302303
return JSONB_OK;
@@ -308,16 +309,14 @@ jsonb_pop_object(jsonb *b, char buf[], size_t bufsize)
308309
enum jsonbcode code;
309310
size_t pos = 0;
310311
switch (*b->top) {
311-
case JSONB_DONE:
312-
code = JSONB_END;
313-
break;
314312
case JSONB_OBJECT_KEY_OR_CLOSE:
315313
case JSONB_OBJECT_NEXT_KEY_OR_CLOSE:
316-
code = JSONB_OK;
314+
code = b->top - 1 == b->stack ? JSONB_END : JSONB_OK;
317315
break;
318316
default:
319317
STACK_HEAD(b, JSONB_ERROR);
320318
/* fall-through */
319+
case JSONB_DONE:
321320
case JSONB_ERROR:
322321
return JSONB_ERROR_INPUT;
323322
}
@@ -419,23 +418,22 @@ jsonb_push_key(
419418
jsonbcode
420419
jsonb_push_array(jsonb *b, char buf[], size_t bufsize)
421420
{
422-
enum jsonbstate next_state;
421+
enum jsonbstate new_state;
423422
size_t pos = 0;
424-
if (b->top - b->stack >= JSONB_MAX_DEPTH)
425-
return JSONB_ERROR_STACK;
423+
if (b->top - b->stack >= JSONB_MAX_DEPTH) return JSONB_ERROR_STACK;
426424
switch (*b->top) {
427425
case JSONB_ARRAY_NEXT_VALUE_OR_CLOSE:
428426
BUFFER_COPY_CHAR(b, ',', pos, buf, bufsize);
429427
/* fall-through */
430428
case JSONB_OBJECT_VALUE:
431429
case JSONB_ARRAY_VALUE_OR_CLOSE:
432430
if (*b->top <= JSONB_OBJECT_NEXT_KEY_OR_CLOSE)
433-
next_state = JSONB_OBJECT_NEXT_KEY_OR_CLOSE;
431+
new_state = JSONB_OBJECT_NEXT_KEY_OR_CLOSE;
434432
else if (*b->top <= JSONB_ARRAY_NEXT_VALUE_OR_CLOSE)
435-
next_state = JSONB_ARRAY_NEXT_VALUE_OR_CLOSE;
433+
new_state = JSONB_ARRAY_NEXT_VALUE_OR_CLOSE;
436434
break;
437435
case JSONB_ARRAY_OR_OBJECT_OR_VALUE:
438-
next_state = JSONB_DONE;
436+
new_state = JSONB_DONE;
439437
break;
440438
default:
441439
STACK_HEAD(b, JSONB_ERROR);
@@ -444,7 +442,7 @@ jsonb_push_array(jsonb *b, char buf[], size_t bufsize)
444442
return JSONB_ERROR_INPUT;
445443
}
446444
BUFFER_COPY_CHAR(b, '[', pos, buf, bufsize);
447-
STACK_HEAD(b, next_state);
445+
STACK_HEAD(b, new_state);
448446
STACK_PUSH(b, JSONB_ARRAY_VALUE_OR_CLOSE);
449447
b->pos += pos;
450448
return JSONB_OK;
@@ -456,16 +454,14 @@ jsonb_pop_array(jsonb *b, char buf[], size_t bufsize)
456454
enum jsonbcode code;
457455
size_t pos = 0;
458456
switch (*b->top) {
459-
case JSONB_DONE:
460-
code = JSONB_END;
461-
break;
462457
case JSONB_ARRAY_VALUE_OR_CLOSE:
463458
case JSONB_ARRAY_NEXT_VALUE_OR_CLOSE:
464-
code = JSONB_OK;
459+
code = b->top - 1 == b->stack ? JSONB_END : JSONB_OK;
465460
break;
466461
default:
467462
STACK_HEAD(b, JSONB_ERROR);
468463
/* fall-through */
464+
case JSONB_DONE:
469465
case JSONB_ERROR:
470466
return JSONB_ERROR_INPUT;
471467
}

0 commit comments

Comments
 (0)