aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2021-02-20 16:50:11 -0500
committerDavid Robillard <d@drobilla.net>2022-01-13 23:03:35 -0500
commitcb93c91df45006a5406921c75f4bfd551182953f (patch)
treef4b23baee68e9b9c00fd39701a5d109bfd31adf5
parentf4016a594bc74a08c3a432047e6fbbaeb3cf6b14 (diff)
downloadserd-cb93c91df45006a5406921c75f4bfd551182953f.tar.gz
serd-cb93c91df45006a5406921c75f4bfd551182953f.tar.bz2
serd-cb93c91df45006a5406921c75f4bfd551182953f.zip
Zero node padding before passing to reader sinks
-rw-r--r--src/n3.c5
-rw-r--r--src/node.c30
-rw-r--r--src/node.h3
-rw-r--r--src/reader.c4
-rw-r--r--src/stack.h1
5 files changed, 41 insertions, 2 deletions
diff --git a/src/n3.c b/src/n3.c
index cc4ee27a..24642fb9 100644
--- a/src/n3.c
+++ b/src/n3.c
@@ -1199,7 +1199,7 @@ read_object(SerdReader* const reader,
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;
@@ -1436,6 +1436,7 @@ read_base(SerdReader* const reader, const bool sparql, const bool token)
SerdNode* uri = NULL;
TRY(st, read_IRIREF(reader, &uri));
+ serd_node_zero_pad(uri);
TRY(st, serd_sink_write_base(reader->sink, uri));
read_ws_star(reader);
@@ -1476,6 +1477,8 @@ read_prefixID(SerdReader* const reader, const bool sparql, const bool token)
SerdNode* uri = NULL;
TRY(st, read_IRIREF(reader, &uri));
+ serd_node_zero_pad(name);
+ serd_node_zero_pad(uri);
st = serd_sink_write_prefix(reader->sink, name, uri);
if (!sparql) {
diff --git a/src/node.c b/src/node.c
index 043ed9a5..a4e40611 100644
--- a/src/node.c
+++ b/src/node.c
@@ -148,6 +148,27 @@ serd_node_set(SerdNode** const dst, const SerdNode* const src)
memcpy(*dst, src, size);
}
+/**
+ 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->length;
+ const size_t padded_size = serd_node_pad_size(size);
+
+ memset(buf + size, 0, padded_size - size);
+
+ if (node->flags & (SERD_HAS_DATATYPE | SERD_HAS_LANGUAGE)) {
+ serd_node_zero_pad(serd_node_meta(node));
+ }
+}
+
SerdNode*
serd_new_simple_node(const SerdNodeType type, const SerdStringView str)
{
@@ -246,7 +267,14 @@ serd_node_copy(const SerdNode* node)
}
const size_t size = serd_node_total_size(node);
- SerdNode* copy = (SerdNode*)serd_calloc_aligned(serd_node_align, size);
+#ifndef NDEBUG
+ const size_t unpadded_size = node->length;
+ const size_t padded_size = serd_node_pad_size(node->length);
+ 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*)serd_calloc_aligned(serd_node_align, size);
memcpy(copy, node, size);
return copy;
}
diff --git a/src/node.h b/src/node.h
index 816445fb..73af0d63 100644
--- a/src/node.h
+++ b/src/node.h
@@ -49,6 +49,9 @@ void
serd_node_set(SerdNode* SERD_NULLABLE* SERD_NONNULL dst,
const SerdNode* SERD_NULLABLE src);
+void
+serd_node_zero_pad(SerdNode* SERD_NONNULL node);
+
/// Create a new URI from a string, resolved against a base URI
SerdNode* SERD_ALLOCATED
serd_new_resolved_uri(SerdStringView string, SerdURIView base_uri);
diff --git a/src/reader.c b/src/reader.c
index 04c7f372..1677ed92 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -124,6 +124,10 @@ emit_statement(SerdReader* const reader,
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);
+
const SerdStatus st = serd_sink_write(
reader->sink, *ctx.flags, ctx.subject, ctx.predicate, o, graph);
diff --git a/src/stack.h b/src/stack.h
index 4531b662..49f77843 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -85,6 +85,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;
}