Bug 102607

Summary: NULL pointer dereference vulnerability in poppler 0.59.0 Annot.cc AnnotRichMedia::Configuration::Configuration()
Product: poppler Reporter: Ziqiang Gu <etovio>
Component: generalAssignee: poppler-bugs <poppler-bugs>
Status: RESOLVED FIXED QA Contact:
Severity: major    
Priority: medium    
Version: unspecified   
Hardware: x86-64 (AMD64)   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:
Attachments: POC file of the vulnerability

Description Ziqiang Gu 2017-09-08 07:37:27 UTC
Created attachment 134071 [details]
POC file of the vulnerability

A NULL pointer dereference vulnerability was found in poppler Annot.cc AnnotRichMedia::Configuration::Configuration() which may lead to potential Denial of Service attack when handling malicious PDF files:

gzq@ubuntu:~/work/vul/poppler$ /home/gzq/install/poppler-dev/bin/pdftohtml -s ./mal-Annot-cc-6770-3-16.pdf a
Syntax Error: End of file inside dictionary
Syntax Warning: No valid XRef size in trailer
Syntax Error (1884): Dictionary key must be a name object
Syntax Error: Unterminated string
Syntax Error: End of file inside array
Syntax Error: End of file inside dictionary
Syntax Error: End of file inside array
Syntax Error: End of file inside dictionary
Segmentation fault

The Configuation() function code is as below:
AnnotRichMedia::Configuration::Configuration(Dict *dict)
{
  Object obj1 = dict->lookup("Instances");
  if (obj1.isArray()) {
    nInstances = obj1.arrayGetLength();

    instances = (Instance **)gmallocn(nInstances, sizeof(Instance *));

    for (int i = 0; i < nInstances; ++i) {
      Object obj2 = obj1.arrayGet(i);
      if (obj2.isDict()) {
        instances[i] = new AnnotRichMedia::Instance(obj2.getDict());
      } else {
        instances[i] = NULL;
      }
    }
  } else {
    instances = NULL;
  }

  obj1 = dict->lookup("Name");
  if (obj1.isString()) {
    name = new GooString(obj1.getString());
  } else {
    name = NULL;
  }

  obj1 = dict->lookup("Subtype");
  if (obj1.isName()) {
    const char *name = obj1.getName();

    if (!strcmp(name, "3D")) {
      type = type3D;
    } else if (!strcmp(name, "Flash")) {
      type = typeFlash;
    } else if (!strcmp(name, "Sound")) {
      type = typeSound;
    } else if (!strcmp(name, "Video")) {
      type = typeVideo;
    } else {
      // determine from first instance
      if (instances && nInstances > 0) {
        AnnotRichMedia::Instance *instance = instances[0];
        switch (instance->getType()) {
          case AnnotRichMedia::Instance::type3D:
            type = type3D;
            break;
          case AnnotRichMedia::Instance::typeFlash:
            type = typeFlash;
            break;
          case AnnotRichMedia::Instance::typeSound:
            type = typeSound;
            break;
          case AnnotRichMedia::Instance::typeVideo:
            type = typeVideo;
            break;
          default:
            type = typeFlash;
            break;
        }
      }
    }
  }
}

From the for() loop we can see that it is possible that instances[i] is set to NULL if a crafted PDF file is being handled, but the following call instance->getType() is not aware of it.

This vulnerability has been reproduced in both the latest stable release 0.59.0 and the latest code in the repository. xpdf also affected.

A pdf file has been attached to help to reproduce this vulnerability.
Comment 1 Albert Astals Cid 2017-09-08 16:30:31 UTC
Fixed, thanks :)

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.