diff options
author | David Robillard <d@drobilla.net> | 2021-07-08 22:50:02 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2023-12-02 18:49:07 -0500 |
commit | 3389cf3e506ad9e8475daf8b1cac0248274849bc (patch) | |
tree | 6906508561067469cece409f30c28fb458d69a90 /src | |
parent | 38f2d631ae89388ca96ebfbc66012c8c29a3d35b (diff) | |
download | serd-3389cf3e506ad9e8475daf8b1cac0248274849bc.tar.gz serd-3389cf3e506ad9e8475daf8b1cac0248274849bc.tar.bz2 serd-3389cf3e506ad9e8475daf8b1cac0248274849bc.zip |
Handle read errors more precisely
Diffstat (limited to 'src')
-rw-r--r-- | src/n3.c | 39 | ||||
-rw-r--r-- | src/reader.c | 17 | ||||
-rw-r--r-- | src/reader.h | 3 |
3 files changed, 39 insertions, 20 deletions
@@ -209,6 +209,11 @@ read_utf8_character(SerdReader* const reader, uint32_t size = 0; uint8_t bytes[4] = {0, 0, 0, 0}; SerdStatus st = read_utf8_bytes(reader, bytes, &size, c); + + if (!tolerate_status(reader, st)) { + return st; + } + if (st) { const SerdStatus rst = push_bytes(reader, dest, replacement_char, 3); return rst ? rst : st; @@ -341,12 +346,13 @@ read_STRING_LITERAL_LONG(SerdReader* const reader, const uint8_t q) { SerdStatus st = SERD_SUCCESS; - - while (!(st && reader->strict)) { + while (tolerate_status(reader, st)) { const int c = peek_byte(reader); if (c == '\\') { skip_byte(reader, c); st = read_string_escape(reader, ref); + } else if (c == EOF) { + st = r_err(reader, SERD_NO_DATA, "unexpected end of file\n"); } else if (c == q) { skip_byte(reader, q); const int q2 = eat_byte_safe(reader, peek_byte(reader)); @@ -365,14 +371,12 @@ read_STRING_LITERAL_LONG(SerdReader* const reader, st = read_character(reader, ref, (uint8_t)q2); } } - } else if (c == EOF) { - st = r_err(reader, SERD_BAD_SYNTAX, "end of file in long string\n"); } else { st = read_character(reader, ref, (uint8_t)eat_byte_safe(reader, c)); } } - return (st && reader->strict) ? st : SERD_SUCCESS; + return tolerate_status(reader, st) ? SERD_SUCCESS : st; } // STRING_LITERAL_QUOTE and STRING_LITERAL_SINGLE_QUOTE @@ -384,7 +388,7 @@ read_STRING_LITERAL(SerdReader* const reader, { SerdStatus st = SERD_SUCCESS; - while (!st || !reader->strict) { + while (tolerate_status(reader, st)) { const int c = peek_byte(reader); switch (c) { case EOF: @@ -405,7 +409,7 @@ read_STRING_LITERAL(SerdReader* const reader, } } - return st ? st : eat_byte_check(reader, q); + return tolerate_status(reader, st) ? SERD_SUCCESS : st; } static SerdStatus @@ -792,15 +796,13 @@ read_IRIREF(SerdReader* const reader, SerdNode** const dest) } } else if (!(c & 0x80)) { st = push_byte(reader, *dest, c); - } else if (read_utf8_character(reader, *dest, (uint8_t)c)) { - if (reader->strict) { - return SERD_BAD_SYNTAX; - } + } else { + st = read_utf8_character(reader, *dest, (uint8_t)c); } } } - return st; + return tolerate_status(reader, st) ? SERD_SUCCESS : st; } static SerdStatus @@ -1066,7 +1068,7 @@ read_BLANK_NODE_LABEL(SerdReader* const reader, // Adjust ID to avoid clashes with generated IDs if necessary st = adjust_blank_id(reader, buf); - return st; + return tolerate_status(reader, st) ? SERD_SUCCESS : st; } static SerdStatus @@ -1102,7 +1104,8 @@ read_anon(SerdReader* const reader, ctx.subject = *dest; if (!empty) { bool ate_dot_in_list = false; - TRY_FAILING(st, read_predicateObjectList(reader, ctx, &ate_dot_in_list)); + TRY(st, read_predicateObjectList(reader, ctx, &ate_dot_in_list)); + if (ate_dot_in_list) { return r_err(reader, SERD_BAD_SYNTAX, "'.' inside blank\n"); } @@ -1241,7 +1244,7 @@ read_objectList(SerdReader* const reader, ReadContext ctx, bool* const ate_dot) reader, SERD_BAD_SYNTAX, "syntax does not support abbreviation\n"); } - while (!*ate_dot && eat_delim(reader, ',')) { + while (st <= SERD_FAILURE && !*ate_dot && eat_delim(reader, ',')) { st = read_object(reader, &ctx, true, ate_dot); } @@ -1681,7 +1684,7 @@ read_turtleTrigDoc(SerdReader* const reader) const SerdStatus st = read_n3_statement(reader); if (st > SERD_FAILURE) { - if (reader->strict) { + if (!tolerate_status(reader, st)) { serd_stack_pop_to(&reader->stack, orig_stack_size); return st; } @@ -1738,9 +1741,7 @@ read_nquads_statement(SerdReader* const reader) TRY(st, eat_byte_check(reader, '.')); } - TRY(st, emit_statement(reader, ctx, ctx.object)); - - return SERD_SUCCESS; + return emit_statement(reader, ctx, ctx.object); } SerdStatus diff --git a/src/reader.c b/src/reader.c index 15c45202..f45e9e0d 100644 --- a/src/reader.c +++ b/src/reader.c @@ -53,6 +53,21 @@ genid_size(const SerdReader* const reader) return reader->bprefix_len + 1 + 10 + 1; // + "b" + UINT32_MAX + \0 } +bool +tolerate_status(const SerdReader* const reader, const SerdStatus status) +{ + if (status == SERD_SUCCESS || status == SERD_FAILURE) { + return true; + } + + if (status == SERD_BAD_STREAM || status == SERD_BAD_STACK || + status == SERD_BAD_WRITE || status == SERD_NO_DATA) { + return false; + } + + return !reader->strict; +} + SerdNode* blank_id(SerdReader* const reader) { @@ -285,7 +300,7 @@ serd_reader_prepare(SerdReader* const reader) } else if (st == SERD_FAILURE) { reader->source.eof = true; } else { - r_err(reader, st, "read error: %s\n", strerror(errno)); + r_err(reader, st, "error preparing read: %s\n", strerror(errno)); } return st; } diff --git a/src/reader.h b/src/reader.h index 3f830ef4..fcbcb110 100644 --- a/src/reader.h +++ b/src/reader.h @@ -71,6 +71,9 @@ push_node(SerdReader* reader, SERD_PURE_FUNC size_t genid_size(const SerdReader* reader); +SERD_PURE_FUNC bool +tolerate_status(const SerdReader* reader, SerdStatus status); + SerdNode* blank_id(SerdReader* reader); |