1
0
mirror of https://github.com/janet-lang/janet synced 2024-09-27 14:48:13 +00:00

Fix some very mild memory leaks in line.c and the do_bytes function (not

deiniting the parser).
This commit is contained in:
Calvin Rose 2018-05-15 22:03:45 -04:00
parent c6f79eca6d
commit 6ac59251e9
4 changed files with 106 additions and 63 deletions

View File

@ -31,9 +31,10 @@ int dst_dobytes(DstTable *env, const uint8_t *bytes, int32_t len) {
int errflags = 0; int errflags = 0;
int32_t index = 0; int32_t index = 0;
int dudeol = 0; int dudeol = 0;
int done = 0;
dst_parser_init(&parser, DST_PARSEFLAG_SOURCEMAP); dst_parser_init(&parser, DST_PARSEFLAG_SOURCEMAP);
for (;;) { while (!errflags && !done) {
switch (dst_parser_status(&parser)) { switch (dst_parser_status(&parser)) {
case DST_PARSE_FULL: case DST_PARSE_FULL:
{ {
@ -62,7 +63,6 @@ int dst_dobytes(DstTable *env, const uint8_t *bytes, int32_t len) {
if (dudeol) { if (dudeol) {
errflags |= 0x04; errflags |= 0x04;
printf("internal parse error: unexpected end of source\n"); printf("internal parse error: unexpected end of source\n");
return errflags;
} else { } else {
dudeol = 1; dudeol = 1;
dst_parser_consume(&parser, '\n'); dst_parser_consume(&parser, '\n');
@ -72,11 +72,16 @@ int dst_dobytes(DstTable *env, const uint8_t *bytes, int32_t len) {
} }
break; break;
case DST_PARSE_ROOT: case DST_PARSE_ROOT:
if (index >= len) return errflags; if (index >= len) {
dst_parser_consume(&parser, bytes[index++]); done = 1;
} else {
dst_parser_consume(&parser, bytes[index++]);
}
break; break;
} }
} }
dst_parser_deinit(&parser);
return errflags;
} }
int dst_dostring(DstTable *env, const char *str) { int dst_dostring(DstTable *env, const char *str) {

View File

@ -46,9 +46,15 @@ enum DstParserStatus {
}; };
struct DstParser { struct DstParser {
Dst* argstack; Dst* args;
size_t argcount;
size_t argcap;
DstParseState *states; DstParseState *states;
size_t statecount;
size_t statecap;
uint8_t *buf; uint8_t *buf;
size_t bufcount;
size_t bufcap;
const char *error; const char *error;
size_t index; size_t index;
int lookback; int lookback;

View File

@ -265,6 +265,8 @@ static void addhistory() {
if (len < DST_HISTORY_MAX) { if (len < DST_HISTORY_MAX) {
dst_v_push(history, newline); dst_v_push(history, newline);
len++; len++;
} else {
free(history[DST_HISTORY_MAX - 1]);
} }
for (i = len - 1; i > 0; i--) { for (i = len - 1; i > 0; i--) {
history[i] = history[i - 1]; history[i] = history[i - 1];
@ -275,6 +277,7 @@ static void addhistory() {
static void replacehistory() { static void replacehistory() {
char *newline = sdup(buf); char *newline = sdup(buf);
if (!newline) return; if (!newline) return;
free(history[0]);
history[0] = newline; history[0] = newline;
} }

View File

@ -22,7 +22,6 @@
#include <dst/dst.h> #include <dst/dst.h>
#include <dst/dstparse.h> #include <dst/dstparse.h>
#include <headerlibs/vector.h>
/* Quote a value */ /* Quote a value */
static Dst quote(Dst x) { static Dst quote(Dst x) {
@ -118,6 +117,31 @@ struct DstParseState {
Consumer consumer; Consumer consumer;
}; };
/* Define a stack on the main parser struct */
#define DEF_PARSER_STACK(NAME, T, STACK, STACKCOUNT, STACKCAP) \
static void NAME(DstParser *p, T x) { \
size_t oldcount = p->STACKCOUNT; \
size_t newcount = oldcount + 1; \
if (newcount > p->STACKCAP) { \
T *next; \
size_t newcap = 2 * newcount; \
next = realloc(p->STACK, sizeof(T) * newcap); \
if (NULL == next) { \
DST_OUT_OF_MEMORY; \
} \
p->STACK = next; \
p->STACKCAP = newcap; \
} \
p->STACK[oldcount] = x; \
p->STACKCOUNT = newcount; \
}
DEF_PARSER_STACK(push_buf, uint8_t, buf, bufcount, bufcap)
DEF_PARSER_STACK(push_arg, Dst, args, argcount, argcap)
DEF_PARSER_STACK(_pushstate, DstParseState, states, statecount, statecap)
#undef DEF_PARSER_STACK
#define PFLAG_CONTAINER 1 #define PFLAG_CONTAINER 1
#define PFLAG_BUFFER 2 #define PFLAG_BUFFER 2
#define PFLAG_PARENS 4 #define PFLAG_PARENS 4
@ -133,14 +157,12 @@ static void pushstate(DstParser *p, Consumer consumer, int flags) {
s.flags = flags; s.flags = flags;
s.consumer = consumer; s.consumer = consumer;
s.start = p->index; s.start = p->index;
dst_v_push(p->states, s); _pushstate(p, s);
} }
static void popstate(DstParser *p, Dst val) { static void popstate(DstParser *p, Dst val) {
DstParseState top = dst_v_last(p->states); DstParseState top = p->states[--p->statecount];
DstParseState *newtop; DstParseState *newtop = p->states + p->statecount - 1;
dst_v_pop(p->states);
newtop = &dst_v_last(p->states);
if (newtop->flags & PFLAG_CONTAINER) { if (newtop->flags & PFLAG_CONTAINER) {
int32_t i, len; int32_t i, len;
len = newtop->qcount; len = newtop->qcount;
@ -157,7 +179,7 @@ static void popstate(DstParser *p, Dst val) {
val = dst_ast_wrap(val, (int32_t) top.start, (int32_t) p->index); val = dst_ast_wrap(val, (int32_t) top.start, (int32_t) p->index);
newtop->argn++; newtop->argn++;
dst_v_push(p->argstack, val); push_arg(p, val);
} }
} }
@ -189,7 +211,7 @@ static int escapeh(DstParser *p, DstParseState *state, uint8_t c) {
state->argn = (state->argn << 4) + digit;; state->argn = (state->argn << 4) + digit;;
state->qcount--; state->qcount--;
if (!state->qcount) { if (!state->qcount) {
dst_v_push(p->buf, (state->argn & 0xFF)); push_buf(p, (state->argn & 0xFF));
state->argn = 0; state->argn = 0;
state->consumer = stringchar; state->consumer = stringchar;
} }
@ -207,7 +229,7 @@ static int escape1(DstParser *p, DstParseState *state, uint8_t c) {
state->argn = 0; state->argn = 0;
state->consumer = escapeh; state->consumer = escapeh;
} else { } else {
dst_v_push(p->buf, e); push_buf(p, e);
state->consumer = stringchar; state->consumer = stringchar;
} }
return 1; return 1;
@ -216,13 +238,13 @@ static int escape1(DstParser *p, DstParseState *state, uint8_t c) {
static int stringend(DstParser *p, DstParseState *state) { static int stringend(DstParser *p, DstParseState *state) {
Dst ret; Dst ret;
if (state->flags & PFLAG_BUFFER) { if (state->flags & PFLAG_BUFFER) {
DstBuffer *b = dst_buffer(dst_v_count(p->buf)); DstBuffer *b = dst_buffer(p->bufcount);
dst_buffer_push_bytes(b, p->buf, dst_v_count(p->buf)); dst_buffer_push_bytes(b, p->buf, p->bufcount);
ret = dst_wrap_buffer(b); ret = dst_wrap_buffer(b);
} else { } else {
ret = dst_wrap_string(dst_string(p->buf, dst_v_count(p->buf))); ret = dst_wrap_string(dst_string(p->buf, p->bufcount));
} }
dst_v_empty(p->buf); p->bufcount = 0;
popstate(p, ret); popstate(p, ret);
return 1; return 1;
} }
@ -238,7 +260,7 @@ static int stringchar(DstParser *p, DstParseState *state, uint8_t c) {
return stringend(p, state); return stringend(p, state);
} }
/* normal char */ /* normal char */
dst_v_push(p->buf, c); push_buf(p, c);
return 1; return 1;
} }
@ -259,12 +281,12 @@ static int tokenchar(DstParser *p, DstParseState *state, uint8_t c) {
Dst numcheck, ret; Dst numcheck, ret;
int32_t blen; int32_t blen;
if (is_symbol_char(c)) { if (is_symbol_char(c)) {
dst_v_push(p->buf, (uint8_t) c); push_buf(p, (uint8_t) c);
if (c > 127) state->argn = 1; /* Use to indicate non ascii */ if (c > 127) state->argn = 1; /* Use to indicate non ascii */
return 1; return 1;
} }
/* Token finished */ /* Token finished */
blen = dst_v_count(p->buf); blen = p->bufcount;
numcheck = dst_scan_number(p->buf, blen); numcheck = dst_scan_number(p->buf, blen);
if (!dst_checktype(numcheck, DST_NIL)) { if (!dst_checktype(numcheck, DST_NIL)) {
ret = numcheck; ret = numcheck;
@ -291,14 +313,14 @@ static int tokenchar(DstParser *p, DstParseState *state, uint8_t c) {
p->error = "empty symbol invalid"; p->error = "empty symbol invalid";
return 0; return 0;
} }
dst_v_empty(p->buf); p->bufcount = 0;
popstate(p, ret); popstate(p, ret);
return 0; return 0;
} }
static int comment(DstParser *p, DstParseState *state, uint8_t c) { static int comment(DstParser *p, DstParseState *state, uint8_t c) {
(void) state; (void) state;
if (c == '\n') dst_v_pop(p->states); if (c == '\n') p->statecount--;
return 1; return 1;
} }
@ -312,7 +334,7 @@ static int dotuple(DstParser *p, DstParseState *state, uint8_t c) {
int32_t i; int32_t i;
Dst *ret = dst_tuple_begin(state->argn); Dst *ret = dst_tuple_begin(state->argn);
for (i = state->argn - 1; i >= 0; i--) { for (i = state->argn - 1; i >= 0; i--) {
ret[i] = dst_v_last(p->argstack); dst_v_pop(p->argstack); ret[i] = p->args[--p->argcount];
} }
popstate(p, dst_wrap_tuple(dst_tuple_end(ret))); popstate(p, dst_wrap_tuple(dst_tuple_end(ret)));
return 1; return 1;
@ -327,7 +349,7 @@ static int doarray(DstParser *p, DstParseState *state, uint8_t c) {
int32_t i; int32_t i;
DstArray *array = dst_array(state->argn); DstArray *array = dst_array(state->argn);
for (i = state->argn - 1; i >= 0; i--) { for (i = state->argn - 1; i >= 0; i--) {
array->data[i] = dst_v_last(p->argstack); dst_v_pop(p->argstack); array->data[i] = p->args[--p->argcount];
} }
array->count = state->argn; array->count = state->argn;
popstate(p, dst_wrap_array(array)); popstate(p, dst_wrap_array(array));
@ -346,8 +368,8 @@ static int dostruct(DstParser *p, DstParseState *state, uint8_t c) {
} }
st = dst_struct_begin(state->argn >> 1); st = dst_struct_begin(state->argn >> 1);
for (i = state->argn; i > 0; i -= 2) { for (i = state->argn; i > 0; i -= 2) {
Dst value = dst_v_last(p->argstack); dst_v_pop(p->argstack); Dst value = p->args[--p->argcount];
Dst key = dst_v_last(p->argstack); dst_v_pop(p->argstack); Dst key = p->args[--p->argcount];
dst_struct_put(st, key, value); dst_struct_put(st, key, value);
} }
popstate(p, dst_wrap_struct(dst_struct_end(st))); popstate(p, dst_wrap_struct(dst_struct_end(st)));
@ -366,8 +388,8 @@ static int dotable(DstParser *p, DstParseState *state, uint8_t c) {
} }
table = dst_table(state->argn >> 1); table = dst_table(state->argn >> 1);
for (i = state->argn; i > 0; i -= 2) { for (i = state->argn; i > 0; i -= 2) {
Dst value = dst_v_last(p->argstack); dst_v_pop(p->argstack); Dst value = p->args[--p->argcount];
Dst key = dst_v_last(p->argstack); dst_v_pop(p->argstack); Dst key = p->args[--p->argcount];
dst_table_put(table, key, value); dst_table_put(table, key, value);
} }
popstate(p, dst_wrap_table(table)); popstate(p, dst_wrap_table(table));
@ -387,7 +409,7 @@ static int longstring(DstParser *p, DstParseState *state, uint8_t c) {
state->qcount = 1; /* Use qcount to keep track of number of '=' seen */ state->qcount = 1; /* Use qcount to keep track of number of '=' seen */
return 1; return 1;
} }
dst_v_push(p->buf, c); push_buf(p, c);
return 1; return 1;
} else if (state->flags & PFLAG_END_CANDIDATE) { } else if (state->flags & PFLAG_END_CANDIDATE) {
int i; int i;
@ -402,9 +424,9 @@ static int longstring(DstParser *p, DstParseState *state, uint8_t c) {
} }
/* Failed end candidate */ /* Failed end candidate */
for (i = 0; i < state->qcount; i++) { for (i = 0; i < state->qcount; i++) {
dst_v_push(p->buf, '`'); push_buf(p, '`');
} }
dst_v_push(p->buf, c); push_buf(p, c);
state->qcount = 0; state->qcount = 0;
state->flags &= ~PFLAG_END_CANDIDATE; state->flags &= ~PFLAG_END_CANDIDATE;
state->flags |= PFLAG_INSTRING; state->flags |= PFLAG_INSTRING;
@ -414,7 +436,7 @@ static int longstring(DstParser *p, DstParseState *state, uint8_t c) {
state->argn++; state->argn++;
if (c != '`') { if (c != '`') {
state->flags |= PFLAG_INSTRING; state->flags |= PFLAG_INSTRING;
dst_v_push(p->buf, c); push_buf(p, c);
} }
return 1; return 1;
} }
@ -422,7 +444,7 @@ static int longstring(DstParser *p, DstParseState *state, uint8_t c) {
static int ampersand(DstParser *p, DstParseState *state, uint8_t c) { static int ampersand(DstParser *p, DstParseState *state, uint8_t c) {
(void) state; (void) state;
dst_v_pop(p->states); p->statecount--;
switch (c) { switch (c) {
case '{': case '{':
pushstate(p, dotable, PFLAG_CONTAINER | PFLAG_CURLYBRACKETS); pushstate(p, dotable, PFLAG_CONTAINER | PFLAG_CURLYBRACKETS);
@ -443,7 +465,7 @@ static int ampersand(DstParser *p, DstParseState *state, uint8_t c) {
break; break;
} }
pushstate(p, tokenchar, 0); pushstate(p, tokenchar, 0);
dst_v_push(p->buf, '@'); /* Push the leading ampersand that was dropped */ push_buf(p, '@'); /* Push the leading ampersand that was dropped */
return 0; return 0;
} }
@ -495,7 +517,7 @@ int dst_parser_consume(DstParser *parser, uint8_t c) {
if (parser->error) return 0; if (parser->error) return 0;
parser->index++; parser->index++;
while (!consumed && !parser->error) { while (!consumed && !parser->error) {
DstParseState *state = &dst_v_last(parser->states); DstParseState *state = parser->states + parser->statecount - 1;
consumed = state->consumer(parser, state, c); consumed = state->consumer(parser, state, c);
} }
parser->lookback = c; parser->lookback = c;
@ -504,15 +526,15 @@ int dst_parser_consume(DstParser *parser, uint8_t c) {
enum DstParserStatus dst_parser_status(DstParser *parser) { enum DstParserStatus dst_parser_status(DstParser *parser) {
if (parser->error) return DST_PARSE_ERROR; if (parser->error) return DST_PARSE_ERROR;
if (dst_v_count(parser->states) > 1) return DST_PARSE_PENDING; if (parser->statecount > 1) return DST_PARSE_PENDING;
if (dst_v_count(parser->argstack)) return DST_PARSE_FULL; if (parser->argcount) return DST_PARSE_FULL;
return DST_PARSE_ROOT; return DST_PARSE_ROOT;
} }
void dst_parser_flush(DstParser *parser) { void dst_parser_flush(DstParser *parser) {
dst_v_empty(parser->argstack); parser->argcount = 0;
dst_v__cnt(parser->states) = 1; parser->statecount = 1;
dst_v_empty(parser->buf); parser->bufcount = 0;
} }
const char *dst_parser_error(DstParser *parser) { const char *dst_parser_error(DstParser *parser) {
@ -528,21 +550,27 @@ const char *dst_parser_error(DstParser *parser) {
Dst dst_parser_produce(DstParser *parser) { Dst dst_parser_produce(DstParser *parser) {
Dst ret; Dst ret;
int32_t i; size_t i;
enum DstParserStatus status = dst_parser_status(parser); enum DstParserStatus status = dst_parser_status(parser);
if (status != DST_PARSE_FULL) return dst_wrap_nil(); if (status != DST_PARSE_FULL) return dst_wrap_nil();
ret = parser->argstack[0]; ret = parser->args[0];
for (i = 1; i < dst_v_count(parser->argstack); i++) { for (i = 1; i < parser->argcount; i++) {
parser->argstack[i - 1] = parser->argstack[i]; parser->args[i - 1] = parser->args[i];
} }
dst_v__cnt(parser->argstack)--; parser->argcount--;
return ret; return ret;
} }
void dst_parser_init(DstParser *parser, int flags) { void dst_parser_init(DstParser *parser, int flags) {
parser->argstack = NULL; parser->args = NULL;
parser->states = NULL; parser->states = NULL;
parser->buf = NULL; parser->buf = NULL;
parser->argcount = 0;
parser->argcap = 0;
parser->bufcount = 0;
parser->bufcap = 0;
parser->statecount = 0;
parser->statecap = 0;
parser->error = NULL; parser->error = NULL;
parser->index = 0; parser->index = 0;
parser->lookback = -1; parser->lookback = -1;
@ -551,19 +579,19 @@ void dst_parser_init(DstParser *parser, int flags) {
} }
void dst_parser_deinit(DstParser *parser) { void dst_parser_deinit(DstParser *parser) {
dst_v_free(parser->argstack); free(parser->args);
dst_v_free(parser->buf); free(parser->buf);
dst_v_free(parser->states); free(parser->states);
} }
/* C functions */ /* C functions */
static int parsermark(void *p, size_t size) { static int parsermark(void *p, size_t size) {
int32_t i; size_t i;
DstParser *parser = (DstParser *)p; DstParser *parser = (DstParser *)p;
(void) size; (void) size;
for (i = 0; i < dst_v_count(parser->argstack); i++) { for (i = 0; i < parser->argcount; i++) {
dst_mark(parser->argstack[i]); dst_mark(parser->args[i]);
} }
return 0; return 0;
} }
@ -687,32 +715,33 @@ static int cfun_flush(DstArgs args) {
} }
static int cfun_state(DstArgs args) { static int cfun_state(DstArgs args) {
int32_t i; size_t i;
uint8_t *buf = NULL;
const uint8_t *str; const uint8_t *str;
size_t oldcount;
DstParser *p; DstParser *p;
DST_FIXARITY(args, 1); DST_FIXARITY(args, 1);
DST_CHECKABSTRACT(args, 0, &dst_parse_parsertype); DST_CHECKABSTRACT(args, 0, &dst_parse_parsertype);
p = (DstParser *) dst_unwrap_abstract(args.v[0]); p = (DstParser *) dst_unwrap_abstract(args.v[0]);
for (i = 0; i < dst_v_count(p->states); i++) { oldcount = p->bufcount;
for (i = 0; i < p->statecount; i++) {
DstParseState *s = p->states + i; DstParseState *s = p->states + i;
if (s->flags & PFLAG_PARENS) { if (s->flags & PFLAG_PARENS) {
dst_v_push(buf, '('); push_buf(p, '(');
} else if (s->flags & PFLAG_SQRBRACKETS) { } else if (s->flags & PFLAG_SQRBRACKETS) {
dst_v_push(buf, '['); push_buf(p, '[');
} else if (s->flags & PFLAG_CURLYBRACKETS) { } else if (s->flags & PFLAG_CURLYBRACKETS) {
dst_v_push(buf, '{'); push_buf(p, '{');
} else if (s->flags & PFLAG_STRING) { } else if (s->flags & PFLAG_STRING) {
dst_v_push(buf, '"'); push_buf(p, '"');
} else if (s->flags & PFLAG_LONGSTRING) { } else if (s->flags & PFLAG_LONGSTRING) {
int32_t i; int32_t i;
for (i = 0; i < s->argn; i++) { for (i = 0; i < s->argn; i++) {
dst_v_push(buf, '`'); push_buf(p, '`');
} }
} }
} }
str = dst_string(buf, dst_v_count(buf)); str = dst_string(p->buf + oldcount, p->bufcount - oldcount);
dst_v_free(buf); p->bufcount = oldcount;
DST_RETURN_STRING(args, str); DST_RETURN_STRING(args, str);
} }