Fossil SCM

Attempt to limit the depth of recursion in markdown formatting.

drh 2019-09-24 18:04 trunk
Commit a5835cac3b63d2d4fe5bfffcbe8bc99b64781124a87748c054eef2270cbf1cac
1 file changed +16 -10
+16 -10
--- src/markdown.c
+++ src/markdown.c
@@ -153,10 +153,11 @@
153153
/* render -- structure containing one particular render */
154154
struct render {
155155
struct mkd_renderer make;
156156
struct Blob refs;
157157
char_trigger active_char[256];
158
+ int iDepth; /* Depth of recursion */
158159
int nBlobCache; /* Number of entries in aBlobCache */
159160
struct Blob *aBlobCache[20]; /* Cache of Blobs available for reuse */
160161
};
161162
162163
@@ -299,14 +300,20 @@
299300
count(block_tags),
300301
sizeof block_tags[0],
301302
cmp_html_tag);
302303
}
303304
305
+/* return true if recursion has gone too deep */
306
+static int too_deep(struct render *rndr){
307
+ return rndr->iDepth>200;
308
+}
304309
305
-/* get a new working buffer from the cache or create one */
310
+/* get a new working buffer from the cache or create one. return NULL
311
+** if failIfDeep is true and the depth of recursion has gone too deep. */
306312
static struct Blob *new_work_buffer(struct render *rndr){
307313
struct Blob *ret;
314
+ rndr->iDepth++;
308315
if( rndr->nBlobCache ){
309316
ret = rndr->aBlobCache[--rndr->nBlobCache];
310317
}else{
311318
ret = fossil_malloc(sizeof(*ret));
312319
}
@@ -316,10 +323,11 @@
316323
317324
318325
/* release the given working buffer back to the cache */
319326
static void release_work_buffer(struct render *rndr, struct Blob *buf){
320327
if( !buf ) return;
328
+ rndr->iDepth--;
321329
blob_reset(buf);
322330
if( rndr->nBlobCache < sizeof(rndr->aBlobCache)/sizeof(rndr->aBlobCache[0]) ){
323331
rndr->aBlobCache[rndr->nBlobCache++] = buf;
324332
}else{
325333
fossil_free(buf);
@@ -556,13 +564,13 @@
556564
}
557565
if( data[i]==c
558566
&& data[i-1]!=' '
559567
&& data[i-1]!='\t'
560568
&& data[i-1]!='\n'
569
+ && !too_deep(rndr)
561570
){
562571
work = new_work_buffer(rndr);
563
- if( !work ) return 0;
564572
parse_inline(work, rndr, data, i);
565573
r = rndr->make.emphasis(ob, work, c, rndr->make.opaque);
566574
release_work_buffer(rndr, work);
567575
return r ? i+1 : 0;
568576
}
@@ -594,13 +602,13 @@
594602
&& data[i+1]==c
595603
&& i
596604
&& data[i-1]!=' '
597605
&& data[i-1]!='\t'
598606
&& data[i-1]!='\n'
607
+ && !too_deep(rndr)
599608
){
600609
work = new_work_buffer(rndr);
601
- if( !work ) return 0;
602610
parse_inline(work, rndr, data, i);
603611
r = rndr->make.double_emphasis(ob, work, c, rndr->make.opaque);
604612
release_work_buffer(rndr, work);
605613
return r ? i+2 : 0;
606614
}
@@ -634,14 +642,14 @@
634642
635643
if( i+2<size
636644
&& data[i+1]==c
637645
&& data[i+2] == c
638646
&& rndr->make.triple_emphasis
647
+ && !too_deep(rndr)
639648
){
640649
/* triple symbol found */
641650
struct Blob *work = new_work_buffer(rndr);
642
- if( !work ) return 0;
643651
parse_inline(work, rndr, data, i);
644652
r = rndr->make.triple_emphasis(ob, work, c, rndr->make.opaque);
645653
release_work_buffer(rndr, work);
646654
return r ? i+3 : 0;
647655
}else if( i+1<size && data[i+1]==c ){
@@ -990,14 +998,13 @@
990998
/* skip any amount of whitespace or newline */
991999
/* (this is much more laxist than original markdown syntax) */
9921000
while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; }
9931001
9941002
/* allocate temporary buffers to store content, link and title */
1003
+ title = new_work_buffer(rndr);
9951004
content = new_work_buffer(rndr);
9961005
link = new_work_buffer(rndr);
997
- title = new_work_buffer(rndr);
998
- if( !title ) return 0;
9991006
ret = 0; /* error if we don't get to the callback */
10001007
10011008
/* inline style link */
10021009
if( i<size && data[i]=='(' ){
10031010
size_t span_end = i;
@@ -1384,11 +1391,10 @@
13841391
char *data,
13851392
size_t size
13861393
){
13871394
size_t beg, end, pre;
13881395
struct Blob *work = new_work_buffer(rndr);
1389
- if( !work ) work = ob;
13901396
13911397
beg = 0;
13921398
while( beg<size ){
13931399
for(end=beg+1; end<size && data[end-1]!='\n'; end++);
13941400
pre = prefix_code(data+beg, end-beg);
@@ -1893,13 +1899,11 @@
18931899
if( i<size && data[i]=='\n' ){
18941900
align_size++;
18951901
18961902
/* render the header row */
18971903
head = new_work_buffer(rndr);
1898
- if( head ){
1899
- parse_table_row(head, rndr, data, head_end, 0, 0, MKD_CELL_HEAD);
1900
- }
1904
+ parse_table_row(head, rndr, data, head_end, 0, 0, MKD_CELL_HEAD);
19011905
19021906
/* parse alignments if provided */
19031907
if( col && (aligns=fossil_malloc(align_size * sizeof *aligns))!=0 ){
19041908
for(i=0; i<align_size; i++) aligns[i] = 0;
19051909
col = 0;
@@ -2146,10 +2150,11 @@
21462150
21472151
/* filling the render structure */
21482152
if( !rndrer ) return;
21492153
rndr.make = *rndrer;
21502154
rndr.nBlobCache = 0;
2155
+ rndr.iDepth = 0;
21512156
rndr.refs = empty_blob;
21522157
for(i=0; i<256; i++) rndr.active_char[i] = 0;
21532158
if( (rndr.make.emphasis
21542159
|| rndr.make.double_emphasis
21552160
|| rndr.make.triple_emphasis)
@@ -2204,10 +2209,11 @@
22042209
if( rndr.make.prolog ) rndr.make.prolog(ob, rndr.make.opaque);
22052210
parse_block(ob, &rndr, blob_buffer(&text), blob_size(&text));
22062211
if( rndr.make.epilog ) rndr.make.epilog(ob, rndr.make.opaque);
22072212
22082213
/* clean-up */
2214
+ assert( rndr.iDepth==0 );
22092215
blob_reset(&text);
22102216
lr = (struct link_ref *)blob_buffer(&rndr.refs);
22112217
end = blob_size(&rndr.refs)/sizeof(struct link_ref);
22122218
for(i=0; i<end; i++){
22132219
blob_reset(&lr[i].id);
22142220
--- src/markdown.c
+++ src/markdown.c
@@ -153,10 +153,11 @@
153 /* render -- structure containing one particular render */
154 struct render {
155 struct mkd_renderer make;
156 struct Blob refs;
157 char_trigger active_char[256];
 
158 int nBlobCache; /* Number of entries in aBlobCache */
159 struct Blob *aBlobCache[20]; /* Cache of Blobs available for reuse */
160 };
161
162
@@ -299,14 +300,20 @@
299 count(block_tags),
300 sizeof block_tags[0],
301 cmp_html_tag);
302 }
303
 
 
 
 
304
305 /* get a new working buffer from the cache or create one */
 
306 static struct Blob *new_work_buffer(struct render *rndr){
307 struct Blob *ret;
 
308 if( rndr->nBlobCache ){
309 ret = rndr->aBlobCache[--rndr->nBlobCache];
310 }else{
311 ret = fossil_malloc(sizeof(*ret));
312 }
@@ -316,10 +323,11 @@
316
317
318 /* release the given working buffer back to the cache */
319 static void release_work_buffer(struct render *rndr, struct Blob *buf){
320 if( !buf ) return;
 
321 blob_reset(buf);
322 if( rndr->nBlobCache < sizeof(rndr->aBlobCache)/sizeof(rndr->aBlobCache[0]) ){
323 rndr->aBlobCache[rndr->nBlobCache++] = buf;
324 }else{
325 fossil_free(buf);
@@ -556,13 +564,13 @@
556 }
557 if( data[i]==c
558 && data[i-1]!=' '
559 && data[i-1]!='\t'
560 && data[i-1]!='\n'
 
561 ){
562 work = new_work_buffer(rndr);
563 if( !work ) return 0;
564 parse_inline(work, rndr, data, i);
565 r = rndr->make.emphasis(ob, work, c, rndr->make.opaque);
566 release_work_buffer(rndr, work);
567 return r ? i+1 : 0;
568 }
@@ -594,13 +602,13 @@
594 && data[i+1]==c
595 && i
596 && data[i-1]!=' '
597 && data[i-1]!='\t'
598 && data[i-1]!='\n'
 
599 ){
600 work = new_work_buffer(rndr);
601 if( !work ) return 0;
602 parse_inline(work, rndr, data, i);
603 r = rndr->make.double_emphasis(ob, work, c, rndr->make.opaque);
604 release_work_buffer(rndr, work);
605 return r ? i+2 : 0;
606 }
@@ -634,14 +642,14 @@
634
635 if( i+2<size
636 && data[i+1]==c
637 && data[i+2] == c
638 && rndr->make.triple_emphasis
 
639 ){
640 /* triple symbol found */
641 struct Blob *work = new_work_buffer(rndr);
642 if( !work ) return 0;
643 parse_inline(work, rndr, data, i);
644 r = rndr->make.triple_emphasis(ob, work, c, rndr->make.opaque);
645 release_work_buffer(rndr, work);
646 return r ? i+3 : 0;
647 }else if( i+1<size && data[i+1]==c ){
@@ -990,14 +998,13 @@
990 /* skip any amount of whitespace or newline */
991 /* (this is much more laxist than original markdown syntax) */
992 while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; }
993
994 /* allocate temporary buffers to store content, link and title */
 
995 content = new_work_buffer(rndr);
996 link = new_work_buffer(rndr);
997 title = new_work_buffer(rndr);
998 if( !title ) return 0;
999 ret = 0; /* error if we don't get to the callback */
1000
1001 /* inline style link */
1002 if( i<size && data[i]=='(' ){
1003 size_t span_end = i;
@@ -1384,11 +1391,10 @@
1384 char *data,
1385 size_t size
1386 ){
1387 size_t beg, end, pre;
1388 struct Blob *work = new_work_buffer(rndr);
1389 if( !work ) work = ob;
1390
1391 beg = 0;
1392 while( beg<size ){
1393 for(end=beg+1; end<size && data[end-1]!='\n'; end++);
1394 pre = prefix_code(data+beg, end-beg);
@@ -1893,13 +1899,11 @@
1893 if( i<size && data[i]=='\n' ){
1894 align_size++;
1895
1896 /* render the header row */
1897 head = new_work_buffer(rndr);
1898 if( head ){
1899 parse_table_row(head, rndr, data, head_end, 0, 0, MKD_CELL_HEAD);
1900 }
1901
1902 /* parse alignments if provided */
1903 if( col && (aligns=fossil_malloc(align_size * sizeof *aligns))!=0 ){
1904 for(i=0; i<align_size; i++) aligns[i] = 0;
1905 col = 0;
@@ -2146,10 +2150,11 @@
2146
2147 /* filling the render structure */
2148 if( !rndrer ) return;
2149 rndr.make = *rndrer;
2150 rndr.nBlobCache = 0;
 
2151 rndr.refs = empty_blob;
2152 for(i=0; i<256; i++) rndr.active_char[i] = 0;
2153 if( (rndr.make.emphasis
2154 || rndr.make.double_emphasis
2155 || rndr.make.triple_emphasis)
@@ -2204,10 +2209,11 @@
2204 if( rndr.make.prolog ) rndr.make.prolog(ob, rndr.make.opaque);
2205 parse_block(ob, &rndr, blob_buffer(&text), blob_size(&text));
2206 if( rndr.make.epilog ) rndr.make.epilog(ob, rndr.make.opaque);
2207
2208 /* clean-up */
 
2209 blob_reset(&text);
2210 lr = (struct link_ref *)blob_buffer(&rndr.refs);
2211 end = blob_size(&rndr.refs)/sizeof(struct link_ref);
2212 for(i=0; i<end; i++){
2213 blob_reset(&lr[i].id);
2214
--- src/markdown.c
+++ src/markdown.c
@@ -153,10 +153,11 @@
153 /* render -- structure containing one particular render */
154 struct render {
155 struct mkd_renderer make;
156 struct Blob refs;
157 char_trigger active_char[256];
158 int iDepth; /* Depth of recursion */
159 int nBlobCache; /* Number of entries in aBlobCache */
160 struct Blob *aBlobCache[20]; /* Cache of Blobs available for reuse */
161 };
162
163
@@ -299,14 +300,20 @@
300 count(block_tags),
301 sizeof block_tags[0],
302 cmp_html_tag);
303 }
304
305 /* return true if recursion has gone too deep */
306 static int too_deep(struct render *rndr){
307 return rndr->iDepth>200;
308 }
309
310 /* get a new working buffer from the cache or create one. return NULL
311 ** if failIfDeep is true and the depth of recursion has gone too deep. */
312 static struct Blob *new_work_buffer(struct render *rndr){
313 struct Blob *ret;
314 rndr->iDepth++;
315 if( rndr->nBlobCache ){
316 ret = rndr->aBlobCache[--rndr->nBlobCache];
317 }else{
318 ret = fossil_malloc(sizeof(*ret));
319 }
@@ -316,10 +323,11 @@
323
324
325 /* release the given working buffer back to the cache */
326 static void release_work_buffer(struct render *rndr, struct Blob *buf){
327 if( !buf ) return;
328 rndr->iDepth--;
329 blob_reset(buf);
330 if( rndr->nBlobCache < sizeof(rndr->aBlobCache)/sizeof(rndr->aBlobCache[0]) ){
331 rndr->aBlobCache[rndr->nBlobCache++] = buf;
332 }else{
333 fossil_free(buf);
@@ -556,13 +564,13 @@
564 }
565 if( data[i]==c
566 && data[i-1]!=' '
567 && data[i-1]!='\t'
568 && data[i-1]!='\n'
569 && !too_deep(rndr)
570 ){
571 work = new_work_buffer(rndr);
 
572 parse_inline(work, rndr, data, i);
573 r = rndr->make.emphasis(ob, work, c, rndr->make.opaque);
574 release_work_buffer(rndr, work);
575 return r ? i+1 : 0;
576 }
@@ -594,13 +602,13 @@
602 && data[i+1]==c
603 && i
604 && data[i-1]!=' '
605 && data[i-1]!='\t'
606 && data[i-1]!='\n'
607 && !too_deep(rndr)
608 ){
609 work = new_work_buffer(rndr);
 
610 parse_inline(work, rndr, data, i);
611 r = rndr->make.double_emphasis(ob, work, c, rndr->make.opaque);
612 release_work_buffer(rndr, work);
613 return r ? i+2 : 0;
614 }
@@ -634,14 +642,14 @@
642
643 if( i+2<size
644 && data[i+1]==c
645 && data[i+2] == c
646 && rndr->make.triple_emphasis
647 && !too_deep(rndr)
648 ){
649 /* triple symbol found */
650 struct Blob *work = new_work_buffer(rndr);
 
651 parse_inline(work, rndr, data, i);
652 r = rndr->make.triple_emphasis(ob, work, c, rndr->make.opaque);
653 release_work_buffer(rndr, work);
654 return r ? i+3 : 0;
655 }else if( i+1<size && data[i+1]==c ){
@@ -990,14 +998,13 @@
998 /* skip any amount of whitespace or newline */
999 /* (this is much more laxist than original markdown syntax) */
1000 while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; }
1001
1002 /* allocate temporary buffers to store content, link and title */
1003 title = new_work_buffer(rndr);
1004 content = new_work_buffer(rndr);
1005 link = new_work_buffer(rndr);
 
 
1006 ret = 0; /* error if we don't get to the callback */
1007
1008 /* inline style link */
1009 if( i<size && data[i]=='(' ){
1010 size_t span_end = i;
@@ -1384,11 +1391,10 @@
1391 char *data,
1392 size_t size
1393 ){
1394 size_t beg, end, pre;
1395 struct Blob *work = new_work_buffer(rndr);
 
1396
1397 beg = 0;
1398 while( beg<size ){
1399 for(end=beg+1; end<size && data[end-1]!='\n'; end++);
1400 pre = prefix_code(data+beg, end-beg);
@@ -1893,13 +1899,11 @@
1899 if( i<size && data[i]=='\n' ){
1900 align_size++;
1901
1902 /* render the header row */
1903 head = new_work_buffer(rndr);
1904 parse_table_row(head, rndr, data, head_end, 0, 0, MKD_CELL_HEAD);
 
 
1905
1906 /* parse alignments if provided */
1907 if( col && (aligns=fossil_malloc(align_size * sizeof *aligns))!=0 ){
1908 for(i=0; i<align_size; i++) aligns[i] = 0;
1909 col = 0;
@@ -2146,10 +2150,11 @@
2150
2151 /* filling the render structure */
2152 if( !rndrer ) return;
2153 rndr.make = *rndrer;
2154 rndr.nBlobCache = 0;
2155 rndr.iDepth = 0;
2156 rndr.refs = empty_blob;
2157 for(i=0; i<256; i++) rndr.active_char[i] = 0;
2158 if( (rndr.make.emphasis
2159 || rndr.make.double_emphasis
2160 || rndr.make.triple_emphasis)
@@ -2204,10 +2209,11 @@
2209 if( rndr.make.prolog ) rndr.make.prolog(ob, rndr.make.opaque);
2210 parse_block(ob, &rndr, blob_buffer(&text), blob_size(&text));
2211 if( rndr.make.epilog ) rndr.make.epilog(ob, rndr.make.opaque);
2212
2213 /* clean-up */
2214 assert( rndr.iDepth==0 );
2215 blob_reset(&text);
2216 lr = (struct link_ref *)blob_buffer(&rndr.refs);
2217 end = blob_size(&rndr.refs)/sizeof(struct link_ref);
2218 for(i=0; i<end; i++){
2219 blob_reset(&lr[i].id);
2220

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button