bugtex4ht - Bugs: bug #611, Random SIGSEGV of tex4ht due to...

Show feedback again

You are not allowed to post comments on this tracker with your current authentification level.

bug #611: Random SIGSEGV of tex4ht due to invalid memory accesses

Submitted by:  Oliver Freyermuth <olifre>
Submitted on:  Thu Oct 5 19:31:55 2023  
Category: NonePriority: 5 - Normal
Severity: 7 - ImportantStatus: Ready For Test
Privacy: PublicAssigned to: None
Open/Closed: Closed

(Jump to the original submission Jump to the original submission)

Sun Oct 15 21:38:13 2023, comment #6:

Hi Oliver - I can't easily rebuild the musl binaries, so waiting for TL24 looks like the current state. And good luck with Gentoo.

I'm really glad you dug into this to find these hard-to-pin-down errors. Thanks again. Happy converting :).

Karl Berry <karl>
Project Administrator
Sat Oct 14 21:33:57 2023, comment #5:

Hi again Karl,

many thanks! I don't see any problem with the memset call, and can confirm this also makes valgrind blissfully silent on my end when applying the patches to tex4ht on my local desktop (Gentoo Linux). I tested with various documents and various parameters and found no problems.

Since Gentoo currently seems to package an old snapshot of tex4ht based on a not-directly-upstream source, I have pinged the corresponding maintainer to pull in the fixes or ideally just switch to upstream ( for reference: https://bugs.gentoo.org/915782 ).

In my CI/CD pipeline which I am running via GitHub actions to produce HTML pages for deployment with GitHub pages, I am actually relying on Docker containers based on Alpine Linux with Texlive binaries installed via tlmgr. Hence, that would be x86_64-linuxmusl binaries. In case those are easy for you to build, of course that would be appreciated, if not, waiting for TL24 is also fine for me (it's not that far off, and knowing the issue is fixed for good makes me very happy :-) ).

Cheers and many thanks for fixing things so quickly!

Oliver Freyermuth <olifre>
Fri Oct 13 22:47:26 2023, comment #4:

Hi again Oliver - well, I couldn't discern any plausible way to initialize the htf_4hf array on the fly, so I just memset the whole array to zero after it is allocated. That is, after this line:

htf_4hf = m_alloc(struct htf_4hf_rec, 256);

I added (some comments and):
memset (htf_4hf, 0, 256 * sizeof (struct htf_4hf_rec));

and valgrind was blessedly silent afterwards. The HTML output on your sample file was unchanged. I didn't test anything else specifically.

It's been a while since I called memset by hand :), so please do let me know if you see problems. (Eitan never wrote a wrapper for calloc as he did for malloc, so this seemed the simplest way.)

I also committed the new source to TL, r68541.

And I also installed a new tex4ht binary for x86_64-linux (only) since, well, why not (r68542). I'm not sure if you are building from source or using our binaries. Let me know if I need to do more to propagate the fix so you'll get it.

Thanks again for doing all the real work here.

Karl Berry <karl>
Project Administrator
Thu Oct 12 22:42:33 2023, comment #3:

Hi Karl,

many thanks! That does indeed look very reasonable (and straightforward) as a fix. Testing it locally expectedly also removes the invalid read on my machine :-).

Thanks to you for taking care of this (very valuable) tool and of the report so quickly!

Since the main place in which I have hit the "Illegal storage address" issue is in a CI/CD environment which uses monthly texlive snapshots (via containers), I'll then automatically get the fix in there with the next monthly snapshot once it is in texlive.

Thanks a lot, and keeping my fingers crossed hoping the fix for the uninitialized values is also not too much effort,

Oliver Freyermuth <olifre>
Thu Oct 12 16:17:24 2023, comment #2:

Hi Oliver - thanks again for all the debugging. Due to all your work, I think the fix for the invalid read is pretty simple:

&& cur_fnt >= 0

before the condition indexing font_tbl, to avoid the negative indexing. That is, change that line to be:

&& cur_fnt >= 0 && (default_font != font_tbl[cur_fnt].num) ){

Committed to the tex4ht repo in r1387. I'll update the TeX Live repo in a bit.

(The diff is obscured by thousands of unimportant #line changes, so not bothering to send that.)

cur_fnt is initialized to -1. So this happens when that test is made before any font (DVI fntdef command) has been seen, which is the case with your test dvi. It's not clear to me which of the many DVI specials (xxx opcodes) is being executed at the time of the test, but I think it doesn't matter. We can just protect against it.

After doing that, valgrind no longer complains about the invalid read (for me).

As long as I'm here, I'll look into the uninitialized values too, but thought I'd send this first.

Thanks again.

Karl Berry <karl>
Project Administrator
Thu Oct 5 20:41:51 2023, comment #1:

THank you very much for all that debugging! I will see if I can patch the source as soon as possible.

Karl Berry <karl>
Project Administrator
Thu Oct 5 19:31:55 2023, original submission:

I've been haunted by "Illegal storage address" for large documents with many fonts for quite a while (coming and going with tex4ht releases and even changing depending on shell environment), and often, unrelated changes in the document (e.g. reducing fonts) fix it.

I believe I have finally hunted down the underlying issue to an invalid memory access in tex4ht — reproducible with an MWE (which does not crash), visible with valgrind / gdb.


1) Create foo.tex with content:


2) Run:
make4ht --utf8 --output-dir html foo

