Skip to content

fix: Crash (Load access fault) when indexing chapters containing characters unsupported by bold/italic font variants#997

Merged
daveallie merged 1 commit intocrosspoint-reader:masterfrom
Uri-Tauber:fix/load-access-fault
Feb 19, 2026
Merged

fix: Crash (Load access fault) when indexing chapters containing characters unsupported by bold/italic font variants#997
daveallie merged 1 commit intocrosspoint-reader:masterfrom
Uri-Tauber:fix/load-access-fault

Conversation

@Uri-Tauber
Copy link
Contributor

@Uri-Tauber Uri-Tauber commented Feb 19, 2026

Summary

  • What is the goal of this PR?

I flashed the last revision before commit f1740db, and chapter indexing worked without any crashes.
After applying f1740db, the same chapter consistently triggered a device reboot during indexing.

The affected chapter contains inline equation images surrounded by styled (bold/italic) text that includes special math/symbol characters.

Additional Context

Prior to f1740db, both getTextAdvanceX() and getSpaceWidth() always measured text using EpdFontFamily::REGULAR, regardless of the actual style.

Commit f1740db improved correctness by passing the active style so spacing is calculated using the actual bold/italic font variant.

However, bold and italic variants have narrower Unicode coverage than the regular font. When a character exists in the regular font but not in the selected styled variant, pdFont::getGlyph() returns nullptr.

The updated measurement functions did not check for this and immediately dereferenced the pointer:

width += font.getGlyph(cp, style)->advanceX; // nullptr->advanceX

Because advanceX is located at byte offset 2 within EpdGlyph, dereferencing a null pointer caused the CPU to attempt a load from address 0x00000002, resulting in a RISC-V:
Load access fault
MCAUSE = 5
MTVAL = 2

Fix

Added null-safety checks to both getTextAdvanceX() and getSpaceWidth(), following the same pattern used in the rendering path:

If the glyph is missing in the selected style → fall back to the replacement glyph.

If the replacement glyph is also unavailable → treat the character as zero-width.

This preserves the improved style-correct spacing while preventing crashes.
No behavioral changes occur for characters that are supported by the selected font variant.


AI Usage

Did you use AI tools to help write this code? < YES >
I encounter this bug while testing 1.1.0 RC.
I pasted the serial log to Claude, which identify the bug and fixed it. I can confirm now the chapter in question is indexed and loaded correctly.

…cters unsupported by bold/italic font variants
@Uri-Tauber
Copy link
Contributor Author

If anyone wants to take a look at the serial log:

