diff options
author | David Robillard <d@drobilla.net> | 2018-05-13 00:48:31 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2020-06-21 18:12:04 +0200 |
commit | 41bce81262f89a2659d077b0284a8a04f000daef (patch) | |
tree | fbe34698807318278220369810612d77c54cf6d8 | |
parent | 540aa01afd60e68b751baaa47cd05729e023a527 (diff) | |
download | serd-41bce81262f89a2659d077b0284a8a04f000daef.tar.gz serd-41bce81262f89a2659d077b0284a8a04f000daef.tar.bz2 serd-41bce81262f89a2659d077b0284a8a04f000daef.zip |
Zero node padding before passing to reader sinks
-rw-r--r-- | src/n3.c | 9 | ||||
-rw-r--r-- | src/node.c | 28 | ||||
-rw-r--r-- | src/node.h | 1 | ||||
-rw-r--r-- | src/reader.c | 5 | ||||
-rw-r--r-- | src/stack.h | 1 |
5 files changed, 41 insertions, 3 deletions
@@ -1073,10 +1073,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; } @@ -1283,6 +1283,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); } @@ -1317,12 +1318,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) { @@ -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; @@ -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 82be89db..078380ee 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 6358a0ed..e2d74769 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; } |