A fork of https://github.com/crosspoint-reader/crosspoint-reader
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: Skip large CSS files to prevent crashes (#952)

## Summary

**What is the goal of this PR?** (e.g., Implements the new feature for
file uploading.)
* Fixes:
https://github.com/crosspoint-reader/crosspoint-reader/issues/947

**What changes are included?**
* Check to see if there's free heap memory before processing CSS (should
we be doing this type of check or is it better to just crash if we
exhaust the memory?)
* Skip CSS files larger than 128kb

## Additional Context

* I found that a copy of `Release it` contained a 250kb+ CSS file, from
the homepage of the publisher. It has nothing to do with the epub, so we
should just skip it
* Major question: Are there better ways to detect CSS that doesn't
belong in a book, or is this size-based approach valid?
* Another question: Are there any epubs we know of that legitimately
include >128kb CSS files?

Code changes themselves created with an agent, all investigation and
write-up done by human. If you (the maintainers) would prefer a
different fix for this issue, let me know.

---

### 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? _**< YES >**_

authored by

Sam Lord and committed by
GitHub
e1074a84 e70066e7

+24
+24
lib/Epub/Epub.cpp
··· 258 258 } 259 259 260 260 void Epub::parseCssFiles() const { 261 + // Maximum CSS file size we'll attempt to parse (uncompressed) 262 + // Larger files risk memory exhaustion on ESP32 263 + constexpr size_t MAX_CSS_FILE_SIZE = 128 * 1024; // 128KB 264 + // Minimum heap required before attempting CSS parsing 265 + constexpr size_t MIN_HEAP_FOR_CSS_PARSING = 64 * 1024; // 64KB 266 + 261 267 if (cssFiles.empty()) { 262 268 LOG_DBG("EBP", "No CSS files to parse, but CssParser created for inline styles"); 263 269 } ··· 267 273 // No cache yet - parse CSS files 268 274 for (const auto& cssPath : cssFiles) { 269 275 LOG_DBG("EBP", "Parsing CSS file: %s", cssPath.c_str()); 276 + 277 + // Check heap before parsing - CSS parsing allocates heavily 278 + const uint32_t freeHeap = ESP.getFreeHeap(); 279 + if (freeHeap < MIN_HEAP_FOR_CSS_PARSING) { 280 + LOG_ERR("EBP", "Insufficient heap for CSS parsing (%u bytes free, need %zu), skipping: %s", freeHeap, 281 + MIN_HEAP_FOR_CSS_PARSING, cssPath.c_str()); 282 + continue; 283 + } 284 + 285 + // Check CSS file size before decompressing - skip files that are too large 286 + size_t cssFileSize = 0; 287 + if (getItemSize(cssPath, &cssFileSize)) { 288 + if (cssFileSize > MAX_CSS_FILE_SIZE) { 289 + LOG_ERR("EBP", "CSS file too large (%zu bytes > %zu max), skipping: %s", cssFileSize, MAX_CSS_FILE_SIZE, 290 + cssPath.c_str()); 291 + continue; 292 + } 293 + } 270 294 271 295 // Extract CSS file to temp location 272 296 const auto tmpCssPath = getCachePath() + "/.tmp.css";