From f3d7f3079a954d7c88c0af615bf0308fa40a062c Mon Sep 17 00:00:00 2001
From: David Robillard <d@drobilla.net>
Date: Fri, 9 Jul 2021 16:25:07 -0400
Subject: Handle writer stack overflows gracefully

---
 test/test_writer.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

(limited to 'test')

diff --git a/test/test_writer.c b/test/test_writer.c
index 190995b6..19aaf4b3 100644
--- a/test/test_writer.c
+++ b/test/test_writer.c
@@ -19,6 +19,7 @@
 #include "serd/serd.h"
 
 #include <assert.h>
+#include <stdio.h>
 #include <string.h>
 
 static void
@@ -82,11 +83,66 @@ test_write_long_literal(void)
   serd_free(out);
 }
 
+static size_t
+null_sink(const void* const buf,
+          const size_t      size,
+          const size_t      nmemb,
+          void* const       stream)
+{
+  (void)buf;
+  (void)stream;
+
+  return size * nmemb;
+}
+
+static void
+test_writer_stack_overflow(void)
+{
+  SerdEnv*    env    = serd_env_new(SERD_EMPTY_STRING());
+  SerdWriter* writer = serd_writer_new(SERD_TURTLE, 0u, env, null_sink, NULL);
+
+  const SerdSink* sink = serd_writer_sink(writer);
+
+  SerdNode* const s = serd_new_uri(SERD_STRING("http://example.org/s"));
+  SerdNode* const p = serd_new_uri(SERD_STRING("http://example.org/p"));
+
+  SerdNode*  o  = serd_new_blank(SERD_STRING("http://example.org/o"));
+  SerdStatus st = serd_sink_write(sink, SERD_ANON_O_BEGIN, s, p, o, NULL);
+  assert(!st);
+
+  // Repeatedly write nested anonymous objects until the writer stack overflows
+  for (unsigned i = 0u; i < 512u; ++i) {
+    char buf[1024];
+    snprintf(buf, sizeof(buf), "b%u", i);
+
+    SerdNode* next_o = serd_new_blank(SERD_STRING(buf));
+
+    st = serd_sink_write(sink, SERD_ANON_O_BEGIN, o, p, next_o, NULL);
+
+    serd_node_free(o);
+    o = next_o;
+
+    if (st) {
+      assert(st == SERD_ERR_OVERFLOW);
+      break;
+    }
+  }
+
+  assert(st == SERD_ERR_OVERFLOW);
+
+  serd_node_free(o);
+  serd_node_free(p);
+  serd_node_free(s);
+  serd_writer_free(writer);
+  serd_env_free(env);
+}
+
 int
 main(void)
 {
   test_write_bad_prefix();
   test_write_long_literal();
+  test_writer_stack_overflow();
 
   return 0;
 }
-- 
cgit v1.2.1