summaryrefslogtreecommitdiff
path: root/src/latex.c
diff options
context:
space:
mode:
authorJohn MacFarlane <jgm@berkeley.edu>2017-06-29 10:01:34 +0200
committerJohn MacFarlane <jgm@berkeley.edu>2017-06-29 10:03:55 +0200
commitf8737b1c82981624b3263224dbf92fa6627f7205 (patch)
tree56cbf6eb574aaf2230e560c950a13a8339bc9f27 /src/latex.c
parent09d96cd0b6f352227f741c4fc9b0d82cbefcc012 (diff)
latex writer: fix memory overflow.
We got an array overflow in enumerated lists nested more than 10 deep with start number =/= 1. Found by google/oss-fuzz. https://oss-fuzz.com/v2/testcase-detail/5546760854306816 This commit also ensures that we don't try to set `enum_` counters that aren't defined by LaTeX (generally up to enumv). Closes #210.
Diffstat (limited to 'src/latex.c')
-rw-r--r--src/latex.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/src/latex.c b/src/latex.c
index 22052d7..f372a13 100644
--- a/src/latex.c
+++ b/src/latex.c
@@ -220,11 +220,10 @@ static int S_get_enumlevel(cmark_node *node) {
static int S_render_node(cmark_renderer *renderer, cmark_node *node,
cmark_event_type ev_type, int options) {
int list_number;
+ int enumlevel;
char list_number_string[LIST_NUMBER_STRING_SIZE];
bool entering = (ev_type == CMARK_EVENT_ENTER);
cmark_list_type list_type;
- const char *roman_numerals[] = {"", "i", "ii", "iii", "iv", "v",
- "vi", "vii", "viii", "ix", "x"};
bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options);
// avoid warning about unused parameter:
@@ -253,13 +252,24 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
CR();
list_number = cmark_node_get_list_start(node);
if (list_number > 1) {
- snprintf(list_number_string, LIST_NUMBER_STRING_SIZE, "%d",
- list_number);
- LIT("\\setcounter{enum");
- LIT((char *)roman_numerals[S_get_enumlevel(node)]);
- LIT("}{");
- OUT(list_number_string, false, NORMAL);
- LIT("}");
+ enumlevel = S_get_enumlevel(node);
+ // latex normally supports only five levels
+ if (enumlevel >= 1 && enumlevel <= 5) {
+ snprintf(list_number_string, LIST_NUMBER_STRING_SIZE, "%d",
+ list_number);
+ LIT("\\setcounter{enum");
+ switch(enumlevel) {
+ case 1: LIT("i"); break;
+ case 2: LIT("ii"); break;
+ case 3: LIT("iii"); break;
+ case 4: LIT("iv"); break;
+ case 5: LIT("v"); break;
+ default: LIT("i"); break;
+ }
+ LIT("}{");
+ OUT(list_number_string, false, NORMAL);
+ LIT("}");
+ }
CR();
}
} else {