Skip to content

Commit d1492fc

Browse files
cmark_parser: improve lifecycle management.
This slightly breaks API as finish will now return NULL after it has been called once, but I believe that's for the best. This fixes potential leaks of root when a parser was fed but not finished, and makes reusing a parser instance multiple times possible.
1 parent 1c22565 commit d1492fc

File tree

1 file changed

+53
-20
lines changed

1 file changed

+53
-20
lines changed

src/blocks.c

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,35 @@ int cmark_parser_attach_syntax_extension(cmark_parser *parser,
7979
return 1;
8080
}
8181

82-
cmark_parser *cmark_parser_new(int options) {
83-
cmark_parser *parser = (cmark_parser *)malloc(sizeof(cmark_parser));
82+
static void cmark_parser_dispose(cmark_parser *parser) {
83+
if (parser->root)
84+
cmark_node_free(parser->root);
85+
86+
if (parser->curline) {
87+
cmark_strbuf_free(parser->curline);
88+
free(parser->curline);
89+
}
90+
91+
if (parser->linebuf) {
92+
cmark_strbuf_free(parser->linebuf);
93+
free(parser->linebuf);
94+
}
95+
96+
if (parser->refmap)
97+
cmark_reference_map_free(parser->refmap);
98+
}
99+
100+
static void cmark_parser_reset(cmark_parser *parser) {
101+
cmark_llist *saved_exts = parser->syntax_extensions;
102+
cmark_llist *saved_inline_exts = parser->inline_syntax_extensions;
103+
int saved_options = parser->options;
104+
105+
cmark_parser_dispose(parser);
106+
107+
memset(parser, 0, sizeof(cmark_parser));
108+
84109
cmark_node *document = make_document();
110+
85111
cmark_strbuf *line = (cmark_strbuf *)malloc(sizeof(cmark_strbuf));
86112
cmark_strbuf *buf = (cmark_strbuf *)malloc(sizeof(cmark_strbuf));
87113
cmark_strbuf_init(line, 256);
@@ -90,31 +116,26 @@ cmark_parser *cmark_parser_new(int options) {
90116
parser->refmap = cmark_reference_map_new();
91117
parser->root = document;
92118
parser->current = document;
93-
parser->line_number = 0;
94-
parser->offset = 0;
95-
parser->column = 0;
96-
parser->first_nonspace = 0;
97-
parser->first_nonspace_column = 0;
98-
parser->indent = 0;
99-
parser->blank = false;
100-
parser->partially_consumed_tab = false;
101119
parser->curline = line;
102-
parser->last_line_length = 0;
103120
parser->linebuf = buf;
104-
parser->options = options;
121+
105122
parser->last_buffer_ended_with_cr = false;
106-
parser->syntax_extensions = NULL;
107-
parser->inline_syntax_extensions = NULL;
123+
124+
parser->syntax_extensions = saved_exts;
125+
parser->inline_syntax_extensions = saved_inline_exts;
126+
parser->options = saved_options;
127+
}
128+
129+
cmark_parser *cmark_parser_new(int options) {
130+
cmark_parser *parser = (cmark_parser *)calloc(1, sizeof(cmark_parser));
131+
cmark_parser_reset(parser);
132+
parser->options = options;
108133

109134
return parser;
110135
}
111136

112137
void cmark_parser_free(cmark_parser *parser) {
113-
cmark_strbuf_free(parser->curline);
114-
free(parser->curline);
115-
cmark_strbuf_free(parser->linebuf);
116-
free(parser->linebuf);
117-
cmark_reference_map_free(parser->refmap);
138+
cmark_parser_dispose(parser);
118139
cmark_llist_free(parser->syntax_extensions);
119140
cmark_llist_free(parser->inline_syntax_extensions);
120141
free(parser);
@@ -1249,6 +1270,12 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
12491270
}
12501271

12511272
cmark_node *cmark_parser_finish(cmark_parser *parser) {
1273+
cmark_node *res;
1274+
1275+
/* Parser was already finished once */
1276+
if (parser->root == NULL)
1277+
return NULL;
1278+
12521279
if (parser->linebuf->size) {
12531280
S_process_line(parser, parser->linebuf->ptr, parser->linebuf->size);
12541281
cmark_strbuf_clear(parser->linebuf);
@@ -1267,7 +1294,13 @@ cmark_node *cmark_parser_finish(cmark_parser *parser) {
12671294
abort();
12681295
}
12691296
#endif
1270-
return parser->root;
1297+
1298+
res = parser->root;
1299+
parser->root = NULL;
1300+
1301+
cmark_parser_reset(parser);
1302+
1303+
return res;
12711304
}
12721305

12731306
int cmark_parser_get_line_number(cmark_parser *parser) {

0 commit comments

Comments
 (0)