diff options
author | Rafael G. Martins <rafael@rafaelmartins.eng.br> | 2016-07-03 17:42:54 +0200 |
---|---|---|
committer | Rafael G. Martins <rafael@rafaelmartins.eng.br> | 2016-07-03 17:42:54 +0200 |
commit | 4aac65c4b8f2d8415ca8d9d8449e0158e0ff1e9c (patch) | |
tree | 609b2e2349371006e37c9112c9ceebbbffe45950 /src | |
parent | c23d58aaec79938f29cdac8336d4dcd46cc346ab (diff) | |
download | blogc-4aac65c4b8f2d8415ca8d9d8449e0158e0ff1e9c.tar.gz blogc-4aac65c4b8f2d8415ca8d9d8449e0158e0ff1e9c.tar.bz2 blogc-4aac65c4b8f2d8415ca8d9d8449e0158e0ff1e9c.zip |
blogc: added utf8 validation
Diffstat (limited to 'src')
-rw-r--r-- | src/blogc.c | 6 | ||||
-rw-r--r-- | src/file.c | 9 | ||||
-rw-r--r-- | src/utf8.c | 88 | ||||
-rw-r--r-- | src/utf8.h | 19 |
4 files changed, 122 insertions, 0 deletions
diff --git a/src/blogc.c b/src/blogc.c index 40a5918..4606740 100644 --- a/src/blogc.c +++ b/src/blogc.c @@ -30,6 +30,7 @@ #include "loader.h" #include "renderer.h" #include "error.h" +#include "utf8.h" #include "utils.h" #ifndef PACKAGE_VERSION @@ -125,6 +126,11 @@ main(int argc, char **argv) sb_trie_insert(config, "BLOGC_VERSION", sb_strdup(PACKAGE_VERSION)); for (unsigned int i = 1; i < argc; i++) { + if (!blogc_utf8_validate((uint8_t*) argv[i], strlen(argv[i]))) { + fprintf(stderr, "blogc: error: command-line argument is not utf8-" + "encoded: %s\n", argv[i]); + goto cleanup; + } tmp = NULL; if (argv[i][0] == '-') { switch (argv[i][1]) { @@ -16,6 +16,7 @@ #include <string.h> #include "file.h" #include "error.h" +#include "utf8.h" #include "utils.h" // this would belong to loader.c, but we need it in a separated file to be @@ -47,6 +48,14 @@ blogc_file_get_contents(const char *path, size_t *len, blogc_error_t **err) sb_string_append_len(str, buffer, read_len); } fclose(fp); + + if (!blogc_utf8_validate_str(str)) { + *err = blogc_error_new_printf(BLOGC_ERROR_LOADER, + "File content is not valid UTF-8: %s", path); + sb_string_free(str, true); + return NULL; + } + return sb_string_free(str, false); } diff --git a/src/utf8.c b/src/utf8.c new file mode 100644 index 0000000..deea46d --- /dev/null +++ b/src/utf8.c @@ -0,0 +1,88 @@ +/* + * blogc: A blog compiler. + * Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de> + * Copyright (c) 2016 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +// Based on Bjoern Hoehrmann's algorithm. +// See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. + +#include <stdbool.h> +#include <inttypes.h> +#include "utils.h" + +#define UTF8_ACCEPT 0 +#define UTF8_REJECT 12 + + +static const uint8_t utf8d[] = { + // The first part of the table maps bytes to character classes that + // to reduce the size of the transition table and create bitmasks. + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + + // The second part is a transition table that maps a combination + // of a state of the automaton and a character class to a state. + 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, + 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, + 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, + 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, + 12,36,12,12,12,12,12,12,12,12,12,12, +}; + + +static uint32_t inline +decode(uint32_t* state, uint32_t* codep, uint32_t byte) { + uint32_t type = utf8d[byte]; + + *codep = (*state != UTF8_ACCEPT) ? + (byte & 0x3fu) | (*codep << 6) : + (0xff >> type) & (byte); + + *state = utf8d[256 + *state + type]; + return *state; +} + + +bool +blogc_utf8_validate(const uint8_t *str, size_t len) +{ + uint32_t codepoint; + uint32_t state = 0; + + for (size_t i = 0; i < len; i++) + decode(&state, &codepoint, str[i]); + + return state == UTF8_ACCEPT; +} + + +bool +blogc_utf8_validate_str(sb_string_t *str) +{ + return blogc_utf8_validate((uint8_t*) str->str, str->len); +} diff --git a/src/utf8.h b/src/utf8.h new file mode 100644 index 0000000..837d02f --- /dev/null +++ b/src/utf8.h @@ -0,0 +1,19 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015-2016 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#ifndef _UTF_8_H +#define _UTF_8_H + +#include <inttypes.h> +#include <stdbool.h> +#include "utils.h" + +bool blogc_utf8_validate(const uint8_t *str, size_t len); +bool blogc_utf8_validate_str(sb_string_t *str); + +#endif /* _UTF_8_H */ |