|
26 | 26 | #include "md4c.h"
|
27 | 27 |
|
28 | 28 | #include <limits.h>
|
| 29 | +#include <stdint.h> |
29 | 30 | #include <stdio.h>
|
30 | 31 | #include <stdlib.h>
|
31 | 32 | #include <string.h>
|
|
143 | 144 | #define SZ MD_SIZE
|
144 | 145 | #define OFF MD_OFFSET
|
145 | 146 |
|
| 147 | +#define SZ_MAX (sizeof(SZ) == 8 ? UINT64_MAX : UINT32_MAX) |
| 148 | +#define OFF_MAX (sizeof(OFF) == 8 ? UINT64_MAX : UINT32_MAX) |
| 149 | + |
146 | 150 | typedef struct MD_MARK_tag MD_MARK;
|
147 | 151 | typedef struct MD_BLOCK_tag MD_BLOCK;
|
148 | 152 | typedef struct MD_CONTAINER_tag MD_CONTAINER;
|
@@ -180,6 +184,7 @@ struct MD_CTX_tag {
|
180 | 184 | int alloc_ref_defs;
|
181 | 185 | void** ref_def_hashtable;
|
182 | 186 | int ref_def_hashtable_size;
|
| 187 | + SZ max_ref_def_output; |
183 | 188 |
|
184 | 189 | /* Stack of inline/span markers.
|
185 | 190 | * This is only used for parsing a single block contents but by storing it
|
@@ -2283,11 +2288,14 @@ md_is_link_reference(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines,
|
2283 | 2288 | int is_multiline;
|
2284 | 2289 | CHAR* label;
|
2285 | 2290 | SZ label_size;
|
2286 |
| - int ret; |
| 2291 | + int ret = FALSE; |
2287 | 2292 |
|
2288 | 2293 | MD_ASSERT(CH(beg) == _T('[') || CH(beg) == _T('!'));
|
2289 | 2294 | MD_ASSERT(CH(end-1) == _T(']'));
|
2290 | 2295 |
|
| 2296 | + if(ctx->max_ref_def_output == 0) |
| 2297 | + return FALSE; |
| 2298 | + |
2291 | 2299 | beg += (CH(beg) == _T('!') ? 2 : 1);
|
2292 | 2300 | end--;
|
2293 | 2301 |
|
@@ -2315,7 +2323,17 @@ md_is_link_reference(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines,
|
2315 | 2323 | if(is_multiline)
|
2316 | 2324 | free(label);
|
2317 | 2325 |
|
2318 |
| - ret = (def != NULL); |
| 2326 | + if(def != NULL) { |
| 2327 | + /* See https://github.com/mity/md4c/issues/238 */ |
| 2328 | + MD_SIZE output_size_estimation = def->label_size + def->title_size + def->dest_end - def->dest_beg; |
| 2329 | + if(output_size_estimation < ctx->max_ref_def_output) { |
| 2330 | + ctx->max_ref_def_output -= output_size_estimation; |
| 2331 | + ret = TRUE; |
| 2332 | + } else { |
| 2333 | + MD_LOG("Too many link reference definition instantiations."); |
| 2334 | + ctx->max_ref_def_output = 0; |
| 2335 | + } |
| 2336 | + } |
2319 | 2337 |
|
2320 | 2338 | abort:
|
2321 | 2339 | return ret;
|
@@ -6470,6 +6488,7 @@ md_parse(const MD_CHAR* text, MD_SIZE size, const MD_PARSER* parser, void* userd
|
6470 | 6488 | ctx.code_indent_offset = (ctx.parser.flags & MD_FLAG_NOINDENTEDCODEBLOCKS) ? (OFF)(-1) : 4;
|
6471 | 6489 | md_build_mark_char_map(&ctx);
|
6472 | 6490 | ctx.doc_ends_with_newline = (size > 0 && ISNEWLINE_(text[size-1]));
|
| 6491 | + ctx.max_ref_def_output = MIN(MIN(16 * (uint64_t)size, (uint64_t)(1024 * 1024)), (uint64_t)SZ_MAX); |
6473 | 6492 |
|
6474 | 6493 | /* Reset all mark stacks and lists. */
|
6475 | 6494 | for(i = 0; i < (int) SIZEOF_ARRAY(ctx.opener_stacks); i++)
|
|
0 commit comments