Fossil SCM

Change signature of <code>add_inline_footnote()</code> in order to move away from returning of unreliable pointer. Amend a few comments. Fix a couple of minor issues that fuzzer complains about.

george 2022-04-23 17:23 markdown-footnotes
Commit 0850862e6a2a55193677bc9604d4b51f4c6e69dae9facd9714a0ae0bc1c912fd
1 file changed +22 -19
+22 -19
--- src/markdown.c
+++ src/markdown.c
@@ -186,11 +186,12 @@
186186
int iDepth; /* Depth of recursion */
187187
int nBlobCache; /* Number of entries in aBlobCache */
188188
struct Blob *aBlobCache[20]; /* Cache of Blobs available for reuse */
189189
190190
struct {
191
- Blob all; /* array of footnotes */
191
+ Blob all; /* Buffer that holds array of footnotes. Its underline
192
+ memory may be reallocated when a new footnote is added. */
192193
int nLbled; /* number of labeled footnotes found during the first pass */
193194
int nMarks; /* counts distinct indices found during the second pass */
194195
struct footnote misref; /* nUsed counts misreferences, iMark must be -1 */
195196
} notes;
196197
};
@@ -1049,11 +1050,11 @@
10491050
link_e--;
10501051
}
10511052
10521053
/* remove optional angle brackets around the link */
10531054
if( data[link_b]=='<' ) link_b += 1;
1054
- if( data[link_e-1]=='>' ) link_e -= 1; /* TODO: handle link_e == 0 */
1055
+ if( link_e && data[link_e-1]=='>' ) link_e -= 1;
10551056
10561057
/* escape backslashed character from link */
10571058
blob_reset(link);
10581059
i = link_b;
10591060
while( i<link_e ){
@@ -1200,21 +1201,21 @@
12001201
}
12011202
return 0;
12021203
}
12031204
12041205
/*
1205
-** Adds unlabeled footnote to the rndr. If text is blank then returns
1206
-** 0, otherwise returns the address of the added footnote, which lives
1207
-** in rndr->notes, noting that the pointer may be invalidated via
1208
-** reallocation the next time a footnote is added to that member.
1206
+** Adds unlabeled footnote to the rndr->notes.all.
1207
+** On success puts a shallow copy of the constructed footnote into pFN
1208
+** and returns 1, otherwise pFN is unchanged and 0 is returned.
12091209
*/
1210
-static inline const struct footnote* add_inline_footnote(
1210
+static inline int add_inline_footnote(
12111211
struct render *rndr,
12121212
const char *text,
1213
- size_t size
1213
+ size_t size,
1214
+ struct footnote* pFN
12141215
){
1215
- struct footnote fn = FOOTNOTE_INITIALIZER;
1216
+ struct footnote fn = FOOTNOTE_INITIALIZER, *last;
12161217
const char *zUPC = 0;
12171218
size_t nUPC = 0, n = sizeof_blank_prefix(text, size, 3);
12181219
if( n >= size ) return 0;
12191220
text += n;
12201221
size -= n;
@@ -1236,12 +1237,15 @@
12361237
fn.index = COUNT_FOOTNOTES(&rndr->notes.all);
12371238
assert( fn.iMark > 0 );
12381239
blob_append(&fn.text, text, size);
12391240
if(nUPC) blob_append(&fn.upc, zUPC, nUPC);
12401241
blob_append(&rndr->notes.all, (char *)&fn, sizeof fn);
1241
- return (struct footnote*)( blob_buffer(&rndr->notes.all)
1242
+ last = (struct footnote*)( blob_buffer(&rndr->notes.all)
12421243
+( blob_size(&rndr->notes.all)-sizeof fn ));
1244
+ assert( pFN );
1245
+ memcpy( pFN, last, sizeof fn );
1246
+ return 1;
12431247
}
12441248
12451249
/*
12461250
** Return the byte offset of the matching closing bracket or 0 if not
12471251
** found. begin[0] must be either '[' or '('.
@@ -1279,19 +1283,18 @@
12791283
char *data,
12801284
size_t offset,
12811285
size_t size
12821286
){
12831287
size_t end;
1284
- const struct footnote* fn;
1288
+ struct footnote fn;
12851289
12861290
if( size<4 || data[1]!='^' ) return 0;
12871291
end = matching_bracket_offset(data, data+size);
12881292
if( !end ) return 0;
1289
- fn = add_inline_footnote(rndr, data+2, end-2);
1290
- if( !fn ) return 0;
1293
+ if( !add_inline_footnote(rndr, data+2, end-2, &fn) ) return 0;
12911294
if( rndr->make.footnote_ref ){
1292
- rndr->make.footnote_ref(ob,0,&fn->upc,fn->iMark,1,rndr->make.opaque);
1295
+ rndr->make.footnote_ref(ob,0,&fn.upc,fn.iMark,1,rndr->make.opaque);
12931296
}
12941297
return end+1;
12951298
}
12961299
12971300
/*
@@ -1341,14 +1344,12 @@
13411344
if( i<size && data[i]=='(' ){
13421345
13431346
if( i+2<size && data[i+1]=='^' ){ /* span-bounded inline footnote */
13441347
13451348
const size_t k = matching_bracket_offset(data+i, data+size);
1346
- const struct footnote *x;
13471349
if( !k ) goto char_link_cleanup;
1348
- x = add_inline_footnote(rndr, data+(i+2), k-2);
1349
- if( x ) fn = *x;
1350
+ add_inline_footnote(rndr, data+(i+2), k-2, &fn);
13501351
i += k+1;
13511352
}else{ /* inline style link */
13521353
size_t span_end = i;
13531354
while( span_end<size
13541355
&& !(data[span_end]==')'
@@ -2316,14 +2317,16 @@
23162317
char *data, /* input text */
23172318
size_t size /* input text size */
23182319
){
23192320
size_t beg, end, i;
23202321
char *txt_data;
2321
- int has_table = (rndr->make.table
2322
+ int has_table;
2323
+ if( !size ) return;
2324
+ has_table = (rndr->make.table
23222325
&& rndr->make.table_row
23232326
&& rndr->make.table_cell
2324
- && memchr(data, '|', size)!=0); /* TODO: handle data == 0 */
2327
+ && memchr(data, '|', size)!=0);
23252328
23262329
beg = 0;
23272330
while( beg<size ){
23282331
txt_data = data+beg;
23292332
end = size-beg;
23302333
--- src/markdown.c
+++ src/markdown.c
@@ -186,11 +186,12 @@
186 int iDepth; /* Depth of recursion */
187 int nBlobCache; /* Number of entries in aBlobCache */
188 struct Blob *aBlobCache[20]; /* Cache of Blobs available for reuse */
189
190 struct {
191 Blob all; /* array of footnotes */
 
192 int nLbled; /* number of labeled footnotes found during the first pass */
193 int nMarks; /* counts distinct indices found during the second pass */
194 struct footnote misref; /* nUsed counts misreferences, iMark must be -1 */
195 } notes;
196 };
@@ -1049,11 +1050,11 @@
1049 link_e--;
1050 }
1051
1052 /* remove optional angle brackets around the link */
1053 if( data[link_b]=='<' ) link_b += 1;
1054 if( data[link_e-1]=='>' ) link_e -= 1; /* TODO: handle link_e == 0 */
1055
1056 /* escape backslashed character from link */
1057 blob_reset(link);
1058 i = link_b;
1059 while( i<link_e ){
@@ -1200,21 +1201,21 @@
1200 }
1201 return 0;
1202 }
1203
1204 /*
1205 ** Adds unlabeled footnote to the rndr. If text is blank then returns
1206 ** 0, otherwise returns the address of the added footnote, which lives
1207 ** in rndr->notes, noting that the pointer may be invalidated via
1208 ** reallocation the next time a footnote is added to that member.
1209 */
1210 static inline const struct footnote* add_inline_footnote(
1211 struct render *rndr,
1212 const char *text,
1213 size_t size
 
1214 ){
1215 struct footnote fn = FOOTNOTE_INITIALIZER;
1216 const char *zUPC = 0;
1217 size_t nUPC = 0, n = sizeof_blank_prefix(text, size, 3);
1218 if( n >= size ) return 0;
1219 text += n;
1220 size -= n;
@@ -1236,12 +1237,15 @@
1236 fn.index = COUNT_FOOTNOTES(&rndr->notes.all);
1237 assert( fn.iMark > 0 );
1238 blob_append(&fn.text, text, size);
1239 if(nUPC) blob_append(&fn.upc, zUPC, nUPC);
1240 blob_append(&rndr->notes.all, (char *)&fn, sizeof fn);
1241 return (struct footnote*)( blob_buffer(&rndr->notes.all)
1242 +( blob_size(&rndr->notes.all)-sizeof fn ));
 
 
 
1243 }
1244
1245 /*
1246 ** Return the byte offset of the matching closing bracket or 0 if not
1247 ** found. begin[0] must be either '[' or '('.
@@ -1279,19 +1283,18 @@
1279 char *data,
1280 size_t offset,
1281 size_t size
1282 ){
1283 size_t end;
1284 const struct footnote* fn;
1285
1286 if( size<4 || data[1]!='^' ) return 0;
1287 end = matching_bracket_offset(data, data+size);
1288 if( !end ) return 0;
1289 fn = add_inline_footnote(rndr, data+2, end-2);
1290 if( !fn ) return 0;
1291 if( rndr->make.footnote_ref ){
1292 rndr->make.footnote_ref(ob,0,&fn->upc,fn->iMark,1,rndr->make.opaque);
1293 }
1294 return end+1;
1295 }
1296
1297 /*
@@ -1341,14 +1344,12 @@
1341 if( i<size && data[i]=='(' ){
1342
1343 if( i+2<size && data[i+1]=='^' ){ /* span-bounded inline footnote */
1344
1345 const size_t k = matching_bracket_offset(data+i, data+size);
1346 const struct footnote *x;
1347 if( !k ) goto char_link_cleanup;
1348 x = add_inline_footnote(rndr, data+(i+2), k-2);
1349 if( x ) fn = *x;
1350 i += k+1;
1351 }else{ /* inline style link */
1352 size_t span_end = i;
1353 while( span_end<size
1354 && !(data[span_end]==')'
@@ -2316,14 +2317,16 @@
2316 char *data, /* input text */
2317 size_t size /* input text size */
2318 ){
2319 size_t beg, end, i;
2320 char *txt_data;
2321 int has_table = (rndr->make.table
 
 
2322 && rndr->make.table_row
2323 && rndr->make.table_cell
2324 && memchr(data, '|', size)!=0); /* TODO: handle data == 0 */
2325
2326 beg = 0;
2327 while( beg<size ){
2328 txt_data = data+beg;
2329 end = size-beg;
2330
--- src/markdown.c
+++ src/markdown.c
@@ -186,11 +186,12 @@
186 int iDepth; /* Depth of recursion */
187 int nBlobCache; /* Number of entries in aBlobCache */
188 struct Blob *aBlobCache[20]; /* Cache of Blobs available for reuse */
189
190 struct {
191 Blob all; /* Buffer that holds array of footnotes. Its underline
192 memory may be reallocated when a new footnote is added. */
193 int nLbled; /* number of labeled footnotes found during the first pass */
194 int nMarks; /* counts distinct indices found during the second pass */
195 struct footnote misref; /* nUsed counts misreferences, iMark must be -1 */
196 } notes;
197 };
@@ -1049,11 +1050,11 @@
1050 link_e--;
1051 }
1052
1053 /* remove optional angle brackets around the link */
1054 if( data[link_b]=='<' ) link_b += 1;
1055 if( link_e && data[link_e-1]=='>' ) link_e -= 1;
1056
1057 /* escape backslashed character from link */
1058 blob_reset(link);
1059 i = link_b;
1060 while( i<link_e ){
@@ -1200,21 +1201,21 @@
1201 }
1202 return 0;
1203 }
1204
1205 /*
1206 ** Adds unlabeled footnote to the rndr->notes.all.
1207 ** On success puts a shallow copy of the constructed footnote into pFN
1208 ** and returns 1, otherwise pFN is unchanged and 0 is returned.
 
1209 */
1210 static inline int add_inline_footnote(
1211 struct render *rndr,
1212 const char *text,
1213 size_t size,
1214 struct footnote* pFN
1215 ){
1216 struct footnote fn = FOOTNOTE_INITIALIZER, *last;
1217 const char *zUPC = 0;
1218 size_t nUPC = 0, n = sizeof_blank_prefix(text, size, 3);
1219 if( n >= size ) return 0;
1220 text += n;
1221 size -= n;
@@ -1236,12 +1237,15 @@
1237 fn.index = COUNT_FOOTNOTES(&rndr->notes.all);
1238 assert( fn.iMark > 0 );
1239 blob_append(&fn.text, text, size);
1240 if(nUPC) blob_append(&fn.upc, zUPC, nUPC);
1241 blob_append(&rndr->notes.all, (char *)&fn, sizeof fn);
1242 last = (struct footnote*)( blob_buffer(&rndr->notes.all)
1243 +( blob_size(&rndr->notes.all)-sizeof fn ));
1244 assert( pFN );
1245 memcpy( pFN, last, sizeof fn );
1246 return 1;
1247 }
1248
1249 /*
1250 ** Return the byte offset of the matching closing bracket or 0 if not
1251 ** found. begin[0] must be either '[' or '('.
@@ -1279,19 +1283,18 @@
1283 char *data,
1284 size_t offset,
1285 size_t size
1286 ){
1287 size_t end;
1288 struct footnote fn;
1289
1290 if( size<4 || data[1]!='^' ) return 0;
1291 end = matching_bracket_offset(data, data+size);
1292 if( !end ) return 0;
1293 if( !add_inline_footnote(rndr, data+2, end-2, &fn) ) return 0;
 
1294 if( rndr->make.footnote_ref ){
1295 rndr->make.footnote_ref(ob,0,&fn.upc,fn.iMark,1,rndr->make.opaque);
1296 }
1297 return end+1;
1298 }
1299
1300 /*
@@ -1341,14 +1344,12 @@
1344 if( i<size && data[i]=='(' ){
1345
1346 if( i+2<size && data[i+1]=='^' ){ /* span-bounded inline footnote */
1347
1348 const size_t k = matching_bracket_offset(data+i, data+size);
 
1349 if( !k ) goto char_link_cleanup;
1350 add_inline_footnote(rndr, data+(i+2), k-2, &fn);
 
1351 i += k+1;
1352 }else{ /* inline style link */
1353 size_t span_end = i;
1354 while( span_end<size
1355 && !(data[span_end]==')'
@@ -2316,14 +2317,16 @@
2317 char *data, /* input text */
2318 size_t size /* input text size */
2319 ){
2320 size_t beg, end, i;
2321 char *txt_data;
2322 int has_table;
2323 if( !size ) return;
2324 has_table = (rndr->make.table
2325 && rndr->make.table_row
2326 && rndr->make.table_cell
2327 && memchr(data, '|', size)!=0);
2328
2329 beg = 0;
2330 while( beg<size ){
2331 txt_data = data+beg;
2332 end = size-beg;
2333

Keyboard Shortcuts

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