Merge pull request #703 from simonduq/fix/json-buffer-overflows
Json library: fix a number of potential buffer overflows
This commit is contained in:
commit
42436cc486
@ -32,34 +32,42 @@
|
|||||||
#include "jsonparse.h"
|
#include "jsonparse.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
static int
|
static bool
|
||||||
push(struct jsonparse_state *state, char c)
|
push(struct jsonparse_state *state, char c)
|
||||||
{
|
{
|
||||||
state->stack[state->depth] = c;
|
if(state->depth < JSONPARSE_MAX_DEPTH) {
|
||||||
state->depth++;
|
state->stack[state->depth] = c;
|
||||||
state->vtype = 0;
|
state->depth++;
|
||||||
return state->depth < JSONPARSE_MAX_DEPTH;
|
state->vtype = 0;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
static void
|
static bool
|
||||||
modify(struct jsonparse_state *state, char c)
|
modify(struct jsonparse_state *state, char c)
|
||||||
{
|
{
|
||||||
if(state->depth > 0) {
|
if(state->depth > 0) {
|
||||||
state->stack[state->depth - 1] = c;
|
state->stack[state->depth - 1] = c;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
static char
|
static bool
|
||||||
pop(struct jsonparse_state *state)
|
pop(struct jsonparse_state *state)
|
||||||
{
|
{
|
||||||
if(state->depth == 0) {
|
if(state->depth == 0) {
|
||||||
return JSON_TYPE_ERROR;
|
return false;
|
||||||
}
|
}
|
||||||
state->depth--;
|
state->depth--;
|
||||||
state->vtype = state->stack[state->depth];
|
state->vtype = state->stack[state->depth];
|
||||||
return state->stack[state->depth];
|
return true;
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
/* will pass by the value and store the start and length of the value for
|
/* will pass by the value and store the start and length of the value for
|
||||||
@ -134,15 +142,11 @@ skip_ws(struct jsonparse_state *state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
static int
|
static bool
|
||||||
is_atomic(struct jsonparse_state *state)
|
is_atomic(struct jsonparse_state *state)
|
||||||
{
|
{
|
||||||
char v = state->vtype;
|
char v = state->vtype;
|
||||||
if(v == 'N' || v == '"' || v == '0' || v == 'n' || v == 't' || v == 'f') {
|
return v == 'N' || v == '"' || v == '0' || v == 'n' || v == 't' || v == 'f';
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
@ -163,6 +167,7 @@ jsonparse_next(struct jsonparse_state *state)
|
|||||||
char c;
|
char c;
|
||||||
char s;
|
char s;
|
||||||
char v;
|
char v;
|
||||||
|
bool ret;
|
||||||
|
|
||||||
skip_ws(state);
|
skip_ws(state);
|
||||||
c = state->json[state->pos];
|
c = state->json[state->pos];
|
||||||
@ -173,48 +178,51 @@ jsonparse_next(struct jsonparse_state *state)
|
|||||||
switch(c) {
|
switch(c) {
|
||||||
case '{':
|
case '{':
|
||||||
if((s == 0 && v == 0) || s == '[' || s == ':') {
|
if((s == 0 && v == 0) || s == '[' || s == ':') {
|
||||||
push(state, c);
|
if(push(state, c)) {
|
||||||
} else {
|
return c;
|
||||||
state->error = JSON_ERROR_UNEXPECTED_OBJECT;
|
}
|
||||||
return JSON_TYPE_ERROR;
|
|
||||||
}
|
}
|
||||||
return c;
|
state->error = JSON_ERROR_UNEXPECTED_OBJECT;
|
||||||
|
return JSON_TYPE_ERROR;
|
||||||
case '}':
|
case '}':
|
||||||
if((s == ':' && v != ',' && v != 0 ) || (s == '{' && v == 0)) {
|
if((s == ':' && v != ',' && v != 0 ) || (s == '{' && v == 0)) {
|
||||||
pop(state);
|
if(pop(state)) {
|
||||||
} else {
|
return c;
|
||||||
state->error = JSON_ERROR_UNEXPECTED_END_OF_OBJECT;
|
}
|
||||||
return JSON_TYPE_ERROR;
|
|
||||||
}
|
}
|
||||||
return c;
|
state->error = JSON_ERROR_UNEXPECTED_END_OF_OBJECT;
|
||||||
|
return JSON_TYPE_ERROR;
|
||||||
case ']':
|
case ']':
|
||||||
if(s == '[' && v != ',') {
|
if(s == '[' && v != ',') {
|
||||||
pop(state);
|
if(pop(state)) {
|
||||||
} else {
|
return c;
|
||||||
state->error = JSON_ERROR_UNEXPECTED_END_OF_ARRAY;
|
}
|
||||||
return JSON_TYPE_ERROR;
|
|
||||||
}
|
}
|
||||||
return c;
|
state->error = JSON_ERROR_UNEXPECTED_END_OF_ARRAY;
|
||||||
|
return JSON_TYPE_ERROR;
|
||||||
case ':':
|
case ':':
|
||||||
if(s == '{' && v == 'N') {
|
if(s == '{' && v == 'N') {
|
||||||
modify(state, ':');
|
ret = modify(state, ':');
|
||||||
state->vtype = 0;
|
state->vtype = 0;
|
||||||
} else {
|
if(ret) {
|
||||||
state->error = JSON_ERROR_SYNTAX;
|
return jsonparse_next(state);
|
||||||
return JSON_TYPE_ERROR;
|
}
|
||||||
}
|
}
|
||||||
return jsonparse_next(state);
|
state->error = JSON_ERROR_SYNTAX;
|
||||||
|
return JSON_TYPE_ERROR;
|
||||||
case ',':
|
case ',':
|
||||||
if(s == ':' && v != 0) {
|
if(s == ':' && v != 0) {
|
||||||
modify(state, '{');
|
ret = modify(state, '{');
|
||||||
state->vtype = c;
|
state->vtype = c;
|
||||||
|
if(ret) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
} else if(s == '[') {
|
} else if(s == '[') {
|
||||||
state->vtype = c;
|
state->vtype = c;
|
||||||
} else {
|
return c;
|
||||||
state->error = JSON_ERROR_SYNTAX;
|
|
||||||
return JSON_TYPE_ERROR;
|
|
||||||
}
|
}
|
||||||
return c;
|
state->error = JSON_ERROR_SYNTAX;
|
||||||
|
return JSON_TYPE_ERROR;
|
||||||
case '"':
|
case '"':
|
||||||
if((s == 0 && v == 0) || s == '{' || s == '[' || s == ':') {
|
if((s == 0 && v == 0) || s == '{' || s == '[' || s == ':') {
|
||||||
return atomic(state, c = (s == '{' ? JSON_TYPE_PAIR_NAME : c));
|
return atomic(state, c = (s == '{' ? JSON_TYPE_PAIR_NAME : c));
|
||||||
@ -225,12 +233,12 @@ jsonparse_next(struct jsonparse_state *state)
|
|||||||
return c;
|
return c;
|
||||||
case '[':
|
case '[':
|
||||||
if((s == 0 && v == 0) || s == '[' || s == ':') {
|
if((s == 0 && v == 0) || s == '[' || s == ':') {
|
||||||
push(state, c);
|
if(push(state, c)) {
|
||||||
} else {
|
return c;
|
||||||
state->error = JSON_ERROR_UNEXPECTED_ARRAY;
|
}
|
||||||
return JSON_TYPE_ERROR;
|
|
||||||
}
|
}
|
||||||
return c;
|
state->error = JSON_ERROR_UNEXPECTED_ARRAY;
|
||||||
|
return JSON_TYPE_ERROR;
|
||||||
case 0:
|
case 0:
|
||||||
if(v == 0 || state->depth > 0) {
|
if(v == 0 || state->depth > 0) {
|
||||||
state->error = JSON_ERROR_SYNTAX;
|
state->error = JSON_ERROR_SYNTAX;
|
||||||
|
@ -198,7 +198,10 @@ jsontree_print_next(struct jsontree_context *js_ctx)
|
|||||||
} else {
|
} else {
|
||||||
ov = o->values[index];
|
ov = o->values[index];
|
||||||
}
|
}
|
||||||
/* TODO check max depth */
|
if(js_ctx->depth >= JSONTREE_MAX_DEPTH - 1) {
|
||||||
|
/* Too deep: return 0 */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
js_ctx->depth++; /* step down to value... */
|
js_ctx->depth++; /* step down to value... */
|
||||||
js_ctx->index[js_ctx->depth] = 0; /* and init index */
|
js_ctx->index[js_ctx->depth] = 0; /* and init index */
|
||||||
js_ctx->values[js_ctx->depth] = ov;
|
js_ctx->values[js_ctx->depth] = ov;
|
||||||
@ -299,7 +302,10 @@ find_next(struct jsontree_context *js_ctx)
|
|||||||
} else {
|
} else {
|
||||||
ov = o->values[index];
|
ov = o->values[index];
|
||||||
}
|
}
|
||||||
/* TODO check max depth */
|
if(js_ctx->depth >= JSONTREE_MAX_DEPTH - 1) {
|
||||||
|
/* Too deep: return NULL */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
js_ctx->depth++; /* step down to value... */
|
js_ctx->depth++; /* step down to value... */
|
||||||
js_ctx->index[js_ctx->depth] = 0; /* and init index */
|
js_ctx->index[js_ctx->depth] = 0; /* and init index */
|
||||||
js_ctx->values[js_ctx->depth] = ov;
|
js_ctx->values[js_ctx->depth] = ov;
|
||||||
|
Loading…
Reference in New Issue
Block a user