#include "char.h"
#include "d_string.h"
#include "html.h"
-#include "libMultiMarkdown.h"
#include "i18n.h"
+#include "libMultiMarkdown.h"
#include "parser.h"
#include "token.h"
#include "scanners.h"
void mmd_export_token_tree_html(DString * out, const char * source, token * t, size_t offset, scratch_pad * scratch) {
+
+ // Prevent stack overflow with "dangerous" input causing extreme recursion
+ if (scratch->recurse_depth == kMaxExportRecursiveDepth) {
+ return;
+ }
+
+ scratch->recurse_depth++;
+
while (t != NULL) {
if (scratch->skip_token) {
scratch->skip_token--;
t = t->next;
}
+
+ scratch->recurse_depth--;
}
e->extensions = extensions;
+ e->recurse_depth = 0;
+
e->allow_meta = (extensions & EXT_COMPATIBILITY) ? false : true;
e->language = LC_EN;
/// Parse token tree
void mmd_parse_token_chain(mmd_engine * e, token * chain) {
+ if (e->recurse_depth == kMaxParseRecursiveDepth)
+ return;
+
+ e->recurse_depth++;
+
void* pParser = ParseAlloc (malloc); // Create a parser (for lemon)
token * walker = chain->child; // Walk the existing tree
token * remainder; // Hold unparsed tail of chain
e->root = NULL;
ParseFree(pParser, free);
+
+ e->recurse_depth--;
}
case BLOCK_H5:
case BLOCK_H6:
case BLOCK_PARA:
- token_pairs_match_pairs_inside_token(block, e, s);
+ token_pairs_match_pairs_inside_token(block, e, s, 0);
break;
case DOC_START_TOKEN:
case BLOCK_LIST_BULLETED:
break;
case BLOCK_LIST_ITEM:
case BLOCK_LIST_ITEM_TIGHT:
- token_pairs_match_pairs_inside_token(block, e, s);
+ token_pairs_match_pairs_inside_token(block, e, s, 0);
mmd_pair_tokens_in_chain(block->child, e, s);
break;
case LINE_TABLE:
case BLOCK_TABLE:
// TODO: Need to parse into cells first
- token_pairs_match_pairs_inside_token(block, e, s);
+ token_pairs_match_pairs_inside_token(block, e, s, 0);
mmd_pair_tokens_in_chain(block->child, e, s);
break;
case BLOCK_EMPTY:
// This avoids allocating/freeing one for each iteration.
stack * pair_stack = stack_new(0);
+
mmd_pair_tokens_in_block(doc, e->pairings1, pair_stack);
mmd_pair_tokens_in_block(doc, e->pairings2, pair_stack);
mmd_pair_tokens_in_block(doc, e->pairings3, pair_stack);
#include "token.h"
#include "token_pairs.h"
+#define kMaxParseRecursiveDepth 1000 //!< Maximum recursion depth when parsing -- to prevent stack overflow with "pathologic" input
+
+
struct mmd_engine {
DString * dstr;
token * root;
unsigned long extensions;
+ unsigned short recurse_depth;
bool allow_meta;
/// Search a token's childen for matching pairs
-void token_pairs_match_pairs_inside_token(token * parent, token_pair_engine * e, stack * s) {
+void token_pairs_match_pairs_inside_token(token * parent, token_pair_engine * e, stack * s, unsigned short depth) {
+
+ // Avoid stack overflow in "pathologic" input
+ if (depth == kMaxPairRecursiveDepth)
+ return;
// Walk the child chain
token * walker = parent->child;
while (walker != NULL) {
if (walker->child) {
- token_pairs_match_pairs_inside_token(walker, e, s);
+ token_pairs_match_pairs_inside_token(walker, e, s, depth + 1);
}
// Is this a closer?
#include "CuTest.h"
#endif
-#define kMaxTokenTypes 200 // This needs to be larger than the largest token type being used
-#define kLargeStackThreshold 1000 // Avoid unnecessary searches of large stacks
+#define kMaxTokenTypes 200 //!< This needs to be larger than the largest token type being used
+#define kLargeStackThreshold 1000 //!< Avoid unnecessary searches of large stacks
+#define kMaxPairRecursiveDepth 1000 //!< Maximum recursion depth to traverse when pairing tokens -- to prevent stack overflow with "pathologic" input
/// Store information about which tokens can be paired, and what actions to take when
void token_pairs_match_pairs_inside_token(
token * parent, //!< Which tokens should we search for pairs
token_pair_engine * e, //!< Token pair engine to be used for matching
- stack * s //!< Pointer to a stack to use for pairing tokens
+ stack * s, //!< Pointer to a stack to use for pairing tokens
+ unsigned short depth //!< Keep track of recursion depth
);
p->header_stack = e->header_stack;
+ p->recurse_depth = 0;
+
// Store links in a hash for rapid retrieval when exporting
p->link_hash = NULL;
link * l;
#include "uthash.h"
+#define kMaxExportRecursiveDepth 1000 //!< Maximum recursion depth when exporting token tree -- to prevent stack overflow with "pathologic" input
+
+
typedef struct {
struct link * link_hash;
struct meta * meta_hash;
short quotes_lang;
stack * header_stack;
+
+ short recurse_depth;
char _PADDING[4]; //!< pad struct for alignment