[17:38:07] [DBG] [SCT] Page 24 processed
[17:38:07] [DBG] [EHP] Found image: src=graphics/017equ01.jpg
[17:38:07] [ERR] [ZIP] Decompressed 10626 bytes into 19229 bytes
[17:38:07] [DBG] [JPG] Image dimensions: 184x59
[17:38:07] [DBG] [EHP] Image dimensions: 184x59
[17:38:07] [DBG] [EHP] Display size: 184x59 (scale 1.00)
[17:38:07] [DBG] [SCT] Page 25 processed
[17:38:07] [DBG] [EHP] Found image: src=graphics/02tab01.jpg
[17:38:07] [INF] [MEM] Free: 163980 bytes, Total: 227804 bytes, Min Free: 93108 bytes
[17:38:07] [ERR] [ZIP] Decompressed 31296 bytes into 44661 bytes
[17:38:08] [DBG] [JPG] Image dimensions: 639x208
[17:38:08] [DBG] [EHP] Image dimensions: 639x208
[17:38:08] [DBG] [EHP] Display size: 464x151 (scale 0.73)
[17:38:08] [DBG] [EHP] Found image: src=graphics/le.jpg
[17:38:08] [ERR] [ZIP] Decompressed 4692 bytes into 11491 bytes
[17:38:08] [DBG] [JPG] Image dimensions: 11x19
[17:38:08] [DBG] [EHP] Image dimensions: 11x19
[17:38:08] [DBG] [EHP] Display size: 11x19 (scale 1.00)
[17:38:08] [DBG] [EHP] Found image: src=graphics/le.jpg
[17:38:08] [ERR] [ZIP] Decompressed 4692 bytes into 11491 bytes
[17:38:08] [DBG] [JPG] Image dimensions: 11x19
[17:38:08] [DBG] [EHP] Image dimensions: 11x19
[17:38:08] [DBG] [EHP] Display size: 11x19 (scale 1.00)
[17:38:09] [DBG] [EHP] Found image: src=graphics/le.jpg
[17:38:09] [ERR] [ZIP] Decompressed 4692 bytes into 11491 bytes
[17:38:09] [DBG] [JPG] Image dimensions: 11x19
[17:38:09] [DBG] [EHP] Image dimensions: 11x19
[17:38:09] [DBG] [EHP] Display size: 11x19 (scale 1.00)
[17:38:09] [DBG] [EHP] Found image: src=graphics/le.jpg
[17:38:09] [ERR] [ZIP] Decompressed 4692 bytes into 11491 bytes
[17:38:09] [DBG] [JPG] Image dimensions: 11x19
[17:38:09] [DBG] [EHP] Image dimensions: 11x19
[17:38:09] [DBG] [EHP] Display size: 11x19 (scale 1.00)
[17:38:09] [DBG] [SCT] Page 26 processed
[17:38:09] [DBG] [SCT] Page 27 processed
[17:38:09] [DBG] [EHP] Found image: src=graphics/018equ01.jpg
[17:38:09] [ERR] [ZIP] Decompressed 21104 bytes into 29430 bytes
[17:38:09] [DBG] [JPG] Image dimensions: 478x139
[17:38:09] [DBG] [EHP] Image dimensions: 478x139
[17:38:09] [DBG] [EHP] Display size: 464x134 (scale 0.97)
[17:38:09] [DBG] [EHP] Found image: src=graphics/le.jpg
[17:38:10] [ERR] [ZIP] Decompressed 4692 bytes into 11491 bytes
[17:38:10] [DBG] [JPG] Image dimensions: 11x19
[17:38:10] [DBG] [EHP] Image dimensions: 11x19
[17:38:10] [DBG] [EHP] Display size: 11x19 (scale 1.00)
[17:38:10] [DBG] [SCT] Page 28 processed
[17:38:10] [DBG] [EHP] Found image: src=graphics/018equ04.jpg
[17:38:10] [ERR] [ZIP] Decompressed 3227 bytes into 9893 bytes
[17:38:10] [DBG] [JPG] Image dimensions: 82x18
[17:38:10] [DBG] [EHP] Image dimensions: 82x18
[17:38:10] [DBG] [EHP] Display size: 82x18 (scale 1.00)
[17:38:10] [DBG] [EHP] Found image: src=graphics/018equ02.jpg
[17:38:11] [ERR] [ZIP] Decompressed 14854 bytes into 23838 bytes
[17:38:11] [DBG] [JPG] Image dimensions: 248x109
[17:38:11] [DBG] [EHP] Image dimensions: 248x109
[17:38:11] [DBG] [EHP] Display size: 248x109 (scale 1.00)
[17:38:11] [DBG] [SCT] Page 29 processed
[17:38:11] [DBG] [EHP] Found image: src=graphics/018equ03.jpg
[17:38:11] [ERR] [ZIP] Decompressed 7342 bytes into 15156 bytes
[17:38:11] [DBG] [JPG] Image dimensions: 150x22
[17:38:11] [DBG] [EHP] Image dimensions: 150x22
[17:38:11] [DBG] [EHP] Display size: 150x22 (scale 1.00)
Guru Meditation Error: Core  0 panic'ed (Load access fault). Exception was unhandled.
Core  0 register dump:
MEPC    : 0x4203fa22  RA      : 0x4203fa22  SP      : 0x3fcb2c50  GP      : 0x3fc8f000
TP      : 0x3f9e10e4  T0      : 0x3fca7e00  T1      : 0x0000000c  T2      : 0x00000000
S0/FP   : 0x3fc9e8ac  S1      : 0x00000000  A0      : 0x00000000  A1      : 0x0000230a
A2      : 0x0000003f  A3      : 0x3c2ba63c  A4      : 0x0000003e  A5      : 0x0000003f
A6      : 0x3c165b88  A7      : 0x0000fffd  S2      : 0x3fcaa1b8  S3      : 0x00000000
S4      : 0x498b179b  S5      : 0x00000000  S6      : 0x00000004  S7      : 0x3fca7000
S8      : 0x00000001  S9      : 0x3c161000  S10     : 0x0000007b  S11     : 0x00000003
T3      : 0x3fcb5f00  T4      : 0x00000000  T5      : 0x40382800  T6      : 0x00000000
MSTATUS : 0x00001881  MTVEC   : 0x40380001  MCAUSE  : 0x00000005  MTVAL   : 0x00000002
MHARTID : 0x00000000
Stack memory:
3fcb2c50: 0x00000004 0x3fc9e87c 0x3fcb9cd7 0x498b179b 0x00000000 0x3fcb9ccc 0x3c3da000 0x3fc9e87c
3fcb2c70: 0x00000000 0x00000000 0x3fcb9cd4 0x42050fd8 0x3fcb79c4 0x3fcb5f08 0x00000001 0x3fcb2dac
3fcb2c90: 0x498b179b 0x3fc9e87c 0x000001d0 0x218f67b6 0x00001800 0x0000002e 0x0000002e 0x3fcb2dac
3fcb2cb0: 0x498b179b 0x3fc9e87c 0x000001d0 0x3fcb905c 0x0000002e 0x3fcb8ae8 0x3fcb2d2c 0x42051348
3fcb2cd0: 0x00000006 0x3fcba018 0x3fcb9cc4 0x3fcb9cf4 0x00000006 0x3fcb2cec 0x00000000 0x00000003
3fcb2cf0: 0x3fcb79c4 0x3fcb5f08 0x00000001 0x3fcb2dac 0x00000006 0x3c3d9000 0x000001d0 0x498b179b
3fcb2d10: 0x3fc9e87c 0x3fcb905c 0x3fcb905c 0x42051c24 0x3fcb8ae4 0x3fcb8acc 0x3fca7ae0 0x3fcb8acc
3fcb2d30: 0x3fcb8ae8 0x3fcb8afa 0x3fcb2ec4 0x4204b338 0x3fcb8acc 0x3fcb8ae4 0x3fcb8ae4 0x00000002
3fcb2d50: 0x00000000 0x00000000 0x41700000 0xbaad5603 0x40a00000 0x00000003 0x00000000 0x4038ce00
3fcb2d70: 0x3fcb79c4 0x3fcb5f08 0x3c3d9000 0x3c3d9000 0x3c3d9000 0x3c3d9000 0x00000026 0x3f800000
3fcb2d90: 0x3fca7000 0x3fcb905c 0x3fcb328c 0x4204c8c8 0x00000003 0x00766964 0x00000000 0x3fcb328c
3fcb2db0: 0x3fcb9cc4 0x4204c2a0 0x4204e2a8 0x218f67b6 0x67616d69 0x3fcb0065 0x000001d0 0x3fcb7a04
3fcb2dd0: 0x3fca7000 0x3fcb328c 0x3fcb328c 0x4204cad4 0x00000000 0x00000000 0x000001d0 0x3fcb2e5c
3fcb2df0: 0x42180000 0x3fcb2e74 0x3fcb2e5c 0x4204c4d6 0x3fca7000 0x3fcb9ff8 0x3fcb2e5c 0x4204c588
3fcb2e10: 0x3c3d9000 0x3c3d9000 0x000001d0 0x3fcb7a04 0x3fca7000 0x42180000 0x3fcb328c 0x4204de26
3fcb2e30: 0x1bdadb99 0x001606fc 0x00160096 0x3fcb87dc 0x420a0f20 0x00000002 0x00000000 0x00000000
3fcb2e50: 0x00000000 0x00000000 0x00000100 0x00130000 0x00000006 0x00000000 0x00000000 0x00000000
3fcb2e70: 0x00000100 0x00000002 0x00000000 0x00000000 0x41700000 0xbaad5603 0x40a00000 0x00000003
3fcb2e90: 0x00000000 0x4038ce00 0x00000000 0x3fca7e00 0x00000000 0x40382800 0x00000000 0x3fcb5f00
3fcb2eb0: 0x00000000 0x3c3d9000 0x00000000 0x00000000 0x00002061 0x00000002 0x00000000 0x00000000
3fcb2ed0: 0x41700000 0xbaad5603 0x40a00000 0x00000003 0x00000000 0x4038ce00 0x00000000 0x3fca7e00
3fcb2ef0: 0x00000000 0x40382800 0x00000000 0x3fcb5f00 0x00000000 0x3c3d9000 0x00000000 0x00000000
3fcb2f10: 0x3fcb2061 0x3fcb2f1c 0x00000005 0x67616d69 0x3c400065 0x3fcb6ef7 0x3fcb6538 0x3fcb2f34
3fcb2f30: 0x00000000 0x3fcb7900 0x00000000 0x3fcb8f38 0x3c40d9e0 0x00000000 0x3fcb5f84 0x420a1448
3fcb2f50: 0x3c40d9e0 0x00000000 0x00000000 0x420a3fde 0x3fca7000 0x00000000 0x3fcb6538 0x3fcb79f0
3fcb2f70: 0x3fcb5f84 0x00000000 0x3fcb601c 0x65694400 0x3fca7000 0x00000000 0x0000000c 0x218f67b6
3fcb2f90: 0x00000011 0x00000015 0x3fcb905c 0x00000001 0x00000001 0x00000000 0x3fcbb710 0x46bc9800
3fcb2fb0: 0x00000000 0x00005e38 0x3fcb5de8 0x420a0aba 0x0000001e 0x3fcb2fcc 0x00000000 0x00000013
3fcb2fd0: 0x00000000 0x3fcb2fdc 0x00000003 0x00766964 0x00000002 0x00000000 0x3fcb7a04 0x218f67b6
3fcb2ff0: 0x3fcb79c4 0x3fcb5f08 0x00000000 0x3fcb6538 0x3fcb5de8 0x00000001 0x00000000 0x3fcb5f04
3fcb3010: 0x3fcbb8d8 0x3fcbb701 0x3c40d9e0 0x420a606c 0x000001ff 0x3fcb5e00 0x3fcbb549 0x00000000
3fcb3030: 0x420a3730 0x00000000 0x3fcbb4d8 0x3fcbb6fd 0x3fcbb71
0 0x3fcb7a07 0x3fcbb701 0x0000000e
ELF file SHA256: d99a2cda0d418f65
Rebooting...