3) Re-run the tex4ht step with valgrind:
valgrind tex4ht -cmozhtf -utf8 foo.dvi

This reveals:
==4487== Conditional jump or move depends on uninitialised value(s)
==4487== at 0x10EE14: main (tex4ht.c:8099)
==4487== (action on error) vgdb me ...
==4487== Continuing ...
==4487== Conditional jump or move depends on uninitialised value(s)
==4487== at 0x10EE16: main (tex4ht.c:8108)
==4487== (action on error) vgdb me ...
==4487== Continuing ...
==4487== Invalid read of size 4
==4487== at 0x10E794: main (tex4ht.c:8741)
==4487== Address 0x8beb1f8 is 8 bytes before a block of size 2 alloc'd
==4487== at 0x48407C4: malloc (vg_replace_malloc.c:431)
==4487== by 0x11851B: malloc_chk (tex4ht.c:1481)
==4487== by 0x10EC30: main (tex4ht.c:7104)

The invalid read is most worrisome, it originates from the source lines:

8740 if( span_on && !in_span_ch && !ignore_chs && !in_accenting
8741 && (default_font != font_tbl[cur_fnt].num) ){

It is caused by the part:
(default_font != font_tbl[cur_fnt].num)
being evaluated, while the index cur_fmt is negative:

(gdb) p default_font
$12 = -1
(gdb) p cur_fnt
$13 = -1

This yields an invalid read. If the document has many (many!) fonts, the dynamically allocated and subsequently freed memory from opendir/closedir looking for the htf files ends up right before the font_tbl array, and depending on page boundaries, this read with negative index may yield an invalid read / SIGSEGV.

Since I don't understand the full logic of the code, I'm not fit to propose a (good) fix.

It seems this might be affecting other users, too, looking for reports of "Illegal storage address" on tex stackexchange which in some cases were "fixed" by unrelated document changes.

Nota bene:
The two "Conditional jump or move depends on uninitialised value(s)" are from the lines:
if( value == htf_4hf[mid].ch ){
} else if( value < htf_4hf[mid].ch ){
since htf_4hf seems to be used (in some cases) before being initialized. This does not lead to a crash, though, since it's not an invalid read.

Oliver Freyermuth <olifre>


No files currently attached


Depends on the following items: None found

Items that depend on this one: None found


Carbon-Copy List
  • -unavailable- added by karl (Posted a comment)
  • -unavailable- added by olifre (Submitted the item)

    Do you think this task is very important?
    If so, you can click here to add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.


    Please enter the title of George Orwell's famous dystopian book (it's a date):



    2 latest changes follow.

    Date Changed By Updated Field Previous Value => Replaced By
    Sun Oct 15 21:38:13 2023karlOpen/ClosedOpen=>Closed
    Fri Oct 13 22:47:26 2023karlStatusNone=>Ready For Test
    Show feedback again

    Back to the top

    Powered by Savane 3.1-cleanup+gray