Skip to content

Commit ff4f6bf

Browse files
Merge tag '0.29.0.gfm.11' into QuietMisdreavus/gfm.11
rdar://107716414
2 parents 86aeb49 + c8dcdc7 commit ff4f6bf

27 files changed

+373
-224
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ project(cmark-gfm)
44
set(PROJECT_VERSION_MAJOR 0)
55
set(PROJECT_VERSION_MINOR 29)
66
set(PROJECT_VERSION_PATCH 0)
7-
set(PROJECT_VERSION_GFM 6)
7+
set(PROJECT_VERSION_GFM 10)
88
set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.gfm.${PROJECT_VERSION_GFM})
99

1010
include("FindAsan.cmake")

api_test/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,6 +1575,7 @@ int main() {
15751575
int retval;
15761576
test_batch_runner *runner = test_batch_runner_new();
15771577

1578+
cmark_enable_safety_checks(true);
15781579
version(runner);
15791580
constructor(runner);
15801581
accessors(runner);

changelog.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
1+
[0.29.0.gfm.10]
2+
3+
* Fixed polynomial time complexity issue per
4+
https://github.com/github/cmark-gfm/security/advisories/GHSA-r8vr-c48j-fcc5
5+
* Fixed polynomial time complexity issues per
6+
https://github.com/github/cmark-gfm/security/advisories/GHSA-66g8-4hjf-77xh
7+
8+
Note: these changes remove redundant bold tag nesting which may result
9+
in existing rendering tests failing, e.g. rendering "____bold____" to html
10+
will no longer yield "<p><strong><strong>bold</strong></strong></p>".
11+
12+
[0.29.0.gfm.9]
13+
14+
* Cleanup: Use of a private header was cleaned up (#248)
15+
* Cleanup: Man page was updated (#255)
16+
* Cleanup: Warnings for -Wstrict-prototypes were cleaned up (#285)
17+
* Cleanup: We avoid header duplication (#289)
18+
19+
* We now store positioning info for url_match (#201)
20+
* We now expose cmark_parent_footnote_def for non-C renderers (#254)
21+
* Footnote aria-label text now reference the specific footnote backref, and we include a data-footnote-backref-idx attribute so the label can be internationalized in a downstream filter (#307)
22+
123
[0.29.0.gfm.8]
224

325
* We restored backwards compatibility by deprecating the `cmark_init_standard_node_flags()` requirement, which is now a noop (#305)

extensions/CMakeLists.txt

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ include_directories(
1717
${PROJECT_BINARY_DIR}/src
1818
)
1919

20-
include (GenerateExportHeader)
21-
2220
include_directories(include ${CMAKE_CURRENT_BINARY_DIR})
2321

2422
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE} -pg")
@@ -29,6 +27,7 @@ if (CMARK_SHARED)
2927

3028
set_target_properties(${LIBRARY} PROPERTIES
3129
OUTPUT_NAME "cmark-gfm-extensions"
30+
DEFINE_SYMBOL "cmark-gfm"
3231
SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.gfm.${PROJECT_VERSION_GFM}
3332
VERSION ${PROJECT_VERSION})
3433

@@ -38,9 +37,6 @@ if (CMARK_SHARED)
3837
# Avoid name clash between PROGRAM and LIBRARY pdb files.
3938
set_target_properties(${LIBRARY} PROPERTIES PDB_NAME cmark-gfm-extensions_dll)
4039

41-
generate_export_header(${LIBRARY}
42-
BASE_NAME cmark-gfm-extensions)
43-
4440
list(APPEND CMARK_INSTALL ${LIBRARY})
4541
target_link_libraries(${LIBRARY} libcmark-gfm)
4642

@@ -51,6 +47,7 @@ if (CMARK_STATIC)
5147

5248
set_target_properties(${STATICLIBRARY} PROPERTIES
5349
COMPILE_FLAGS "-DCMARK_GFM_STATIC_DEFINE -DCMARK_GFM_EXTENSIONS_STATIC_DEFINE"
50+
DEFINE_SYMBOL "cmark-gfm"
5451
POSITION_INDEPENDENT_CODE ON)
5552

5653
if (MSVC)
@@ -63,11 +60,6 @@ if (CMARK_STATIC)
6360
VERSION ${PROJECT_VERSION})
6461
endif(MSVC)
6562

66-
if (NOT CMARK_SHARED)
67-
generate_export_header(${STATICLIBRARY}
68-
BASE_NAME cmark-gfm-extensions)
69-
endif()
70-
7163
list(APPEND CMARK_INSTALL ${STATICLIBRARY})
7264
endif()
7365

@@ -84,7 +76,6 @@ install(TARGETS ${CMARK_INSTALL}
8476
if (CMARK_SHARED OR CMARK_STATIC)
8577
install(FILES
8678
${CMAKE_CURRENT_SOURCE_DIR}/include/cmark-gfm-core-extensions.h
87-
${CMAKE_CURRENT_SOURCE_DIR}/include/extensions-export.h
8879
DESTINATION include
8980
)
9081

extensions/autolink.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,11 @@ static cmark_node *url_match(cmark_parser *parser, cmark_node *parent,
267267
cmark_node *text = cmark_node_new_with_mem(CMARK_NODE_TEXT, parser->mem);
268268
text->as.literal = url;
269269
cmark_node_append_child(node, text);
270+
271+
node->start_line = text->start_line = node->end_line = text->end_line = cmark_inline_parser_get_line(inline_parser);
272+
273+
node->start_column = text->start_column = max_rewind - rewind;
274+
node->end_column = text->end_column = cmark_inline_parser_get_column(inline_parser) - 1;
270275

271276
return node;
272277
}

extensions/include/cmark-gfm-core-extensions.h

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,40 @@ extern "C" {
66
#endif
77

88
#include "cmark-gfm-extension_api.h"
9-
#include "extensions-export.h"
10-
#include "cmark-gfm_config.h" // for bool
9+
#include "export.h"
10+
#include <stdbool.h>
1111
#include <stdint.h>
1212

13-
CMARK_GFM_EXTENSIONS_EXPORT
13+
CMARK_GFM_EXPORT
1414
void cmark_gfm_core_extensions_ensure_registered(void);
1515

16-
CMARK_GFM_EXTENSIONS_EXPORT
16+
CMARK_GFM_EXPORT
1717
uint16_t cmark_gfm_extensions_get_table_columns(cmark_node *node);
1818

1919
/** Sets the number of columns for the table, returning 1 on success and 0 on error.
2020
*/
21-
CMARK_GFM_EXTENSIONS_EXPORT
21+
CMARK_GFM_EXPORT
2222
int cmark_gfm_extensions_set_table_columns(cmark_node *node, uint16_t n_columns);
2323

24-
CMARK_GFM_EXTENSIONS_EXPORT
24+
CMARK_GFM_EXPORT
2525
uint8_t *cmark_gfm_extensions_get_table_alignments(cmark_node *node);
2626

2727
/** Sets the alignments for the table, returning 1 on success and 0 on error.
2828
*/
29-
CMARK_GFM_EXTENSIONS_EXPORT
29+
CMARK_GFM_EXPORT
3030
int cmark_gfm_extensions_set_table_alignments(cmark_node *node, uint16_t ncols, uint8_t *alignments);
3131

32-
CMARK_GFM_EXTENSIONS_EXPORT
32+
CMARK_GFM_EXPORT
3333
int cmark_gfm_extensions_get_table_row_is_header(cmark_node *node);
3434

3535
/** Sets the column span for the table cell, returning 1 on success and 0 on error.
3636
*/
37-
CMARK_GFM_EXTENSIONS_EXPORT
37+
CMARK_GFM_EXPORT
3838
int cmark_gfm_extensions_set_table_cell_colspan(cmark_node *node, unsigned colspan);
3939

4040
/** Sets the row span for the table cell, returning 1 on success and 0 on error.
4141
*/
42-
CMARK_GFM_EXTENSIONS_EXPORT
42+
CMARK_GFM_EXPORT
4343
int cmark_gfm_extensions_set_table_cell_rowspan(cmark_node *node, unsigned rowspan);
4444

4545
/**
@@ -50,7 +50,7 @@ int cmark_gfm_extensions_set_table_cell_rowspan(cmark_node *node, unsigned rowsp
5050
5151
Column span is only parsed when \c CMARK_OPT_TABLE_SPANS is set.
5252
*/
53-
CMARK_GFM_EXTENSIONS_EXPORT
53+
CMARK_GFM_EXPORT
5454
unsigned cmark_gfm_extensions_get_table_cell_colspan(cmark_node *node);
5555

5656
/**
@@ -61,22 +61,22 @@ unsigned cmark_gfm_extensions_get_table_cell_colspan(cmark_node *node);
6161
6262
Row span is only parsed when \c CMARK_OPT_TABLE_SPANS is set.
6363
*/
64-
CMARK_GFM_EXTENSIONS_EXPORT
64+
CMARK_GFM_EXPORT
6565
unsigned cmark_gfm_extensions_get_table_cell_rowspan(cmark_node *node);
6666

6767
/** Sets whether the node is a table header row, returning 1 on success and 0 on error.
6868
*/
69-
CMARK_GFM_EXTENSIONS_EXPORT
69+
CMARK_GFM_EXPORT
7070
int cmark_gfm_extensions_set_table_row_is_header(cmark_node *node, int is_header);
7171

72-
CMARK_GFM_EXTENSIONS_EXPORT
72+
CMARK_GFM_EXPORT
7373
bool cmark_gfm_extensions_get_tasklist_item_checked(cmark_node *node);
7474
/* For backwards compatibility */
7575
#define cmark_gfm_extensions_tasklist_is_checked cmark_gfm_extensions_get_tasklist_item_checked
7676

7777
/** Sets whether a tasklist item is "checked" (completed), returning 1 on success and 0 on error.
7878
*/
79-
CMARK_GFM_EXTENSIONS_EXPORT
79+
CMARK_GFM_EXPORT
8080
int cmark_gfm_extensions_set_tasklist_item_checked(cmark_node *node, bool is_checked);
8181

8282
#ifdef __cplusplus

extensions/include/extensions-export.h

Lines changed: 0 additions & 60 deletions
This file was deleted.

fuzz/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ macro(fuzzer name)
1919
endmacro()
2020

2121
fuzzer(fuzz_quadratic)
22+
fuzzer(fuzz_quadratic_brackets)

fuzz/fuzz_quadratic.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,13 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
7575

7676
cmark_parser_feed(parser, markdown, markdown_size);
7777
cmark_node *doc = cmark_parser_finish(parser);
78-
78+
7979
free(cmark_render_html(doc, fuzz_config.options, NULL));
80+
free(cmark_render_xml(doc, fuzz_config.options));
81+
free(cmark_render_man(doc, fuzz_config.options, 80));
82+
free(cmark_render_commonmark(doc, fuzz_config.options, 80));
83+
free(cmark_render_plaintext(doc, fuzz_config.options, 80));
84+
free(cmark_render_latex(doc, fuzz_config.options, 80));
8085

8186
cmark_node_free(doc);
8287
cmark_parser_free(parser);

fuzz/fuzz_quadratic_brackets.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#include <stdint.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include "cmark-gfm.h"
5+
#include "cmark-gfm-core-extensions.h"
6+
#include <sys/types.h>
7+
#include <sys/stat.h>
8+
#include <fcntl.h>
9+
#include <unistd.h>
10+
11+
const char *extension_names[] = {
12+
"autolink",
13+
"strikethrough",
14+
"table",
15+
"tagfilter",
16+
NULL,
17+
};
18+
19+
int LLVMFuzzerInitialize(int *argc, char ***argv) {
20+
cmark_gfm_core_extensions_ensure_registered();
21+
return 0;
22+
}
23+
24+
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
25+
struct __attribute__((packed)) {
26+
int options;
27+
int width;
28+
uint8_t startlen;
29+
uint8_t openlen;
30+
uint8_t middlelen;
31+
uint8_t closelen;
32+
} fuzz_config;
33+
34+
if (size >= sizeof(fuzz_config)) {
35+
/* The beginning of `data` is treated as fuzzer configuration */
36+
memcpy(&fuzz_config, data, sizeof(fuzz_config));
37+
38+
/* Test options that are used by GitHub. */
39+
fuzz_config.options = CMARK_OPT_UNSAFE | CMARK_OPT_FOOTNOTES | CMARK_OPT_GITHUB_PRE_LANG | CMARK_OPT_HARDBREAKS;
40+
fuzz_config.openlen = fuzz_config.openlen & 0x7;
41+
fuzz_config.middlelen = fuzz_config.middlelen & 0x7;
42+
fuzz_config.closelen = fuzz_config.closelen & 0x7;
43+
44+
/* Remainder of input is the markdown */
45+
const char *markdown0 = (const char *)(data + sizeof(fuzz_config));
46+
const size_t markdown_size0 = size - sizeof(fuzz_config);
47+
char markdown[0x80000];
48+
if (markdown_size0 <= sizeof(markdown)) {
49+
size_t markdown_size = 0;
50+
const size_t componentslen = fuzz_config.startlen + fuzz_config.openlen + fuzz_config.middlelen + fuzz_config.closelen;
51+
if (componentslen <= markdown_size0) {
52+
size_t offset = 0;
53+
const size_t endlen = markdown_size0 - componentslen;
54+
memcpy(&markdown[markdown_size], &markdown0[offset], fuzz_config.startlen);
55+
markdown_size += fuzz_config.startlen;
56+
offset += fuzz_config.startlen;
57+
58+
if (0 < fuzz_config.openlen) {
59+
while (markdown_size + fuzz_config.openlen <= sizeof(markdown)/2) {
60+
memcpy(&markdown[markdown_size], &markdown0[offset],
61+
fuzz_config.openlen);
62+
markdown_size += fuzz_config.openlen;
63+
}
64+
offset += fuzz_config.openlen;
65+
}
66+
memcpy(&markdown[markdown_size], &markdown0[offset],
67+
fuzz_config.middlelen);
68+
markdown_size += fuzz_config.middlelen;
69+
offset += fuzz_config.middlelen;
70+
if (0 < fuzz_config.closelen) {
71+
while (markdown_size + fuzz_config.closelen + endlen <= sizeof(markdown)) {
72+
memcpy(&markdown[markdown_size], &markdown0[offset],
73+
fuzz_config.closelen);
74+
markdown_size += fuzz_config.closelen;
75+
}
76+
offset += fuzz_config.closelen;
77+
}
78+
if (markdown_size + endlen <= sizeof(markdown)) {
79+
memcpy(&markdown[markdown_size], &markdown0[offset],
80+
endlen);
81+
markdown_size += endlen;
82+
}
83+
} else {
84+
markdown_size = markdown_size0;
85+
memcpy(markdown, markdown0, markdown_size);
86+
}
87+
88+
cmark_parser *parser = cmark_parser_new(fuzz_config.options);
89+
90+
for (const char **it = extension_names; *it; ++it) {
91+
const char *extension_name = *it;
92+
cmark_syntax_extension *syntax_extension = cmark_find_syntax_extension(extension_name);
93+
if (!syntax_extension) {
94+
fprintf(stderr, "%s is not a valid syntax extension\n", extension_name);
95+
abort();
96+
}
97+
cmark_parser_attach_syntax_extension(parser, syntax_extension);
98+
}
99+
100+
cmark_parser_feed(parser, markdown, markdown_size);
101+
cmark_node *doc = cmark_parser_finish(parser);
102+
103+
free(cmark_render_html(doc, fuzz_config.options, NULL));
104+
105+
cmark_node_free(doc);
106+
cmark_parser_free(parser);
107+
}
108+
}
109+
return 0;
110+
}

0 commit comments

Comments
 (0)