Skip to content
13 changes: 13 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ if(CMARK_THREADING)
include(FindThreads)
endif()
include(GNUInstallDirs)
include(CheckCCompilerFlag)

if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES Clang)
check_c_compiler_flag(-Wallocator-wrappers HAS_WARN_ALLOCATOR_WRAPPERS)
check_c_compiler_flag(-ftyped-memory-operations HAS_TYPED_MEMORY_OPERATIONS)
endif()

if(NOT MSVC OR CMAKE_HOST_SYSTEM_NAME STREQUAL Windows)
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON)
Expand All @@ -67,6 +73,13 @@ elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES Clang)
add_compile_options($<$<COMPILE_LANGUAGE:C>:-pedantic>)
endif()

if(HAS_WARN_ALLOCATOR_WRAPPERS)
add_compile_options($<$<COMPILE_LANGUAGE:C>:-Wallocator-wrappers>)
endif()
if(HAS_TYPED_MEMORY_OPERATIONS)
add_compile_options($<$<COMPILE_LANGUAGE:C>:-ftyped-memory-operations>)
endif()

if(CMAKE_BUILD_TYPE STREQUAL "Ubsan")
add_compile_options($<$<COMPILE_LANGUAGE:C>:-fsanitize=undefined>)
endif()
Expand Down
81 changes: 81 additions & 0 deletions Package@swift-6.3.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// swift-tools-version:6.3
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

var cSettings: [CSetting] = [
.unsafeFlags(["-ftyped-memory-operations"]),
.enableWarning("allocator-wrappers"),
]

#if os(Windows)
// When building the library on Windows, we do not have proper control of
// whether it is being built statically or dynamically. However, given the
// current default of static, we will assume that we are building
// statically. More importantly, should this not hold, this will fail at
// link time.
cSettings.append(
.define("CMARK_GFM_STATIC_DEFINE", .when(platforms: [.windows]))
)
#endif

let package = Package(
name: "cmark-gfm",
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "cmark-gfm",
targets: ["cmark-gfm"]),
.library(
name: "cmark-gfm-extensions",
targets: ["cmark-gfm-extensions"]),
.executable(
name: "cmark-gfm-bin",
targets: ["cmark-gfm-bin"]),
.executable(name: "api_test",
targets: ["api_test"])
],
targets: [
.target(name: "cmark-gfm",
path: "src",
exclude: [
"scanners.re",
"libcmark-gfm.pc.in",
"config.h.in",
"CMakeLists.txt",
],
cSettings: cSettings
),
.target(name: "cmark-gfm-extensions",
dependencies: [
"cmark-gfm",
],
path: "extensions",
exclude: [
"CMakeLists.txt",
"ext_scanners.re",
],
cSettings: cSettings
),
.executableTarget(name: "cmark-gfm-bin",
dependencies: [
"cmark-gfm",
"cmark-gfm-extensions",
],
path: "bin",
sources: [
"main.c",
]
),
.executableTarget(name: "api_test",
dependencies: [
"cmark-gfm",
"cmark-gfm-extensions",
],
path: "api_test",
exclude: [
"CMakeLists.txt",
]
)
]
)
3 changes: 2 additions & 1 deletion bin/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "syntax_extension.h"
#include "parser.h"
#include "registry.h"
#include "mem.h"

#include <cmark-gfm-core-extensions.h>

Expand Down Expand Up @@ -104,7 +105,7 @@ static bool print_document(cmark_node *document, writer_format writer,
return false;
}
printf("%s", result);
mem->free(result);
cmark_mem_free(mem, result);

return true;
}
Expand Down
47 changes: 24 additions & 23 deletions extensions/table.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "strikethrough.h"
#include "table.h"
#include "cmark-gfm-core-extensions.h"
#include "mem.h"

