aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2018-05-13 00:48:31 +0200
committerDavid Robillard <d@drobilla.net>2019-12-19 20:52:42 -0500
commit8892afbf7aca85acb37fdc5fda2e6de333d95bb1 (patch)
treeb1298fe69e625ee37cf6a7ecb3544ff869ab828f
parenta3459a9ec4c25ad699791f549f5f450549e88e6f (diff)
downloadserd-8892afbf7aca85acb37fdc5fda2e6de333d95bb1.tar.gz
serd-8892afbf7aca85acb37fdc5fda2e6de333d95bb1.tar.bz2
serd-8892afbf7aca85acb37fdc5fda2e6de333d95bb1.zip
Zero node padding before passing to reader sinks
-rw-r--r--src/n3.c9
-rw-r--r--src/node.c28
-rw-r--r--src/node.h1
-rw-r--r--src/reader.c5
-rw-r--r--src/stack.h1
5 files changed, 41 insertions, 3 deletions
diff --git a/src/n3.c b/src/n3.c
index f4f296c5..6d778b1d 100644
--- a/src/n3.c
+++ b/src/n3.c
@@ -1066,10 +1066,10 @@ read_object(SerdReader* reader, ReadContext* ctx, bool emit, bool* ate_dot)
o->flags = flags;
}
- if (ret && emit && simple) {
+ if (ret && emit && simple && o) {
ret = emit_statement(reader, *ctx, o);
} else if (ret && !emit) {
- ctx->object = o;
+ ctx->object = o;
return true;
}
@@ -1277,6 +1277,7 @@ read_base(SerdReader* reader, bool sparql, bool token)
if (!uri) {
return false;
} else if (reader->sink->base) {
+ serd_node_zero_pad(uri);
reader->sink->base(reader->sink->handle, uri);
}
@@ -1311,12 +1312,14 @@ read_prefixID(SerdReader* reader, bool sparql, bool token)
}
read_ws_star(reader);
- const SerdNode* uri = read_IRIREF(reader);
+ SerdNode* uri = read_IRIREF(reader);
if (!uri) {
return false;
}
if (reader->sink->prefix) {
+ serd_node_zero_pad(name);
+ serd_node_zero_pad(uri);
ret = !reader->sink->prefix(reader->sink->handle, name, uri);
}
if (!sparql) {
diff --git a/src/node.c b/src/node.c
index 83242092..0211996a 100644
--- a/src/node.c
+++ b/src/node.c
@@ -218,6 +218,27 @@ serd_node_new_uri(const char* str)
return str ? serd_node_new_simple_node(SERD_URI, str, strlen(str)) : NULL;
}
+/**
+ Zero node padding.
+
+ This is used for nodes which live in re-used stack memory during reading,
+ which must be normalized before being passed to a sink so comparison will
+ work correctly.
+*/
+void
+serd_node_zero_pad(SerdNode* node)
+{
+ char* buf = serd_node_buffer(node);
+ const size_t size = node->n_bytes;
+ const size_t padded_size = serd_node_pad_size(node->n_bytes);
+
+ memset(buf + size, 0, padded_size - size);
+
+ if (node->flags & (SERD_HAS_DATATYPE|SERD_HAS_LANGUAGE)) {
+ serd_node_zero_pad(serd_node_get_meta(node));
+ }
+}
+
SerdNode*
serd_node_copy(const SerdNode* node)
{
@@ -226,6 +247,13 @@ serd_node_copy(const SerdNode* node)
}
const size_t size = serd_node_total_size(node);
+#ifndef NDEBUG
+ const size_t unpadded_size = node->n_bytes;
+ const size_t padded_size = serd_node_pad_size(node->n_bytes);
+ for (size_t i = 0; i < padded_size - unpadded_size; ++i) {
+ assert(serd_node_buffer_c(node)[unpadded_size + i] == '\0');
+ }
+#endif
SerdNode* copy = (SerdNode*)calloc(1, size + 3);
memcpy(copy, node, size);
return copy;
diff --git a/src/node.h b/src/node.h
index 1dbb10d0..47d73a32 100644
--- a/src/node.h
+++ b/src/node.h
@@ -41,6 +41,7 @@ serd_node_buffer_c(const SerdNode* node)
SerdNode* serd_node_malloc(size_t n_bytes, SerdNodeFlags flags, SerdType type);
void serd_node_set(SerdNode** dst, const SerdNode* src);
+void serd_node_zero_pad(SerdNode* node);
SerdNode* serd_node_new_resolved_uri_i(const char* str, const SerdURI* base);
#endif // SERD_NODE_H
diff --git a/src/reader.c b/src/reader.c
index 3eccacc7..9783502c 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -120,6 +120,11 @@ emit_statement(SerdReader* reader, ReadContext ctx, SerdNode* o)
if (!graph && reader->default_graph) {
graph = reader->default_graph;
}
+
+ /* Zero the pad of the object node on the top of the stack. Lower nodes
+ (subject and predicate) were already zeroed by subsequent pushes. */
+ serd_node_zero_pad(o);
+
bool ret = !reader->sink->statement ||
!reader->sink->statement(
reader->sink->handle, *ctx.flags, graph,
diff --git a/src/stack.h b/src/stack.h
index 5bd86f7a..31ed6c09 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -82,6 +82,7 @@ static inline void
serd_stack_pop_to(SerdStack* stack, size_t n_bytes)
{
assert(stack->size >= n_bytes);
+ memset(stack->buf + n_bytes, 0, stack->size - n_bytes);
stack->size = n_bytes;
}