diff options
author | David Robillard <d@drobilla.net> | 2021-07-09 16:25:07 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2022-01-13 23:03:32 -0500 |
commit | f3d7f3079a954d7c88c0af615bf0308fa40a062c (patch) | |
tree | 9e01d6bf8a9a1a5d91622f2d58b936bc9be8a8fa /src | |
parent | 5c90b6aff410bb4a9737680baffd79d10b5281fd (diff) | |
download | serd-f3d7f3079a954d7c88c0af615bf0308fa40a062c.tar.gz serd-f3d7f3079a954d7c88c0af615bf0308fa40a062c.tar.bz2 serd-f3d7f3079a954d7c88c0af615bf0308fa40a062c.zip |
Handle writer stack overflows gracefully
Diffstat (limited to 'src')
-rw-r--r-- | src/writer.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/src/writer.c b/src/writer.c index a2ba0482..b132dc83 100644 --- a/src/writer.c +++ b/src/writer.c @@ -501,11 +501,11 @@ reset_context(SerdWriter* writer, bool graph) } static SerdStatus -free_context(SerdWriter* writer) +free_context(const WriteContext* const ctx) { - serd_node_free(writer->context.graph); - serd_node_free(writer->context.subject); - serd_node_free(writer->context.predicate); + serd_node_free(ctx->graph); + serd_node_free(ctx->subject); + serd_node_free(ctx->predicate); return SERD_SUCCESS; } @@ -888,6 +888,10 @@ serd_writer_write_statement(SerdWriter* const writer, if (flags & (SERD_ANON_S_BEGIN | SERD_ANON_O_BEGIN)) { WriteContext* ctx = (WriteContext*)serd_stack_push(&writer->anon_stack, sizeof(WriteContext)); + if (!ctx) { + return SERD_ERR_OVERFLOW; + } + *ctx = writer->context; WriteContext new_context = { serd_node_copy(graph), serd_node_copy(subject), NULL}; @@ -916,7 +920,7 @@ serd_writer_end_anon(SerdWriter* writer, const SerdNode* node) } --writer->indent; write_sep(writer, SEP_ANON_END); - free_context(writer); + free_context(&writer->context); writer->context = *anon_stack_top(writer); serd_stack_pop(&writer->anon_stack, sizeof(WriteContext)); const bool is_subject = serd_node_equals(node, writer->context.subject); @@ -937,7 +941,7 @@ serd_writer_finish(SerdWriter* writer) write_sep(writer, SEP_GRAPH_END); } serd_byte_sink_flush(&writer->byte_sink); - free_context(writer); + free_context(&writer->context); writer->indent = 0; writer->context = WRITE_CONTEXT_NULL; return SERD_SUCCESS; @@ -958,7 +962,7 @@ serd_writer_new(SerdSyntax syntax, writer->env = env; writer->root_node = NULL; writer->root_uri = SERD_URI_NULL; - writer->anon_stack = serd_stack_new(4 * sizeof(WriteContext)); + writer->anon_stack = serd_stack_new(SERD_PAGE_SIZE); writer->context = context; writer->list_subj = NULL; writer->empty = true; @@ -1077,6 +1081,13 @@ serd_writer_free(SerdWriter* writer) } serd_writer_finish(writer); + + // Free any leaked entries in the anonymous context stack + while (!serd_stack_is_empty(&writer->anon_stack)) { + free_context(anon_stack_top(writer)); + serd_stack_pop(&writer->anon_stack, sizeof(WriteContext)); + } + serd_stack_free(&writer->anon_stack); free(writer->bprefix); serd_byte_sink_free(&writer->byte_sink); |