Copy link
Member

@daveallie daveallie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good find, thanks for this!

@daveallie daveallie merged commit ca89e41 into crosspoint-reader:master Feb 19, 2026
7 checks passed
daveallie pushed a commit that referenced this pull request Feb 19, 2026
…acters unsupported by bold/italic font variants (#997)

## Summary

* **What is the goal of this PR?** 

I flashed the last revision before commit f1740db, and chapter indexing
worked without any crashes.
After applying f1740db, the same chapter consistently triggered a
device reboot during indexing.

The affected chapter contains inline equation images surrounded by
styled (bold/italic) text that includes special math/symbol characters.

## Additional Context

Prior to f1740db, both `getTextAdvanceX()` and `getSpaceWidth()` always
measured text using `EpdFontFamily::REGULAR`, regardless of the actual
style.

Commit f1740db improved correctness by passing the active style so
spacing is calculated using the actual bold/italic font variant.

However, bold and italic variants have narrower Unicode coverage than
the regular font. When a character exists in the regular font but not in
the selected styled variant, `pdFont::getGlyph()` returns `nullptr`.

The updated measurement functions did not check for this and immediately
dereferenced the pointer:

`width += font.getGlyph(cp, style)->advanceX;   // nullptr->advanceX`


Because `advanceX` is located at byte offset 2 within `EpdGlyph`,
dereferencing a null pointer caused the CPU to attempt a load from
address `0x00000002`, resulting in a RISC-V:
Load access fault
MCAUSE = 5
MTVAL = 2


## Fix

Added null-safety checks to both `getTextAdvanceX()` and
`getSpaceWidth()`, following the same pattern used in the rendering
path:

If the glyph is missing in the selected style → fall back to the
replacement glyph.

If the replacement glyph is also unavailable → treat the character as
zero-width.

This preserves the improved style-correct spacing while preventing
crashes.
No behavioral changes occur for characters that are supported by the
selected font variant.

---

### AI Usage

Did you use AI tools to help write this code? _**< YES >**_
I encounter this bug while testing 1.1.0 RC. 
I pasted the serial log to Claude, which identify the bug and fixed it.
I can confirm now the chapter in question is indexed and loaded
correctly.
@Uri-Tauber Uri-Tauber deleted the fix/load-access-fault branch February 19, 2026 16:48
saslv pushed a commit to saslv/crosspoint-reader that referenced this pull request Feb 19, 2026
…acters unsupported by bold/italic font variants (crosspoint-reader#997)

## Summary

* **What is the goal of this PR?** 

I flashed the last revision before commit f1740db, and chapter indexing
worked without any crashes.
After applying f1740db, the same chapter consistently triggered a
device reboot during indexing.

The affected chapter contains inline equation images surrounded by
styled (bold/italic) text that includes special math/symbol characters.

## Additional Context

Prior to f1740db, both `getTextAdvanceX()` and `getSpaceWidth()` always
measured text using `EpdFontFamily::REGULAR`, regardless of the actual
style.

Commit f1740db improved correctness by passing the active style so
spacing is calculated using the actual bold/italic font variant.

However, bold and italic variants have narrower Unicode coverage than
the regular font. When a character exists in the regular font but not in
the selected styled variant, `pdFont::getGlyph()` returns `nullptr`.

The updated measurement functions did not check for this and immediately
dereferenced the pointer:

`width += font.getGlyph(cp, style)->advanceX;   // nullptr->advanceX`


Because `advanceX` is located at byte offset 2 within `EpdGlyph`,
dereferencing a null pointer caused the CPU to attempt a load from
address `0x00000002`, resulting in a RISC-V:
Load access fault
MCAUSE = 5
MTVAL = 2


## Fix

Added null-safety checks to both `getTextAdvanceX()` and
`getSpaceWidth()`, following the same pattern used in the rendering
path:

If the glyph is missing in the selected style → fall back to the
replacement glyph.

If the replacement glyph is also unavailable → treat the character as
zero-width.

This preserves the improved style-correct spacing while preventing
crashes.
No behavioral changes occur for characters that are supported by the
selected font variant.

---

### AI Usage

Did you use AI tools to help write this code? _**< YES >**_
I encounter this bug while testing 1.1.0 RC. 
I pasted the serial log to Claude, which identify the bug and fixed it.
I can confirm now the chapter in question is indexed and loaded
correctly.
el pushed a commit to el/crosspoint-reader that referenced this pull request Feb 19, 2026
…acters unsupported by bold/italic font variants (crosspoint-reader#997)

## Summary

* **What is the goal of this PR?** 

I flashed the last revision before commit f1740db, and chapter indexing
worked without any crashes.
After applying f1740db, the same chapter consistently triggered a
device reboot during indexing.

The affected chapter contains inline equation images surrounded by
styled (bold/italic) text that includes special math/symbol characters.

## Additional Context

Prior to f1740db, both `getTextAdvanceX()` and `getSpaceWidth()` always
measured text using `EpdFontFamily::REGULAR`, regardless of the actual
style.

Commit f1740db improved correctness by passing the active style so
spacing is calculated using the actual bold/italic font variant.

However, bold and italic variants have narrower Unicode coverage than
the regular font. When a character exists in the regular font but not in
the selected styled variant, `pdFont::getGlyph()` returns `nullptr`.

The updated measurement functions did not check for this and immediately
dereferenced the pointer:

`width += font.getGlyph(cp, style)->advanceX;   // nullptr->advanceX`


Because `advanceX` is located at byte offset 2 within `EpdGlyph`,
dereferencing a null pointer caused the CPU to attempt a load from
address `0x00000002`, resulting in a RISC-V:
Load access fault
MCAUSE = 5
MTVAL = 2


## Fix

Added null-safety checks to both `getTextAdvanceX()` and
`getSpaceWidth()`, following the same pattern used in the rendering
path:

If the glyph is missing in the selected style → fall back to the
replacement glyph.

If the replacement glyph is also unavailable → treat the character as
zero-width.

This preserves the improved style-correct spacing while preventing
crashes.
No behavioral changes occur for characters that are supported by the
selected font variant.

---

### AI Usage

Did you use AI tools to help write this code? _**< YES >**_
I encounter this bug while testing 1.1.0 RC. 
I pasted the serial log to Claude, which identify the bug and fixed it.
I can confirm now the chapter in question is indexed and loaded
correctly.
lukestein pushed a commit to lukestein/crosspoint-reader that referenced this pull request Feb 20, 2026
…acters unsupported by bold/italic font variants (crosspoint-reader#997)

## Summary

* **What is the goal of this PR?** 

I flashed the last revision before commit f1740db, and chapter indexing
worked without any crashes.
After applying f1740db, the same chapter consistently triggered a
device reboot during indexing.

The affected chapter contains inline equation images surrounded by
styled (bold/italic) text that includes special math/symbol characters.

## Additional Context

Prior to f1740db, both `getTextAdvanceX()` and `getSpaceWidth()` always
measured text using `EpdFontFamily::REGULAR`, regardless of the actual
style.

Commit f1740db improved correctness by passing the active style so
spacing is calculated using the actual bold/italic font variant.

However, bold and italic variants have narrower Unicode coverage than
the regular font. When a character exists in the regular font but not in
the selected styled variant, `pdFont::getGlyph()` returns `nullptr`.

The updated measurement functions did not check for this and immediately
dereferenced the pointer:

`width += font.getGlyph(cp, style)->advanceX;   // nullptr->advanceX`


Because `advanceX` is located at byte offset 2 within `EpdGlyph`,
dereferencing a null pointer caused the CPU to attempt a load from
address `0x00000002`, resulting in a RISC-V:
Load access fault
MCAUSE = 5
MTVAL = 2


## Fix

Added null-safety checks to both `getTextAdvanceX()` and
`getSpaceWidth()`, following the same pattern used in the rendering
path:

If the glyph is missing in the selected style → fall back to the
replacement glyph.

If the replacement glyph is also unavailable → treat the character as
zero-width.

This preserves the improved style-correct spacing while preventing
crashes.
No behavioral changes occur for characters that are supported by the
selected font variant.

---

### AI Usage

Did you use AI tools to help write this code? _**< YES >**_
I encounter this bug while testing 1.1.0 RC. 
I pasted the serial log to Claude, which identify the bug and fixed it.
I can confirm now the chapter in question is indexed and loaded
correctly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants