Skip to content

Commit

Permalink
Fix array overflow for headings using roman numerals (Issue #433)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelrsweet committed May 27, 2021
1 parent a5b87b9 commit c67bbd8
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 74 deletions.
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# Changes in HTMLDOC v1.9.13

- Fixed an issue with large values for roman numerals and letters in headings
(Issue #433)


# Changes in HTMLDOC v1.9.12

- Fixed a crash bug with "data:" URIs and EPUB output (Issue #410)
Expand Down
55 changes: 1 addition & 54 deletions htmldoc/toc.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -122,36 +122,6 @@ parse_tree(tree_t *t) /* I - Document tree */
*existing; /* Existing link string */
int i, level; /* Header level */
uchar *var; /* Starting value/type for this level */
static const char *ones[10] =
{
"", "i", "ii", "iii", "iv",
"v", "vi", "vii", "viii", "ix"
},
*tens[10] =
{
"", "x", "xx", "xxx", "xl",
"l", "lx", "lxx", "lxxx", "xc"
},
*hundreds[10] =
{
"", "c", "cc", "ccc", "cd",
"d", "dc", "dcc", "dccc", "cm"
},
*ONES[10] =
{
"", "I", "II", "III", "IV",
"V", "VI", "VII", "VIII", "IX"
},
*TENS[10] =
{
"", "X", "XX", "XXX", "XL",
"L", "LX", "LXX", "LXXX", "XC"
},
*HUNDREDS[10] =
{
"", "C", "CC", "CCC", "CD",
"D", "DC", "DCC", "DCCC", "CM"
};


while (t != NULL)
Expand Down Expand Up @@ -212,30 +182,7 @@ parse_tree(tree_t *t) /* I - Document tree */
else
snprintf((char *)baseptr, sizeof(baselink) - (size_t)(baseptr - baselink), "%d", heading_numbers[i]);

switch (heading_types[i])
{
case '1' :
snprintf((char *)headptr, sizeof(heading) - (size_t)(headptr - heading), "%d", heading_numbers[i]);
break;
case 'a' :
if (heading_numbers[i] > 26)
snprintf((char *)headptr, sizeof(heading) - (size_t)(headptr - heading), "%c%c", 'a' + (heading_numbers[i] / 26) - 1, 'a' + (heading_numbers[i] % 26) - 1);
else
snprintf((char *)headptr, sizeof(heading) - (size_t)(headptr - heading), "%c", 'a' + heading_numbers[i] - 1);
break;
case 'A' :
if (heading_numbers[i] > 26)
snprintf((char *)headptr, sizeof(heading) - (size_t)(headptr - heading), "%c%c", 'A' + (heading_numbers[i] / 26) - 1, 'A' + (heading_numbers[i] % 26) - 1);
else
snprintf((char *)headptr, sizeof(heading) - (size_t)(headptr - heading), "%c", 'A' + heading_numbers[i] - 1);
break;
case 'i' :
snprintf((char *)headptr, sizeof(heading) - (size_t)(headptr - heading), "%s%s%s", hundreds[heading_numbers[i] / 100], tens[(heading_numbers[i] / 10) % 10], ones[heading_numbers[i] % 10]);
break;
case 'I' :
snprintf((char *)headptr, sizeof(heading) - (size_t)(headptr - heading), "%s%s%s", HUNDREDS[heading_numbers[i] / 100], TENS[(heading_numbers[i] / 10) % 10], ONES[heading_numbers[i] % 10]);
break;
}
strlcpy((char *)headptr, format_number(heading_numbers[i], heading_types[i]), sizeof(heading) - (size_t)(headptr - heading));

if (i < level)
{
Expand Down
50 changes: 30 additions & 20 deletions htmldoc/util.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,14 @@ format_number(int n, /* I - Number */
"", "x", "xx", "xxx", "xl",
"l", "lx", "lxx", "lxxx", "xc"
},
*hundreds[10] = /* Roman numerals, 100-900 */
*hundreds[30] = /* Roman numerals, 100-2900 */
{
"", "c", "cc", "ccc", "cd",
"d", "dc", "dcc", "dccc", "cm"
"", "c", "cc", "ccc", "cd",
"d", "dc", "dcc", "dccc", "cm",
"m", "mc", "cc", "ccc", "cd",
"m", "mdc", "mdcc", "mdccc", "mcm",
"mm", "mmc", "mmcc", "mmccc", "mmcd",
"mmd", "mmdc", "mmdcc", "mmdccc", "mmcm"
};
static const char *ONES[10] = /* Roman numerals, 0-9 */
{
Expand All @@ -50,10 +54,14 @@ format_number(int n, /* I - Number */
"", "X", "XX", "XXX", "XL",
"L", "LX", "LXX", "LXXX", "XC"
},
*HUNDREDS[10] = /* Roman numerals, 100-900 */
*HUNDREDS[30] = /* Roman numerals, 100-2900 */
{
"", "C", "CC", "CCC", "CD",
"D", "DC", "DCC", "DCCC", "CM"
"", "C", "CC", "CCC", "CD",
"D", "DC", "DCC", "DCCC", "CM",
"M", "MC", "CC", "CCC", "CD",
"M", "MDC", "MDCC", "MDCCC", "MCM",
"MM", "MMC", "MMCC", "MMCCC", "MMCD",
"MMD", "MMDC", "MMDCC", "MMDCCC", "MMCM"
};
static char buffer[1024]; /* String buffer */

Expand All @@ -65,18 +73,20 @@ format_number(int n, /* I - Number */
break;

case 'a' :
if (n >= (26 * 26))
buffer[0] = '\0';
else if (n > 26)
if (n > (26 * 26))
n = (n % (26 * 26)) + 1;

if (n > 26)
snprintf(buffer, sizeof(buffer), "%c%c", 'a' + (n / 26) - 1, 'a' + (n % 26) - 1);
else
snprintf(buffer, sizeof(buffer), "%c", 'a' + n - 1);
break;

case 'A' :
if (n >= (26 * 26))
buffer[0] = '\0';
else if (n > 26)
if (n > (26 * 26))
n = (n % (26 * 26)) + 1;

if (n > 26)
snprintf(buffer, sizeof(buffer), "%c%c", 'A' + (n / 26) - 1, 'A' + (n % 26) - 1);
else
snprintf(buffer, sizeof(buffer), "%c", 'A' + n - 1);
Expand All @@ -87,17 +97,17 @@ format_number(int n, /* I - Number */
break;

case 'i' :
if (n >= 1000)
buffer[0] = '\0';
else
snprintf(buffer, sizeof(buffer), "%s%s%s", hundreds[n / 100], tens[(n / 10) % 10], ones[n % 10]);
if (n >= 3000)
n = (n % 3000) + 1;
snprintf(buffer, sizeof(buffer), "%s%s%s", hundreds[n / 100], tens[(n / 10) % 10], ones[n % 10]);
break;

case 'I' :
if (n >= 1000)
buffer[0] = '\0';
else
snprintf(buffer, sizeof(buffer), "%s%s%s", HUNDREDS[n / 100], TENS[(n / 10) % 10], ONES[n % 10]);
if (n >= 3000)
n = (n % 3000) + 1;
snprintf(buffer, sizeof(buffer), "%s%s%s", HUNDREDS[n / 100], TENS[(n / 10) % 10], ONES[n % 10]);
break;
}

Expand Down

0 comments on commit c67bbd8

Please sign in to comment.