// Limit to prevent a malicious input from causing a denial of service.
#define MAX_AUTOCOMPLETED_CELLS 0x80000
Expand Down Expand Up @@ -52,16 +53,16 @@ typedef struct {

static void free_table_cell(cmark_mem *mem, node_cell *cell) {
cmark_strbuf_free((cmark_strbuf *)cell->buf);
mem->free(cell->buf);
cmark_mem_free(mem, cell->buf);
if (cell->cell_data)
mem->free(cell->cell_data);
cmark_mem_free(mem, cell->cell_data);
}

static void free_row_cells(cmark_mem *mem, table_row *row) {
while (row->n_columns > 0) {
free_table_cell(mem, &row->cells[--row->n_columns]);
}
mem->free(row->cells);
cmark_mem_free(mem, row->cells);
row->cells = NULL;
}

Expand All @@ -70,21 +71,21 @@ static void free_table_row(cmark_mem *mem, table_row *row) {
return;

free_row_cells(mem, row);
mem->free(row);
cmark_mem_free(mem, row);
}

static void free_node_table(cmark_mem *mem, void *ptr) {
node_table *t = (node_table *)ptr;
mem->free(t->alignments);
mem->free(t);
cmark_mem_free(mem, t->alignments);
cmark_mem_free(mem, t);
}

static void free_node_table_row(cmark_mem *mem, void *ptr) {
mem->free(ptr);
cmark_mem_free(mem, ptr);
}

static void free_node_table_cell_data(cmark_mem *mem, void *data) {
mem->free(data);
cmark_mem_free(mem, data);
}

static int get_n_table_columns(cmark_node *node) {
Expand Down Expand Up @@ -222,7 +223,7 @@ static int increment_cell_rowspan(cmark_node *node) {

static cmark_strbuf *unescape_pipes(cmark_mem *mem, unsigned char *string, bufsize_t len)
{
cmark_strbuf *res = (cmark_strbuf *)mem->calloc(1, sizeof(cmark_strbuf));
cmark_strbuf *res = CMARK_MALLOC(mem, cmark_strbuf);
bufsize_t r, w;

cmark_strbuf_init(mem, res, len + 1);
Expand Down Expand Up @@ -253,7 +254,7 @@ static node_cell* append_row_cell(cmark_mem *mem, table_row *row) {
return NULL;
}
// 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->cells = CMARK_REALLOC(mem, row->cells, node_cell, 2 * n_columns - 1);
}
row->n_columns = (uint16_t)n_columns;
return &row->cells[n_columns-1];
Expand All @@ -279,7 +280,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
int row_end_offset = 0;
int int_overflow_abort = 0;

row = (table_row *)parser->mem->calloc(1, sizeof(table_row));
row = CMARK_MALLOC(parser->mem, table_row);
row->n_columns = 0;
row->cells = NULL;

Expand All @@ -304,7 +305,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
if (!cell) {
int_overflow_abort = 1;
cmark_strbuf_free(cell_buf);
parser->mem->free(cell_buf);
cmark_mem_free(parser->mem, cell_buf);
break;
}
cell->buf = cell_buf;
Expand All @@ -319,7 +320,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
--cell->start_offset;
++cell->internal_offset;
}
cell->cell_data = (node_cell_data *)parser->mem->calloc(1, sizeof(node_cell_data));
cell->cell_data = CMARK_MALLOC(parser->mem, node_cell_data);

if (parser->options & CMARK_OPT_TABLE_SPANS) {
// Check for a column-spanning cell
Expand Down Expand Up @@ -411,10 +412,10 @@ static void try_inserting_table_header_paragraph(cmark_parser *parser,
cmark_strbuf_trim(paragraph_content);
cmark_node_set_string_content(paragraph, (char *) paragraph_content->ptr);
cmark_strbuf_free(paragraph_content);
parser->mem->free(paragraph_content);
cmark_mem_free(parser->mem, paragraph_content);

if (!cmark_node_insert_before(parent_container, paragraph)) {
parser->mem->free(paragraph);
cmark_mem_free(parser->mem, paragraph);
}
}

Expand Down Expand Up @@ -490,13 +491,13 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
}

cmark_node_set_syntax_extension(parent_container, self);
parent_container->as.opaque = parser->mem->calloc(1, sizeof(node_table));
parent_container->as.opaque = CMARK_MALLOC(parser->mem, node_table);
set_n_table_columns(parent_container, header_row->n_columns);

// allocate alignments based on delimiter_row->n_columns
// since we populate the alignments array based on delimiter_row->cells
uint8_t *alignments =
(uint8_t *)parser->mem->calloc(delimiter_row->n_columns, sizeof(uint8_t));
CMARK_CALLOC(parser->mem, uint8_t, delimiter_row->n_columns);
for (i = 0; i < delimiter_row->n_columns; ++i) {
node_cell *node = &delimiter_row->cells[i];
bool left = node->buf->ptr[0] == ':', right = node->buf->ptr[node->buf->size - 1] == ':';
Expand All @@ -517,7 +518,7 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
table_header->end_column = parent_container->start_column + (int)strlen(parent_string) - 2;
table_header->start_line = table_header->end_line = parent_container->start_line;

table_header->as.opaque = ntr = (node_table_row *)parser->mem->calloc(1, sizeof(node_table_row));
table_header->as.opaque = ntr = CMARK_MALLOC(parser->mem, node_table_row);
ntr->is_header = true;

for (i = 0; i < header_row->n_columns; ++i) {
Expand Down Expand Up @@ -564,7 +565,7 @@ static cmark_node *try_opening_table_row(cmark_syntax_extension *self,
parent_container->start_column);
cmark_node_set_syntax_extension(table_row_block, self);
table_row_block->end_column = parent_container->end_column;
table_row_block->as.opaque = parser->mem->calloc(1, sizeof(node_table_row));
table_row_block->as.opaque = CMARK_MALLOC(parser->mem, node_table_row);

row = row_from_string(self, parser, input + cmark_parser_get_first_nonspace(parser),
len - cmark_parser_get_first_nonspace(parser));
Expand Down Expand Up @@ -1032,11 +1033,11 @@ static void html_render(cmark_syntax_extension *extension,

static void opaque_alloc(cmark_syntax_extension *self, cmark_mem *mem, cmark_node *node) {
if (node->type == CMARK_NODE_TABLE) {
node->as.opaque = mem->calloc(1, sizeof(node_table));
node->as.opaque = CMARK_MALLOC(mem, node_table);
} else if (node->type == CMARK_NODE_TABLE_ROW) {
node->as.opaque = mem->calloc(1, sizeof(node_table_row));
node->as.opaque = CMARK_MALLOC(mem, node_table_row);
} else if (node->type == CMARK_NODE_TABLE_CELL) {
node->as.opaque = mem->calloc(1, sizeof(node_cell_data));
node->as.opaque = CMARK_MALLOC(mem, node_cell_data);
}
}

Expand Down Expand Up @@ -1106,7 +1107,7 @@ int cmark_gfm_extensions_set_table_columns(cmark_node *node, uint16_t n_columns)

CMARK_GFM_EXPORT
int cmark_gfm_extensions_set_table_alignments(cmark_node *node, uint16_t ncols, uint8_t *alignments) {
uint8_t *a = (uint8_t *)cmark_node_mem(node)->calloc(1, ncols);
uint8_t *a = CMARK_CALLOC(cmark_node_mem(node), uint8_t, ncols);
memcpy(a, alignments, ncols);
return set_table_alignments(node, a);
}
Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ add_library(libcmark-gfm
linked_list.c
man.c
map.c
mem.c
node.c
plaintext.c
plugin.c
Expand Down Expand Up @@ -81,6 +82,7 @@ install(FILES
include/inlines.h
include/iterator.h
include/map.h
include/mem.h
include/node.h
include/parser.h
include/plugin.h
Expand Down
2 changes: 1 addition & 1 deletion src/arena.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ static void arena_free(void *ptr) {
/* no-op */
}

cmark_mem CMARK_ARENA_MEM_ALLOCATOR = {arena_calloc, arena_realloc, arena_free};
cmark_mem CMARK_ARENA_MEM_ALLOCATOR = {arena_calloc, arena_realloc, arena_free, 0, 0};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than zero initializing, it might be worth considering:

static void *arena_calloc_typed(...) {
  return arena_calloc(...);
}
...
cmark_mem CMARK_ARENA_MEM_ALLOCATOR = {arena_calloc, arena_realloc, arena_free, &arena_calloc_typed, ...};


cmark_mem *cmark_get_arena_mem_allocator(void) {
return &CMARK_ARENA_MEM_ALLOCATOR;
Expand Down
Loading