Address review comment: Don't leave dangling pointers when loading ligature/kern darta fails

This commit is contained in:
spfenwick
2026-05-02 19:51:14 +12:00
parent 13a76597d4
commit 9def61aed9
+24 -14
View File
@@ -72,6 +72,11 @@ void SdCardFont::freeStyleKernLigatureData(PerStyle& s) {
delete[] s.ligaturePairs; delete[] s.ligaturePairs;
s.ligaturePairs = nullptr; s.ligaturePairs = nullptr;
s.ligLoaded = false; s.ligLoaded = false;
// Clear dangling pointers in EpdFontData structs
s.stubData.ligaturePairs = nullptr;
s.stubData.ligaturePairCount = 0;
s.miniData.ligaturePairs = nullptr;
s.miniData.ligaturePairCount = 0;
} }
void SdCardFont::freeStyleMiniKern(PerStyle& s) { void SdCardFont::freeStyleMiniKern(PerStyle& s) {
@@ -157,56 +162,61 @@ bool SdCardFont::loadStyleKernLigatureData(PerStyle& s, bool ligatureOnly) {
// Load only the small class-lookup tables (~3KB each). The full matrix // Load only the small class-lookup tables (~3KB each). The full matrix
// (~36KB contiguous for Literata) is built per-page from SD in // (~36KB contiguous for Literata) is built per-page from SD in
// buildMiniKernMatrix(). // buildMiniKernMatrix().
s.kernLeftClasses = new (std::nothrow) EpdKernClassEntry[s.header.kernLeftEntryCount]; EpdKernClassEntry* newLeft = new (std::nothrow) EpdKernClassEntry[s.header.kernLeftEntryCount];
s.kernRightClasses = new (std::nothrow) EpdKernClassEntry[s.header.kernRightEntryCount]; EpdKernClassEntry* newRight = new (std::nothrow) EpdKernClassEntry[s.header.kernRightEntryCount];
if (!s.kernLeftClasses || !s.kernRightClasses) { if (!newLeft || !newRight) {
delete[] newLeft;
delete[] newRight;
LOG_ERR("SDCF", "Failed to allocate kern classes (%u+%u bytes)", s.header.kernLeftEntryCount * 3u, LOG_ERR("SDCF", "Failed to allocate kern classes (%u+%u bytes)", s.header.kernLeftEntryCount * 3u,
s.header.kernRightEntryCount * 3u); s.header.kernRightEntryCount * 3u);
freeStyleKernLigatureData(s);
file.close(); file.close();
return false; return false;
} }
if (!file.seekSet(s.kernLeftFileOffset)) { if (!file.seekSet(s.kernLeftFileOffset)) {
delete[] newLeft;
delete[] newRight;
LOG_ERR("SDCF", "Failed to seek to kern data"); LOG_ERR("SDCF", "Failed to seek to kern data");
freeStyleKernLigatureData(s);
file.close(); file.close();
return false; return false;
} }
size_t leftSz = s.header.kernLeftEntryCount * sizeof(EpdKernClassEntry); size_t leftSz = s.header.kernLeftEntryCount * sizeof(EpdKernClassEntry);
size_t rightSz = s.header.kernRightEntryCount * sizeof(EpdKernClassEntry); size_t rightSz = s.header.kernRightEntryCount * sizeof(EpdKernClassEntry);
if (file.read(reinterpret_cast<uint8_t*>(s.kernLeftClasses), leftSz) != static_cast<int>(leftSz) || if (file.read(reinterpret_cast<uint8_t*>(newLeft), leftSz) != static_cast<int>(leftSz) ||
file.read(reinterpret_cast<uint8_t*>(s.kernRightClasses), rightSz) != static_cast<int>(rightSz)) { file.read(reinterpret_cast<uint8_t*>(newRight), rightSz) != static_cast<int>(rightSz)) {
delete[] newLeft;
delete[] newRight;
LOG_ERR("SDCF", "Failed to read kern classes"); LOG_ERR("SDCF", "Failed to read kern classes");
freeStyleKernLigatureData(s);
file.close(); file.close();
return false; return false;
} }
s.kernLeftClasses = newLeft;
s.kernRightClasses = newRight;
s.kernClassesLoaded = true; s.kernClassesLoaded = true;
} }
if (wantLig && !s.ligLoaded) { if (wantLig && !s.ligLoaded) {
s.ligaturePairs = new (std::nothrow) EpdLigaturePair[s.header.ligaturePairCount]; EpdLigaturePair* newLig = new (std::nothrow) EpdLigaturePair[s.header.ligaturePairCount];
if (!s.ligaturePairs) { if (!newLig) {
LOG_ERR("SDCF", "Failed to allocate ligature pairs"); LOG_ERR("SDCF", "Failed to allocate ligature pairs");
freeStyleKernLigatureData(s);
file.close(); file.close();
return false; return false;
} }
if (!file.seekSet(s.ligatureFileOffset)) { if (!file.seekSet(s.ligatureFileOffset)) {
delete[] newLig;
LOG_ERR("SDCF", "Failed to seek to ligature data"); LOG_ERR("SDCF", "Failed to seek to ligature data");
freeStyleKernLigatureData(s);
file.close(); file.close();
return false; return false;
} }
size_t sz = s.header.ligaturePairCount * sizeof(EpdLigaturePair); size_t sz = s.header.ligaturePairCount * sizeof(EpdLigaturePair);
if (file.read(reinterpret_cast<uint8_t*>(s.ligaturePairs), sz) != static_cast<int>(sz)) { if (file.read(reinterpret_cast<uint8_t*>(newLig), sz) != static_cast<int>(sz)) {
delete[] newLig;
LOG_ERR("SDCF", "Failed to read ligature pairs"); LOG_ERR("SDCF", "Failed to read ligature pairs");
freeStyleKernLigatureData(s);
file.close(); file.close();
return false; return false;
} }
s.ligaturePairs = newLig;
s.ligLoaded = true; s.ligLoaded = true;
// Make ligatures visible to the stub (used when no mini data built yet). // Make ligatures visible to the stub (used when no mini data built yet).