multiple bug fixes
This commit is contained in:
+35
-16
@@ -7,6 +7,9 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "xjson.h"
|
#include "xjson.h"
|
||||||
|
|
||||||
|
#define XJ_MAX_DEPTH 128
|
||||||
|
#define XJ_MAX_EXPNT 10
|
||||||
|
|
||||||
typedef struct chunk_t chunk_t;
|
typedef struct chunk_t chunk_t;
|
||||||
|
|
||||||
/* Symbol:
|
/* Symbol:
|
||||||
@@ -568,7 +571,7 @@ char *xj_strdup(const char *str, int len, xj_alloc *alloc, xj_error *error)
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *str;
|
const char *str;
|
||||||
int i, len;
|
int i, len, depth;
|
||||||
xj_alloc *alloc;
|
xj_alloc *alloc;
|
||||||
xj_error *error;
|
xj_error *error;
|
||||||
} context_t;
|
} context_t;
|
||||||
@@ -916,15 +919,17 @@ static void *parse_string(context_t *ctx, _Bool raw)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char c = ctx->str[ctx->i];
|
uint32_t rune;
|
||||||
|
int rune_byte_count = xutf8_sequence_to_utf32_codepoint(ctx->str + ctx->i, ctx->len - ctx->i, &rune);
|
||||||
|
|
||||||
ctx->i += 1; // Skip the character after the '\'.
|
if(rune == 'u')
|
||||||
|
|
||||||
if(c == 'u')
|
|
||||||
{
|
{
|
||||||
int start = ctx->i-2;
|
int start = ctx->i-1; // Points to the '\'.
|
||||||
assert(start >= 0);
|
assert(start >= 0);
|
||||||
|
|
||||||
|
assert(rune_byte_count == 1);
|
||||||
|
ctx->i += 1; // Skip the 'u'.
|
||||||
|
|
||||||
uint16_t first_half;
|
uint16_t first_half;
|
||||||
if(!parse_XXXX_after_u(ctx, &first_half))
|
if(!parse_XXXX_after_u(ctx, &first_half))
|
||||||
{
|
{
|
||||||
@@ -1024,22 +1029,29 @@ static void *parse_string(context_t *ctx, _Bool raw)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch(c)
|
const char *s; int l;
|
||||||
|
switch(rune)
|
||||||
{
|
{
|
||||||
case 'n': c = '\n'; break;
|
case 'n': s = "\n"; l = 1; break;
|
||||||
case 't': c = '\t'; break;
|
case 't': s = "\t"; l = 1; break;
|
||||||
case 'b': c = '\b'; break;
|
case 'b': s = "\b"; l = 1; break;
|
||||||
case 'f': c = '\f'; break;
|
case 'f': s = "\f"; l = 1; break;
|
||||||
case 'r': c = '\r'; break;
|
case 'r': s = "\r"; l = 1; break;
|
||||||
|
default:
|
||||||
|
s = ctx->str + ctx->i;
|
||||||
|
l = rune_byte_count;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!spc_append(&spc, &c, 1))
|
ctx->i += rune_byte_count;
|
||||||
|
|
||||||
|
if(!spc_append(&spc, s, l))
|
||||||
{
|
{
|
||||||
xj_report(ctx->error, "Out of memory");
|
xj_report(ctx->error, "Out of memory");
|
||||||
spc_free(&spc);
|
spc_free(&spc);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1182,7 +1194,7 @@ static xj_value *parse_number(context_t *ctx)
|
|||||||
ctx->i += 1;
|
ctx->i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(exponent > 6)
|
if(exponent > XJ_MAX_EXPNT)
|
||||||
{
|
{
|
||||||
xj_preport(ctx->error, ctx->str, exponent_start, "Exponent is too big");
|
xj_preport(ctx->error, ctx->str, exponent_start, "Exponent is too big");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1416,6 +1428,13 @@ static xj_value *parse_value(context_t *ctx)
|
|||||||
xj_report(ctx->error, "String ended where a value was expected");
|
xj_report(ctx->error, "String ended where a value was expected");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->depth += 1;
|
||||||
|
if(ctx->depth == XJ_MAX_DEPTH)
|
||||||
|
{
|
||||||
|
xj_preport(ctx->error, ctx->str, ctx->i, "Maximum depth reached");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
assert(!isspace(ctx->str[ctx->i]));
|
assert(!isspace(ctx->str[ctx->i]));
|
||||||
|
|
||||||
@@ -1547,7 +1566,7 @@ xj_value *xj_decode(const char *str, int len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
context_t ctx = {
|
context_t ctx = {
|
||||||
.str = str, .i = i, .len = len,
|
.str = str, .i = i, .len = len, .depth = 0,
|
||||||
.alloc = alloc, .error = error };
|
.alloc = alloc, .error = error };
|
||||||
return parse_value(&ctx);
|
return parse_value(&ctx);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -45,10 +45,10 @@ typedef struct xj_alloc xj_alloc;
|
|||||||
xj_alloc *xj_alloc_using(void *mem, int size, int ext, void (*free)(void*));
|
xj_alloc *xj_alloc_using(void *mem, int size, int ext, void (*free)(void*));
|
||||||
xj_alloc *xj_alloc_new(int size, int ext);
|
xj_alloc *xj_alloc_new(int size, int ext);
|
||||||
void xj_alloc_del(xj_alloc *alloc);
|
void xj_alloc_del(xj_alloc *alloc);
|
||||||
void *xj_bpalloc(xj_alloc *alloc, int size);
|
|
||||||
|
|
||||||
void xj_preport(xj_error *error, const char *src, int off, const char *fmt, ...);
|
void *xj_bpalloc(xj_alloc *alloc, int size);
|
||||||
#define xj_report(error, fmt, ...) xj_preport(error, NULL, -1, fmt, ## __VA_ARGS__)
|
void xj_preport(xj_error *error, const char *src, int off, const char *fmt, ...);
|
||||||
|
#define xj_report(error, fmt, ...) xj_preport(error, NULL, -1, fmt, ## __VA_ARGS__)
|
||||||
|
|
||||||
xj_value *xj_value_null(xj_alloc *alloc, xj_error *error);
|
xj_value *xj_value_null(xj_alloc *alloc, xj_error *error);
|
||||||
xj_value *xj_value_bool(xj_bool val, xj_alloc *alloc, xj_error *error);
|
xj_value *xj_value_bool(xj_bool val, xj_alloc *alloc, xj_error *error);
|
||||||
|
|||||||
Reference in New Issue
Block a user