Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • P poppler
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 656
    • Issues 656
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 42
    • Merge requests 42
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Monitor
    • Monitor
    • Incidents
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • poppler
  • poppler
  • Issues
  • #846

Closed
Open
Created Nov 28, 2019 by Michal@misoContributor

Manipulation with global linked list from multiple threads not protected by mutex

In CairoFontEngine.cc exists global linked list which is manipulated by _ft_new_face and _ft_done_face

#ifdef CAN_CHECK_OPEN_FACES
static struct _ft_face_data {
  struct _ft_face_data *prev, *next, **head;

  int fd;
  unsigned long hash;
  size_t size;
  unsigned char *bytes;

  FT_Library lib;
  FT_Face face;
  cairo_font_face_t *font_face;
} *_ft_open_faces;
  for (l = _ft_open_faces; l; l = l->next) {
    if (_ft_face_data_equal (l, &tmpl)) {
      if (tmpl.fd != -1) {
#if defined(__SUNPRO_CC) && defined(__sun) && defined(__SVR4)
        munmap ((char*)tmpl.bytes, tmpl.size);
#else
        munmap (tmpl.bytes, tmpl.size);
#endif
        close (tmpl.fd);
      } else {
	gfree (tmpl.bytes);
      }
      *face_out = l->face;
      *font_face_out = cairo_font_face_reference (l->font_face);
      return gTrue;
    }
  }

Attached test_mt_sigsegv.zip

Output from GDB:

Thread 4 "a.out" received signal SIGSEGV, Segmentation fault.

INT_cairo_font_face_reference (font_face=0x3200000008) at ../../../../src/cairo-font-face.c:125
125	../../../../src/cairo-font-face.c: No such file or directory.
#0  0x00007ffff756f7e8 in INT_cairo_font_face_reference (font_face=0x3200000008) at ../../../../src/cairo-font-face.c:125
#1  0x00007ffff7baf621 in _ft_new_face(FT_Library, char const*, char*, int, FT_Face*, cairo_font_face_t**) (lib=lib@entry=0x7fffc0001600, filename=filename@entry=0x0, font_data=font_data@entry=0x7fffe4064e50 "true", font_data_len=<optimized out>, face_out=face_out@entry=0x7fffefadb490, font_face_out=font_face_out@entry=0x7fffefadb498) at ./poppler/CairoFontEngine.cc:331
#2  0x00007ffff7bafd5a in CairoFreeTypeFont::create(GfxFont*, XRef*, FT_LibraryRec_*, bool) (gfxFont=gfxFont@entry=0x7fffe403a370, xref=xref@entry=0x7fffe4034db0, lib=0x7fffc0001600, useCIDs=<optimized out>) at ./poppler/CairoFontEngine.cc:524
#3  0x00007ffff7bb05c8 in CairoFontEngine::getFont(GfxFont*, PDFDoc*, bool, XRef*) (this=0x7fffe4037040, gfxFont=0x7fffe403a370, doc=0x7fffe4001350, printing=false, xref=0x7fffe4034db0) at ./poppler/CairoFontEngine.cc:862
#4  0x00007ffff7bb117f in CairoOutputDev::updateFont(GfxState*) (this=0x7fffe4036df0, state=0x7fffe4052880) at ./poppler/CairoOutputDev.cc:668
#5  0x00007ffff6615252 in Gfx::opShowSpaceText(Object*, int) () at /usr/lib/x86_64-linux-gnu/libpoppler.so.73

I am getting this almost always instantly after run. Tested with poppler 0.62.0 on ubuntu 18.04 (and poppler 0.48.0 on debian stretch) on cpu with 12/24 cores. On other systems it may need more time. It can sometimes also end up with abort signal.

Where font_face argument to cairo_font_face_reference is arbitrary value which happened to be on stack because it can end up initialised only after is new entry added into linked list:

  l = (struct _ft_face_data *) gmallocn (1, sizeof (struct _ft_face_data));
  *l = tmpl;
  l->prev = NULL;
  l->next = _ft_open_faces;
  if (_ft_open_faces)
    _ft_open_faces->prev = l;
  _ft_open_faces = l;

  l->font_face = cairo_ft_font_face_create_for_ft_face (tmpl.face,

This is potentially security vulnerability for applications which use poppler and cairo to render in multiple threads.

tmpl = {..., font_face = 0x3200000008}

It would be no more better to reorder this in source code because compiler can reorder back. There is needed synchronisation mechanism like mutex.

The best would be to remove this global caching which is controlled by CAN_CHECK_OPEN_FACES. It would partially resolve also #845 (closed).

Edited Nov 28, 2019 by Michal
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking