From 016cf82b34f1f84229930bfa216817b5863e6691 Mon Sep 17 00:00:00 2001 From: Bas Alberts Date: Mon, 23 Jan 2023 14:43:51 -0500 Subject: [PATCH 1/2] Prevent implicit integer truncations This commit changes size integers to consistently be of type size_t to prevent implicit integer truncations during integer arithmetic. What remain are explicit truncations to (bufsize_t) which is of type int32_t. This requires additional careful consideration. --- extensions/autolink.c | 20 ++++++++++++++------ extensions/table.c | 2 +- src/map.c | 2 +- src/map.h | 10 +++++----- src/parser.h | 2 +- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/extensions/autolink.c b/extensions/autolink.c index 182c902e2..fc4c6f2c4 100644 --- a/extensions/autolink.c +++ b/extensions/autolink.c @@ -9,6 +9,14 @@ #include #endif +// for ssize_t +#ifdef _MSC_VER +#include +typedef SSIZE_T ssize_t; +#else +#include +#endif + static int is_valid_hostchar(const uint8_t *link, size_t link_len) { int32_t ch; int r = cmark_utf8proc_iterate(link, (bufsize_t)link_len, &ch); @@ -290,10 +298,10 @@ static cmark_node *match(cmark_syntax_extension *ext, cmark_parser *parser, // inline was finished in inlines.c. } -static bool validate_protocol(char protocol[], uint8_t *data, int rewind, int max_rewind) { +static bool validate_protocol(char protocol[], uint8_t *data, size_t rewind, size_t max_rewind) { size_t len = strlen(protocol); - if (len > (size_t)(max_rewind - rewind)) { + if (len > (max_rewind - rewind)) { return false; } @@ -302,11 +310,11 @@ static bool validate_protocol(char protocol[], uint8_t *data, int rewind, int ma return false; } - if (len == (size_t)(max_rewind - rewind)) { + if (len == (max_rewind - rewind)) { return true; } - char prev_char = data[-rewind - len - 1]; + char prev_char = data[-((ssize_t)rewind) - len - 1]; // Make sure the character before the protocol is non-alphanumeric return !cmark_isalnum(prev_char); @@ -421,7 +429,7 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text) { cmark_node *link_text = cmark_node_new_with_mem(CMARK_NODE_TEXT, parser->mem); cmark_chunk email = cmark_chunk_dup( &detached_chunk, - start + offset + max_rewind - rewind, + (bufsize_t)(start + offset + max_rewind - rewind), (bufsize_t)(link_end + rewind)); cmark_chunk_to_cstr(parser->mem, &email); link_text->as.literal = email; @@ -436,7 +444,7 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text) { cmark_node_insert_after(link_node, post); - text->as.literal = cmark_chunk_dup(&detached_chunk, start, offset + max_rewind - rewind); + text->as.literal = cmark_chunk_dup(&detached_chunk, (bufsize_t)start, (bufsize_t)(offset + max_rewind - rewind)); cmark_chunk_to_cstr(parser->mem, &text->as.literal); text = post; diff --git a/extensions/table.c b/extensions/table.c index cc8dc18c5..7f2813226 100644 --- a/extensions/table.c +++ b/extensions/table.c @@ -133,7 +133,7 @@ static node_cell* append_row_cell(cmark_mem *mem, table_row *row) { // Use realloc to double the size of the buffer. row->cells = (node_cell *)mem->realloc(row->cells, (2 * n_columns - 1) * sizeof(node_cell)); } - row->n_columns = n_columns; + row->n_columns = (uint16_t)n_columns; return &row->cells[n_columns-1]; } diff --git a/src/map.c b/src/map.c index fda9606a7..f60f8fc60 100644 --- a/src/map.c +++ b/src/map.c @@ -51,7 +51,7 @@ refsearch(const void *label, const void *p2) { } static void sort_map(cmark_map *map) { - unsigned int i = 0, last = 0, size = map->size; + size_t i = 0, last = 0, size = map->size; cmark_map_entry *r = map->refs, **sorted = NULL; sorted = (cmark_map_entry **)map->mem->calloc(size, sizeof(cmark_map_entry *)); diff --git a/src/map.h b/src/map.h index 345dcf87b..cc9b1f30c 100644 --- a/src/map.h +++ b/src/map.h @@ -10,8 +10,8 @@ extern "C" { struct cmark_map_entry { struct cmark_map_entry *next; unsigned char *label; - unsigned int age; - unsigned int size; + size_t age; + size_t size; }; typedef struct cmark_map_entry cmark_map_entry; @@ -24,9 +24,9 @@ struct cmark_map { cmark_mem *mem; cmark_map_entry *refs; cmark_map_entry **sorted; - unsigned int size; - unsigned int ref_size; - unsigned int max_ref_size; + size_t size; + size_t ref_size; + size_t max_ref_size; cmark_map_free_f free; }; diff --git a/src/parser.h b/src/parser.h index d5964c5b2..436c53f5b 100644 --- a/src/parser.h +++ b/src/parser.h @@ -46,7 +46,7 @@ struct cmark_parser { /* Options set by the user, see the Options section in cmark.h */ int options; bool last_buffer_ended_with_cr; - unsigned int total_size; + size_t total_size; cmark_llist *syntax_extensions; cmark_llist *inline_syntax_extensions; cmark_ispunct_func backslash_ispunct; From 01162c5b28d923bf96472d94821aa3b087b347ef Mon Sep 17 00:00:00 2001 From: Bas Alberts Date: Mon, 23 Jan 2023 16:39:02 -0500 Subject: [PATCH 2/2] move from ssize_t to the C standard based ptrdiff_t --- extensions/autolink.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/extensions/autolink.c b/extensions/autolink.c index fc4c6f2c4..f3b75a7e9 100644 --- a/extensions/autolink.c +++ b/extensions/autolink.c @@ -2,6 +2,7 @@ #include #include #include +#include #if defined(_WIN32) #define strncasecmp _strnicmp @@ -9,14 +10,6 @@ #include #endif -// for ssize_t -#ifdef _MSC_VER -#include -typedef SSIZE_T ssize_t; -#else -#include -#endif - static int is_valid_hostchar(const uint8_t *link, size_t link_len) { int32_t ch; int r = cmark_utf8proc_iterate(link, (bufsize_t)link_len, &ch); @@ -314,7 +307,7 @@ static bool validate_protocol(char protocol[], uint8_t *data, size_t rewind, siz return true; } - char prev_char = data[-((ssize_t)rewind) - len - 1]; + char prev_char = data[-((ptrdiff_t)rewind) - len - 1]; // Make sure the character before the protocol is non-alphanumeric return !cmark_isalnum(prev_char);