1
0
mirror of https://github.com/janet-lang/janet synced 2025-02-10 13:50:02 +00:00

Allocate parser with GC.

This fixes janet_dobytes, which manually allocated a parser on the
stack, and then possibly ran garbage collection before it was
deallocated.
This commit is contained in:
Calvin Rose 2025-01-22 09:21:56 -06:00
parent 06d581dde3
commit 49f151e265

View File

@ -28,7 +28,7 @@
/* Run a string */ /* Run a string */
int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath, Janet *out) { int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath, Janet *out) {
JanetParser parser; JanetParser *parser;
int errflags = 0, done = 0; int errflags = 0, done = 0;
int32_t index = 0; int32_t index = 0;
Janet ret = janet_wrap_nil(); Janet ret = janet_wrap_nil();
@ -37,14 +37,16 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char
if (where) janet_gcroot(janet_wrap_string(where)); if (where) janet_gcroot(janet_wrap_string(where));
if (NULL == sourcePath) sourcePath = "<unknown>"; if (NULL == sourcePath) sourcePath = "<unknown>";
janet_parser_init(&parser); parser = janet_abstract(&janet_parser_type, sizeof(JanetParser));
janet_parser_init(parser);
janet_gcroot(janet_wrap_abstract(parser));
/* While we haven't seen an error */ /* While we haven't seen an error */
while (!done) { while (!done) {
/* Evaluate parsed values */ /* Evaluate parsed values */
while (janet_parser_has_more(&parser)) { while (janet_parser_has_more(parser)) {
Janet form = janet_parser_produce(&parser); Janet form = janet_parser_produce(parser);
JanetCompileResult cres = janet_compile(form, env, where); JanetCompileResult cres = janet_compile(form, env, where);
if (cres.status == JANET_COMPILE_OK) { if (cres.status == JANET_COMPILE_OK) {
JanetFunction *f = janet_thunk(cres.funcdef); JanetFunction *f = janet_thunk(cres.funcdef);
@ -58,8 +60,8 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char
} }
} else { } else {
ret = janet_wrap_string(cres.error); ret = janet_wrap_string(cres.error);
int32_t line = (int32_t) parser.line; int32_t line = (int32_t) parser->line;
int32_t col = (int32_t) parser.column; int32_t col = (int32_t) parser->column;
if ((cres.error_mapping.line > 0) && if ((cres.error_mapping.line > 0) &&
(cres.error_mapping.column > 0)) { (cres.error_mapping.column > 0)) {
line = cres.error_mapping.line; line = cres.error_mapping.line;
@ -81,16 +83,16 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char
if (done) break; if (done) break;
/* Dispatch based on parse state */ /* Dispatch based on parse state */
switch (janet_parser_status(&parser)) { switch (janet_parser_status(parser)) {
case JANET_PARSE_DEAD: case JANET_PARSE_DEAD:
done = 1; done = 1;
break; break;
case JANET_PARSE_ERROR: { case JANET_PARSE_ERROR: {
const char *e = janet_parser_error(&parser); const char *e = janet_parser_error(parser);
errflags |= 0x04; errflags |= 0x04;
ret = janet_cstringv(e); ret = janet_cstringv(e);
int32_t line = (int32_t) parser.line; int32_t line = (int32_t) parser->line;
int32_t col = (int32_t) parser.column; int32_t col = (int32_t) parser->column;
janet_eprintf("%s:%d:%d: parse error: %s\n", sourcePath, line, col, e); janet_eprintf("%s:%d:%d: parse error: %s\n", sourcePath, line, col, e);
done = 1; done = 1;
break; break;
@ -98,9 +100,9 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char
case JANET_PARSE_ROOT: case JANET_PARSE_ROOT:
case JANET_PARSE_PENDING: case JANET_PARSE_PENDING:
if (index >= len) { if (index >= len) {
janet_parser_eof(&parser); janet_parser_eof(parser);
} else { } else {
janet_parser_consume(&parser, bytes[index++]); janet_parser_consume(parser, bytes[index++]);
} }
break; break;
} }
@ -108,7 +110,7 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char
} }
/* Clean up and return errors */ /* Clean up and return errors */
janet_parser_deinit(&parser); janet_gcunroot(janet_wrap_abstract(parser));
if (where) janet_gcunroot(janet_wrap_string(where)); if (where) janet_gcunroot(janet_wrap_string(where));
#ifdef JANET_EV #ifdef JANET_EV
/* Enter the event loop if we are not already in it */ /* Enter the event loop if we are not already in it */