PDF-Writer icon indicating copy to clipboard operation
PDF-Writer copied to clipboard

Memory Leaks & Heap Use After Free

Open gnat42 opened this issue 5 years ago • 1 comments

Hello,

I recently wrote an application that uses PDF-Writer. The library is pretty awesome. After I started getting some odd crashes here and there from within the library I started digging into that. I started compiling the library using AddressSanitizer. On a Linux machine (Fedora f30) I ran the following to compile PDFWriter and the tests.

make .. -DCMAKE_CXX_FLAGS="-fno-omit-frame-pointer -fsanitize=address -fsanitize-recover=address -fsanitize=leak -O1 -g" -DCMAKE_C_FLAGS="fno-omit-frame-pointer -fsanitize=address -fsanitize-recover=address -fsanitize=leak -g -O1" -DCMAKE_EXE_LINKER_FLAGS="fno-omit-frame-pointer -fsanitize=address -fsanitize-recover=address -fsanitize=leak -lasan" -DCMAKE_MODULE_LINKER_FLAGS="fno-omit-frame-pointer -fsanitize=address -fsanitize-recover=address -fsanitize=leak -lasan"

Then when I run the PDFWriterTestPlayground I get a lot of heap-use-after-free errors. Most of which I'm not really sure how to solve. It would be fantastic if you could go through some of those.

However, there is a definite memory leak as well. The following test program

//
//  main.cpp
//  PdfWriterPdfHasher
//
//  Created by Nathanael Noblet on 2019-06-29.
//  Copyright © 2019 Nathanael Noblet. All rights reserved.
//

#include <iostream>
#include <cstring>
#include <PDFWriter/InputFile.h>
#include <PDFWriter/PDFParser.h>
#include <PDFWriter/PDFDictionary.h>
#include <PDFWriter/PDFIndirectObjectReference.h>
#include <PDFWriter/RefCountPtr.h>

int main(int argc, const char * argv[]) {
    long long mObjectPosition = 0;
    InputFile inFile;
    PDFParser parser;
    RefCountPtr<PDFDictionary> trailer;
    
    if (argc <= 1) {
        std::cout << "Invalid number of arguments\n";
        return -1;
    }
    
    for (int x=1; x < argc ; x++) {
        mObjectPosition = 0;
        std::string inputFilePath(argv[x]);
        inFile.OpenFile(inputFilePath);
        parser.StartPDFParsing(inFile.GetInputStream());

        trailer = parser.GetTrailer();

        if (trailer != NULL && trailer->Exists("Info")) {
            PDFIndirectObjectReference *info = (PDFIndirectObjectReference*)trailer->QueryDirectObject("Info");
            XrefEntryInput* infoXrefEntry = parser.GetXrefEntry(info->mObjectID);
            mObjectPosition = (long long)infoXrefEntry->mObjectPosition;
            inFile.CloseFile();
        }
        
        std::cout << argv[x] << "\tInfo Position: " << mObjectPosition << "\n";
    }
    
    return 0; 
}

Compiled with g++ as follows

 g++ -g -O2 -fsanitize=address -fno-omit-frame-pointer cli.cpp -o pdfhasher -lasan -lPDFWriter

I then have a directory with 30-40 PDFs and run ./pdfhash ~/Path/*pdf

The output I get is:

DOCNAME.... HASH
....

=================================================================
==16867==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 1848 byte(s) in 21 object(s) allocated from:
    #0 0x7ff7f3df3a27 in operator new(unsigned long) (/lib64/libasan.so.5+0x10fa27)
    #1 0x7ff7f3c4f791 in PDFObjectParser::ParseNewObject() /usr/src/debug/pdf-writer-4.0-1.fc30.x86_64/PDFWriter/PDFObjectParser.cpp:188
    #2 0x7ff7f30951ff in BZ2_decompress decompress.c:206

Direct leak of 1144 byte(s) in 13 object(s) allocated from:
    #0 0x7ff7f3df3a27 in operator new(unsigned long) (/lib64/libasan.so.5+0x10fa27)
    #1 0x7ff7f3c4f791 in PDFObjectParser::ParseNewObject() /usr/src/debug/pdf-writer-4.0-1.fc30.x86_64/PDFWriter/PDFObjectParser.cpp:188
    #2 0x7ff7f3093e00 in BZ2_decompress decompress.c:356

Direct leak of 792 byte(s) in 9 object(s) allocated from:
    #0 0x7ff7f3df3a27 in operator new(unsigned long) (/lib64/libasan.so.5+0x10fa27)
    #1 0x7ff7f3c4f791 in PDFObjectParser::ParseNewObject() /usr/src/debug/pdf-writer-4.0-1.fc30.x86_64/PDFWriter/PDFObjectParser.cpp:188
    #2 0x7ff7f3092f00 in bsW compress.c:75
    #3 0x7ff7f3092f00 in sendMTFValues compress.c:575
    #4 0x7ff7f3092f00 in BZ2_compressBlock compress.c:652

SUMMARY: AddressSanitizer: 3784 byte(s) leaked in 43 allocation(s).

I'm wondering if you have thoughts on this particular memory leak.

Thanks

gnat42 avatar Jul 11 '19 21:07 gnat42

looks like I needed to delete my PdfIndirectObjectReference *info... So that's the memory leak. However I'd still suggest that you run the playground through the sanitizer there are other issues.

gnat42 avatar Jul 11 '19 22:07 gnat42