Hi Matthias,

> #0  build_goto_dest (document=<optimized out>, action=<optimized out>,
link=0x0) at \
>
/home/ports/pobj/p2/poppler-0.86.1/poppler-0.86.1/glib/poppler-action.cc:348
348      \
> if (! link->isOk ()) { [Current thread is 1 (process 435846)]
> (gdb) print link
> $1 = (const LinkGoTo *) 0x0
> (gdb) up
> #1  _poppler_action_new (document=0x280b77b5c00, link=0x2812b023d40,
title=<optimized \
> out>) at
/home/ports/pobj/p2/poppler-0.86.1/poppler-0.86.1/glib/poppler-action.cc:630
\
> 630                     build_goto_dest (document, action, dynamic_cast
<const \
> LinkGoTo *> (link)); (gdb) print link
> $2 = (const LinkAction *) 0x2812b023d40
> (gdb)

> I'm not a C++ magician, especially if it comes to things like that
> dynamic_cast, but it really looks odd to me that this pointer is
> NULL in the callee while it's not NULL in the caller.

I hope I'm not belaboring the obvious here. This condition seems a
fairly direct result of an unchecked dynamic_cast.  Per C++
dynamic_cast description:

"If the cast fails and new-type is a pointer type, it returns a null
pointer of that type."
https://en.cppreference.com/w/cpp/language/dynamic_cast

This just means that the downcast was a mistake, LinkAction* is NOT a
LinkGoTo*, but some other subclass of LinkAction of which there is a
bunch:

Link.h:161:class LinkGoTo: public LinkAction {
Link.h:187:class LinkGoToR: public LinkAction {
Link.h:216:class LinkLaunch: public LinkAction {
Link.h:240:class LinkURI: public LinkAction {
Link.h:263:class LinkNamed: public LinkAction {
Link.h:285:class LinkMovie: public LinkAction {
Link.h:324:class LinkRendition: public LinkAction {
Link.h:372:class LinkSound: public LinkAction {
Link.h:400:class LinkJavaScript: public LinkAction {
Link.h:422:class LinkOCGState: public LinkAction {
Link.h:453:class LinkHide: public LinkAction {
Link.h:486:class LinkUnknown: public LinkAction {

I don't see how this can be the case if type safety were respected.
The only place where actionGoTo is returned from getKind is in
LinkGoTo class. Though I can't say I'm surprised, the number of
static_cast and C-style casts around these types is so high
I won't expect any type safety in the program.

If one wanted to paper over the problem they could rewrite
_poppler_action_new
"defensively" and make the program fallback locally to
POPPLER_ACTION_NONE. This would avoid the crash, but I suspect the
memory is borked by that point and something else will crash instead.

Out of curiosity, is MALLOC_OPTIONS any help? If repro is easy, maybe
rebuild on an OS with ASan support and see what you get from that?

Thanks
Greg

-- 
nest.cx is Gmail hosted, use PGP:
https://pgp.key-server.io/0x0B1542BD8DF5A1B0
Fingerprint: 5E2B 2D0E 1E03 2046 BEC3  4D50 0B15 42BD 8DF5 A1B0

Reply via email to