This file is indexed.

/usr/share/fusil/fusil-gimp is in fusil 1.5-1.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#! /usr/bin/python
"""
Gimp fuzzer.
"""

from __future__ import print_function, with_statement
from fusil.application import Application
from optparse import OptionGroup
from fusil.process.create import CreateProcess
from fusil.process.watch import WatchProcess
from fusil.process.stdout import WatchStdout
from fusil.auto_mangle import AutoMangle
from fusil.dummy_mangle import DummyMangle
from os.path import basename

PROGRAM = 'gimp'
NB_FILES = 25
MAX_FILESIZE = 1024*1024

class Fuzzer(Application):
    NAME = "gimp"
    USAGE = "%prog [options] image1 [image2 ...]"
    NB_ARGUMENTS = (1, None)

    def createFuzzerOptions(self, parser):
        options = OptionGroup(parser, "Gimp")
        options.add_option("--nb-files", help="Number of generated files (default: %s)" % NB_FILES,
            type="int", default=NB_FILES)
        options.add_option("--program", help="Gimp program path (default: %s)" % PROGRAM,
            type="str", default=PROGRAM)
        options.add_option("--filesize", help="Maximum file size in bytes (default: %s)" % MAX_FILESIZE,
            type="int", default=MAX_FILESIZE)
        options.add_option("--test", help="Test mode (no fuzzing, just make sure that the fuzzer works)",
            action="store_true")
        return options

    def setupProject(self):
        if self.options.test:
            DummyMangle(self.project, self.arguments)
        else:
            mangle = AutoMangle(self.project, self.arguments, self.options.nb_files)
            mangle.max_size = self.options.filesize

        # Create the process
        arguments = [self.options.program,
            '--no-interface',
#            '--verbose',
            '--batch-interpreter', 'plug-in-script-fu-eval',
            '--batch', '-']
        process = GimpProcess(self.project, arguments)
        WatchProcess(process)
        stdout = WatchStdout(process)
        stdout.ignoreRegex('fatal parse error')
        # > Error: Procedure execution of gimp-file-load failed: This XCF file is corrupt!
        # I could not even salvage any partial image data from it.
        stdout.ignoreRegex('file is corrupt')
        stdout.max_nb_line = None
        del stdout.words['warning']
        del stdout.words['error']

class GimpProcess(CreateProcess):
    def init(self):
        CreateProcess.init(self)
        self.script_filename = None

    def on_mangle_filenames(self, filenames):
        self.script_filename = self.session().createFilename("script")
        filenames_str = ' '.join('"%s"' % basename(filename) for filename in filenames)
        with open(self.script_filename, "w") as fp:
            print('(gimp-message "Start Gimp fuzzer")', file=fp)
            print('(define (fuzzfiles n f)', file=fp)
            print('  (let* (', file=fp)
            print('       (fname (car f))', file=fp)
            print('       (img 0)', file=fp)
            print('    )', file=fp)
            print('    (gimp-message fname)', file=fp)
            print('    (set! img (car (gimp-file-load RUN-NONINTERACTIVE fname fname)))', file=fp)
            print('    (gimp-image-delete img)', file=fp)
            print('    (if (= n 1) 1 (fuzzfiles (- n 1) (cdr f)))', file=fp)
            print('  )', file=fp)
            print(')', file=fp)
            print("(fuzzfiles %s '(%s))" % (len(filenames), filenames_str), file=fp)
            print('(gimp-quit 0)', file=fp)
        self.createProcess()

    def createStdin(self):
        return open(self.script_filename, 'rb')

if __name__ == "__main__":
    Fuzzer().main()