github.com/unidoc/unidoc@v2.2.0+incompatible/pdf/core/fuzz_test.go (about)

     1  package core
     2  
     3  import (
     4  	"testing"
     5  )
     6  
     7  func init() {
     8  	// Uncomment when debugging to get trace logging output - to follow flow.
     9  	// common.SetLogger(common.NewConsoleLogger(common.LogLevelTrace))
    10  }
    11  
    12  // Fuzz tests based on findings with go-fuzz.
    13  
    14  // Test for a crash in
    15  // func (this *PdfParser) Trace(obj PdfObject) (PdfObject, error)
    16  // when passing a reference to a non-existing object.
    17  func TestFuzzParserTrace1(t *testing.T) {
    18  	parser := PdfParser{}
    19  	parser.rs, parser.reader, parser.fileSize = makeReaderForText(" /Name")
    20  
    21  	ref := &PdfObjectReference{ObjectNumber: -1}
    22  	obj, err := parser.Trace(ref)
    23  
    24  	// Should return non-err, and a nil object.
    25  	if err != nil {
    26  		t.Errorf("Fail, err != nil (%v)", err)
    27  	}
    28  
    29  	if _, isNil := obj.(*PdfObjectNull); !isNil {
    30  		t.Errorf("Fail, obj != PdfObjectNull (%T)", obj)
    31  	}
    32  }
    33  
    34  // Test for an endless loop when stream length referring to itself.
    35  /*
    36  Found from fuzzing creating an object like:
    37  	13 0 obj
    38  	<< /Length 13 0 R >>
    39  	stream
    40  	xxx
    41  	endstream
    42  
    43  */
    44  func TestFuzzSelfReference1(t *testing.T) {
    45  	rawText := `13 0 obj
    46  << /Length 13 0 R >>
    47  stream
    48  xxx
    49  endstream
    50  `
    51  
    52  	parser := PdfParser{}
    53  	parser.xrefs = make(XrefTable)
    54  	parser.objstms = make(ObjectStreams)
    55  	parser.rs, parser.reader, parser.fileSize = makeReaderForText(rawText)
    56  	parser.streamLengthReferenceLookupInProgress = map[int64]bool{}
    57  
    58  	// Point to the start of the stream (where obj 13 starts).
    59  	parser.xrefs[13] = XrefObject{
    60  		XREF_TABLE_ENTRY,
    61  		13,
    62  		0,
    63  		0,
    64  		0,
    65  		0,
    66  	}
    67  
    68  	_, err := parser.ParseIndirectObject()
    69  	if err == nil {
    70  		t.Errorf("Should fail with an error")
    71  	}
    72  }
    73  
    74  // Slightly more complex case where the reference number is incorrect, but still points to the same object.
    75  func TestFuzzSelfReference2(t *testing.T) {
    76  	// common.SetLogger(common.NewConsoleLogger(common.LogLevelTrace))
    77  
    78  	rawText := `13 0 obj
    79  << /Length 12 0 R >>
    80  stream
    81  xxx
    82  endstream
    83  `
    84  
    85  	parser := PdfParser{}
    86  	parser.xrefs = make(XrefTable)
    87  	parser.objstms = make(ObjectStreams)
    88  	parser.rs, parser.reader, parser.fileSize = makeReaderForText(rawText)
    89  	parser.streamLengthReferenceLookupInProgress = map[int64]bool{}
    90  
    91  	// Point to the start of the stream (where obj 13 starts).
    92  	// NOTE: using incorrect object number here:
    93  	parser.xrefs[12] = XrefObject{
    94  		XREF_TABLE_ENTRY,
    95  		12,
    96  		0,
    97  		0,
    98  		0,
    99  		0,
   100  	}
   101  
   102  	_, err := parser.ParseIndirectObject()
   103  	if err == nil {
   104  		t.Errorf("Should fail with an error")
   105  	}
   106  }
   107  
   108  // Test for problem where Encrypt pointing a reference to a non-existing object.
   109  func TestFuzzIsEncryptedFail1(t *testing.T) {
   110  	parser := PdfParser{}
   111  	parser.rs, parser.reader, parser.fileSize = makeReaderForText(" /Name")
   112  
   113  	ref := &PdfObjectReference{ObjectNumber: -1}
   114  
   115  	parser.trailer = MakeDict()
   116  	parser.trailer.Set("Encrypt", ref)
   117  
   118  	_, err := parser.IsEncrypted()
   119  	if err == nil {
   120  		t.Errorf("err == nil: %v.  Should fail.", err)
   121  		return
   122  	}
   123  }
   124  
   125  // Test for trailer Prev entry pointing to an incorrect object type.
   126  func TestFuzzInvalidXrefPrev1(t *testing.T) {
   127  	parser := PdfParser{}
   128  	parser.rs, parser.reader, parser.fileSize = makeReaderForText(`
   129  xref
   130  0 1
   131  0000000000 65535 f
   132  0000000001 00000 n
   133  trailer
   134  <</Info 1 0 R/Root 2 0 R/Size 17/Prev /Invalid>>
   135  startxref
   136  0
   137  %%EOF
   138  `)
   139  
   140  	_, err := parser.loadXrefs()
   141  	if err != nil {
   142  		t.Errorf("Should not error - just log a debug message regarding an invalid Prev")
   143  		t.Errorf("Err: %v", err)
   144  		return
   145  	}
   146  
   147  }