diff options
author | David Robillard <d@drobilla.net> | 2020-08-15 20:22:26 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2020-10-27 13:13:58 +0100 |
commit | c4e1eb61f7b8262030344712537c8918f4949a20 (patch) | |
tree | 90ee9794cb6d5c8e14959bdfd4613b93dde2d970 | |
parent | 9c9232a079a38e4f56de6bc7b1a6c5b1de332144 (diff) | |
download | serd-c4e1eb61f7b8262030344712537c8918f4949a20.tar.gz serd-c4e1eb61f7b8262030344712537c8918f4949a20.tar.bz2 serd-c4e1eb61f7b8262030344712537c8918f4949a20.zip |
Handle read errors more precisely
-rw-r--r-- | serd/serd.h | 3 | ||||
-rw-r--r-- | src/n3.c | 39 | ||||
-rw-r--r-- | src/reader.c | 2 | ||||
-rw-r--r-- | src/string.c | 1 | ||||
-rw-r--r-- | tests/serd_test.c | 2 |
5 files changed, 22 insertions, 25 deletions
diff --git a/serd/serd.h b/serd/serd.h index 9d5f09b4..433f38e8 100644 --- a/serd/serd.h +++ b/serd/serd.h @@ -110,7 +110,8 @@ typedef enum { SERD_ERR_BAD_CURIE, ///< Invalid CURIE (e.g. prefix does not exist) SERD_ERR_INTERNAL, ///< Unexpected internal error (should not happen) SERD_ERR_OVERFLOW, ///< Stack overflow - SERD_ERR_INVALID ///< Invalid data + SERD_ERR_INVALID, ///< Invalid data + SERD_ERR_NO_DATA ///< Unexpected end of input } SerdStatus; /// RDF syntax type @@ -206,9 +206,10 @@ read_utf8_character(SerdReader* reader, SerdNode* dest, uint8_t c) uint32_t size = 0; uint8_t bytes[4] = {0, 0, 0, 0}; SerdStatus st = read_utf8_bytes(reader, bytes, &size, c); - if (st) { - push_bytes(reader, dest, replacement_char, 3); + if (st && reader->strict) { return st; + } else if (st) { + return push_bytes(reader, dest, replacement_char, 3); } return push_bytes(reader, dest, bytes, size); @@ -221,8 +222,8 @@ read_utf8_code(SerdReader* reader, SerdNode* dest, uint32_t* code, uint8_t c) uint8_t bytes[4] = {0, 0, 0, 0}; SerdStatus st = read_utf8_bytes(reader, bytes, &size, c); if (st) { - push_bytes(reader, dest, replacement_char, 3); - return st; + return reader->strict ? st + : push_bytes(reader, dest, replacement_char, 3); } if (!(st = push_bytes(reader, dest, bytes, size))) { @@ -312,8 +313,7 @@ static SerdStatus read_STRING_LITERAL_LONG(SerdReader* reader, SerdNode* ref, uint8_t q) { SerdStatus st = SERD_SUCCESS; - - while (!(st && reader->strict)) { + while (!st || (st == SERD_ERR_BAD_SYNTAX && !reader->strict)) { const int c = peek_byte(reader); if (c == '\\') { eat_byte_safe(reader, c); @@ -323,6 +323,8 @@ read_STRING_LITERAL_LONG(SerdReader* reader, SerdNode* ref, uint8_t q) return r_err(reader, st, "invalid escape `\\%c'\n", peek_byte(reader)); } + } else if (c == EOF) { + st = r_err(reader, SERD_ERR_NO_DATA, "unexpected end of file\n"); } else if (c == q) { eat_byte_safe(reader, q); const int q2 = eat_byte_safe(reader, peek_byte(reader)); @@ -334,9 +336,6 @@ read_STRING_LITERAL_LONG(SerdReader* reader, SerdNode* ref, uint8_t q) ref->flags |= SERD_HAS_QUOTE; push_byte(reader, ref, c); st = read_character(reader, ref, (uint8_t)q2); - } else if (c == EOF) { - return r_err(reader, SERD_ERR_BAD_SYNTAX, - "end of file in long string\n"); } else { st = read_character(reader, ref, (uint8_t)eat_byte_safe(reader, c)); } @@ -351,8 +350,7 @@ static SerdStatus read_STRING_LITERAL(SerdReader* reader, SerdNode* ref, uint8_t q) { SerdStatus st = SERD_SUCCESS; - - while (!(st && reader->strict)) { + while (!st || (st == SERD_ERR_BAD_SYNTAX && !reader->strict)) { const int c = peek_byte(reader); uint32_t code = 0; switch (c) { @@ -372,7 +370,7 @@ read_STRING_LITERAL(SerdReader* reader, SerdNode* ref, uint8_t q) break; default: if (c == q) { - eat_byte_check(reader, q); + eat_byte_safe(reader, q); return SERD_SUCCESS; } else { st = read_character( @@ -381,8 +379,7 @@ read_STRING_LITERAL(SerdReader* reader, SerdNode* ref, uint8_t q) } } - return st ? st - : eat_byte_check(reader, q) ? SERD_SUCCESS : SERD_ERR_BAD_SYNTAX; + return st; } static SerdStatus @@ -723,9 +720,7 @@ read_IRIREF(SerdReader* reader, SerdNode** dest) } else if (!(c & 0x80)) { push_byte(reader, *dest, c); } else if (read_utf8_character(reader, *dest, (uint8_t)c)) { - if (reader->strict) { - return SERD_ERR_BAD_SYNTAX; - } + st = reader->strict ? SERD_ERR_BAD_SYNTAX : SERD_FAILURE; } } } @@ -1532,7 +1527,8 @@ read_turtleTrigDoc(SerdReader* reader) const size_t orig_stack_size = reader->stack.size; const SerdStatus st = read_n3_statement(reader); if (st > SERD_FAILURE) { - if (reader->strict) { + if (reader->strict || reader->source.eof || + st == SERD_ERR_OVERFLOW) { serd_stack_pop_to(&reader->stack, orig_stack_size); return st; } @@ -1547,7 +1543,7 @@ SerdStatus read_nquadsDoc(SerdReader* reader) { SerdStatus st = SERD_SUCCESS; - while (!reader->source.eof) { + while (!st && !reader->source.eof) { const size_t orig_stack_size = reader->stack.size; SerdStatementFlags flags = 0; @@ -1591,9 +1587,8 @@ read_nquadsDoc(SerdReader* reader) } } - TRY(st, emit_statement(reader, ctx, ctx.object)); - + st = emit_statement(reader, ctx, ctx.object); serd_stack_pop_to(&reader->stack, orig_stack_size); } - return SERD_SUCCESS; + return st; } diff --git a/src/reader.c b/src/reader.c index a88e128d..d2ce61d3 100644 --- a/src/reader.c +++ b/src/reader.c @@ -286,7 +286,7 @@ serd_reader_prepare(SerdReader* 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/string.c b/src/string.c index 8ab735dc..b465bf8d 100644 --- a/src/string.c +++ b/src/string.c @@ -45,6 +45,7 @@ serd_strerror(SerdStatus status) case SERD_ERR_INTERNAL: return "Internal error"; case SERD_ERR_OVERFLOW: return "Stack overflow"; case SERD_ERR_INVALID: return "Invalid data"; + case SERD_ERR_NO_DATA: return "Unexpectd end of input"; default: break; } return "Unknown error"; // never reached diff --git a/tests/serd_test.c b/tests/serd_test.c index e5e1ae18..7a9e67bd 100644 --- a/tests/serd_test.c +++ b/tests/serd_test.c @@ -355,7 +355,7 @@ test_strerror(void) { const char* msg = serd_strerror(SERD_SUCCESS); assert(!strcmp(msg, "Success")); - for (int i = SERD_FAILURE; i <= SERD_ERR_INVALID; ++i) { + for (int i = SERD_FAILURE; i <= SERD_ERR_NO_DATA; ++i) { msg = serd_strerror((SerdStatus)i); assert(strcmp(msg, "Success")); } |