From 8154f88dbe98ade2d73b2830a32474e2df7f4b26 Mon Sep 17 00:00:00 2001 From: CSCMe Date: Tue, 21 Apr 2026 17:34:17 +0200 Subject: [PATCH] fix: Erroneous navigation with long filenames in footnote links (#1723) ## Summary * **What is the goal of this PR?** * Increase the allowed link length for footnotes * **What changes are included?** * Un-magic-numbers parts of the footnote parser * Increases max href length ## Additional Context * Additional RAM usage was not noticable to me, worst case 16 * 128 * 2 = 4KB instead of previously 16 * 88 * 2 ~ 2.8KB, see #1031 * Motivation: My book navigated me to the start of the footnote chapter, which required manual navigating for every footnote due to ungodly file name choices which pushed the required href length to 72, which caused truncating, which caused Crosspoint to not find the anchor (Sacred and Terrible Air, available via reddit) --- ### AI Usage While CrossPoint doesn't have restrictions on AI tools in contributing, please be transparent about their usage as it helps set the right context for reviewers. Did you use AI tools to help write this code? _**NO**_ --- lib/Epub/Epub/FootnoteEntry.h | 7 +++++-- lib/Epub/Epub/Section.cpp | 2 +- .../Epub/parsers/ChapterHtmlSlimParser.cpp | 18 +++++++++--------- lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h | 3 +-- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/Epub/Epub/FootnoteEntry.h b/lib/Epub/Epub/FootnoteEntry.h index 8023df42c..6034a6a5c 100644 --- a/lib/Epub/Epub/FootnoteEntry.h +++ b/lib/Epub/Epub/FootnoteEntry.h @@ -2,9 +2,12 @@ #include +#define FOOTNOTE_NUMBER_LEN 32 +#define FOOTNOTE_HREF_LEN 96 + struct FootnoteEntry { - char number[24]; - char href[64]; + char number[FOOTNOTE_NUMBER_LEN]; + char href[FOOTNOTE_HREF_LEN]; FootnoteEntry() { number[0] = '\0'; diff --git a/lib/Epub/Epub/Section.cpp b/lib/Epub/Epub/Section.cpp index f93457916..a9ecd9549 100644 --- a/lib/Epub/Epub/Section.cpp +++ b/lib/Epub/Epub/Section.cpp @@ -10,7 +10,7 @@ #include "parsers/ChapterHtmlSlimParser.h" namespace { -constexpr uint8_t SECTION_FILE_VERSION = 20; +constexpr uint8_t SECTION_FILE_VERSION = 21; constexpr uint32_t HEADER_SIZE = sizeof(uint8_t) + sizeof(int) + sizeof(float) + sizeof(bool) + sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(bool) + sizeof(bool) + sizeof(uint8_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t); diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp index 93a28104e..eee24c494 100644 --- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp +++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp @@ -539,9 +539,9 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* } self->insideFootnoteLink = true; self->footnoteLinkDepth = self->depth; - strncpy(self->currentFootnoteLinkHref, href, sizeof(self->currentFootnoteLinkHref) - 1); - self->currentFootnoteLinkHref[sizeof(self->currentFootnoteLinkHref) - 1] = '\0'; - self->currentFootnoteLinkText[0] = '\0'; + strncpy(self->currentFootnote.href, href, sizeof(self->currentFootnote.href) - 1); + self->currentFootnote.href[sizeof(self->currentFootnote.href) - 1] = '\0'; + self->currentFootnote.number[0] = '\0'; self->currentFootnoteLinkTextLen = 0; // Apply underline style to visually indicate the link @@ -720,11 +720,11 @@ void XMLCALL ChapterHtmlSlimParser::characterData(void* userData, const XML_Char } // Extract footnote link text - for (int i = start; (self->currentFootnoteLinkTextLen < sizeof(self->currentFootnoteLinkText) - 1) && (i <= end); + for (int i = start; (self->currentFootnoteLinkTextLen < sizeof(self->currentFootnote.number) - 1) && (i <= end); ++i) { - self->currentFootnoteLinkText[self->currentFootnoteLinkTextLen++] = s[i]; + self->currentFootnote.number[self->currentFootnoteLinkTextLen++] = s[i]; } - self->currentFootnoteLinkText[self->currentFootnoteLinkTextLen] = '\0'; + self->currentFootnote.number[self->currentFootnoteLinkTextLen] = '\0'; } for (int i = 0; i < len; i++) { @@ -915,11 +915,11 @@ void XMLCALL ChapterHtmlSlimParser::endElement(void* userData, const XML_Char* n // Closing a footnote link — create entry from collected text and href if (self->insideFootnoteLink && self->depth == self->footnoteLinkDepth) { - if (self->currentFootnoteLinkText[0] != '\0' && self->currentFootnoteLinkHref[0] != '\0') { + if (self->currentFootnote.number[0] != '\0' && self->currentFootnote.href[0] != '\0') { FootnoteEntry entry; - strncpy(entry.number, self->currentFootnoteLinkText, sizeof(entry.number) - 1); + strncpy(entry.number, self->currentFootnote.number, sizeof(entry.number) - 1); entry.number[sizeof(entry.number) - 1] = '\0'; - strncpy(entry.href, self->currentFootnoteLinkHref, sizeof(entry.href) - 1); + strncpy(entry.href, self->currentFootnote.href, sizeof(entry.href) - 1); entry.href[sizeof(entry.href) - 1] = '\0'; int wordIndex = self->wordsExtractedInBlock + (self->currentTextBlock ? static_cast(self->currentTextBlock->size()) : 0); diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h index 31c8ecc2a..8e61b5acd 100644 --- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h +++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h @@ -79,9 +79,8 @@ class ChapterHtmlSlimParser { // Footnote link tracking bool insideFootnoteLink = false; int footnoteLinkDepth = -1; - char currentFootnoteLinkText[24] = {}; + FootnoteEntry currentFootnote = {}; int currentFootnoteLinkTextLen = 0; - char currentFootnoteLinkHref[64] = {}; std::vector> pendingFootnotes; // int wordsExtractedInBlock = 0;