aboutsummaryrefslogtreecommitdiffstats
path: root/fuzz/CMakeLists.txt
blob: e4a8cf36ed91f9bc8c0f7a3c51e9571041559701 (plain) (blame)
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# This directory contains support for Google's oss-fuzz project. See
# https://github.com/google/oss-fuzz/tree/master/projects/qpdf

set(FUZZERS
  qpdf_fuzzer
  ascii85_fuzzer
  dct_fuzzer
  flate_fuzzer
  hex_fuzzer
  lzw_fuzzer
  pngpredictor_fuzzer
  runlength_fuzzer
  tiffpredictor_fuzzer)

# The oss-fuzz project provides LIB_FUZZING_ENGINE and OUT environment
# variables. For local testing, provide values if not set.
set(LIB_FUZZING_ENGINE $ENV{LIB_FUZZING_ENGINE})
if(NOT LIB_FUZZING_ENGINE)
  # When running from oss-fuzz, LIB_FUZZING_ENGINE points to a
  # static library that contains main.
  add_library(standalone_fuzzer STATIC standalone_fuzz_target_runner.cc)
  target_include_directories(
    standalone_fuzzer PRIVATE ${qpdf_SOURCE_DIR}/include)
  set(LIB_FUZZING_ENGINE standalone_fuzzer)
endif()
set(FUZZ_OUT $ENV{OUT})
if(NOT FUZZ_OUT)
  set(FUZZ_OUT ${CMAKE_CURRENT_BINARY_DIR}/fuzz-install)
endif()

if(OSS_FUZZ)
  # We need to link jpeg and zlib statically for oss-fuzz. Construct
  # our own object library without the external dependencies and add
  # what we need.
  add_library(libqpdf_fuzz STATIC $<TARGET_OBJECTS:libqpdf_object>)
  target_link_libraries(libqpdf_fuzz INTERFACE libjpeg.a libz.a)
  target_include_directories(libqpdf_fuzz
    PUBLIC
    ${JPEG_INCLUDE}
    ${qpdf_SOURCE_DIR}/include
    ${qpdf_SOURCE_DIR}/libqpdf)
else()
  add_library(libqpdf_fuzz ALIAS libqpdf_object)
endif()

foreach(PROG ${FUZZERS})
  add_executable(${PROG} ${PROG}.cc)
  target_link_libraries(${PROG} ${LIB_FUZZING_ENGINE})
  target_link_libraries(${PROG} libqpdf_fuzz)
endforeach()

# Files from the test suite that are good for seeding the fuzzer.
# Update count for qpdf in @fuzzers qtest/fuzz.test if you change this list.
set(CORPUS_FROM_TEST
  stream-data.pdf
  lin5.pdf
  field-types.pdf
  image-streams-small.pdf
  need-appearances.pdf
  outlines-with-actions.pdf
  outlines-with-old-root-dests.pdf
  page-labels-and-outlines.pdf
  page-labels-num-tree.pdf
  dr-with-indirect-item.pdf
  fuzz-16214.pdf
  issue-99b.pdf
  issue-99.pdf
  issue-100.pdf
  issue-101.pdf
  issue-106.pdf
  issue-117.pdf
  issue-119.pdf
  issue-120.pdf
  issue-141a.pdf
  issue-141b.pdf
  issue-143.pdf
  issue-146.pdf
  issue-147.pdf
  issue-148.pdf
  issue-149.pdf
  issue-150.pdf
  issue-202.pdf
  issue-263.pdf
  issue-335a.pdf
  issue-335b.pdf)

# Any file that qpdf_fuzzer should be tested with can be named
# something.fuzz and dropped into qpdf_extra. Update count for qpdf in
# @fuzzers qtest/fuzz.test if you change this list.
set(CORPUS_OTHER
  15316.fuzz
  15387.fuzz
  15390.fuzz
  15442.fuzz
  15445.fuzz
  15983.fuzz
  16172.fuzz
  16301.fuzz
  16953.fuzz
  18241.fuzz
  18247.fuzz
  23172.fuzz
  23599.fuzz
  23642.fuzz
  23642-mod.fuzz
  26761.fuzz
  26994.fuzz
  27393.fuzz
  28262.fuzz
  30507.fuzz
  37740.fuzz
  57639.fuzz
  65681.fuzz
  65773.fuzz
  65777.fuzz
)

set(CORPUS_DIR ${CMAKE_CURRENT_BINARY_DIR}/qpdf_corpus)
file(MAKE_DIRECTORY ${CORPUS_DIR})
function(copy_fuzz FROM)
  file(SHA1 ${FROM} SHA)
  set(OUT ${CORPUS_DIR}/${SHA})
  add_custom_command(
    OUTPUT ${OUT}
    COMMAND ${COPY_COMMAND} $<SHELL_PATH:${FROM}> $<SHELL_PATH:${OUT}>)
  set(CORPUS_FILE ${OUT} PARENT_SCOPE)
endfunction()

list(APPEND CORPUS_FILES)
foreach(F ${CORPUS_FROM_TEST})
  copy_fuzz(${qpdf_SOURCE_DIR}/qpdf/qtest/qpdf/${F})
  list(APPEND CORPUS_FILES ${CORPUS_FILE})
endforeach()
foreach(F ${CORPUS_OTHER})
  copy_fuzz(${CMAKE_CURRENT_SOURCE_DIR}/qpdf_extra/${F})
  list(APPEND CORPUS_FILES ${CORPUS_FILE})
endforeach()
add_custom_target(qpdf_corpus ALL
  DEPENDS ${CORPUS_FILES})

add_test(
  NAME fuzz
  COMMAND ${RUN_QTEST}
  --env QPDF_FUZZ_CORPUS=${CORPUS_DIR}
  --top ${qpdf_SOURCE_DIR}
  --bin $<TARGET_FILE_DIR:qpdf_fuzzer>
  --bin $<TARGET_FILE_DIR:qpdf>
  --code ${qpdf_SOURCE_DIR}/fuzz
  --color ${QTEST_COLOR}
  --show-on-failure ${SHOW_FAILED_TEST_OUTPUT})

if(OSS_FUZZ)
  list(APPEND SEED_CORPUS_ZIPS)
  foreach(F ${FUZZERS})
    if(F STREQUAL qpdf_fuzzer)
      set(SEED_DIR ${CORPUS_DIR})
    else()
      set(SEED_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${F}_seed_corpus)
    endif()
    set(SEED_ZIP ${CMAKE_CURRENT_BINARY_DIR}/${F}_seed_corpus.zip)
    add_custom_command(OUTPUT ${SEED_ZIP}
      COMMAND zip -q -r ${SEED_ZIP} .
      WORKING_DIRECTORY ${SEED_DIR})
    list(APPEND SEED_CORPUS_ZIPS ${SEED_ZIP})
  endforeach()
  add_custom_target(seed_corpus_zips ALL DEPENDS ${SEED_CORPUS_ZIPS})
  add_dependencies(seed_corpus_zips qpdf_corpus)
  add_custom_target(fuzzers)
  add_dependencies(fuzzers ${FUZZERS} seed_corpus_zips)
  install(
    TARGETS ${FUZZERS}
    DESTINATION ${FUZZ_OUT}
    EXCLUDE_FROM_ALL
    COMPONENT fuzz)
  install(
    FILES
    ${CMAKE_CURRENT_SOURCE_DIR}/pdf.dict
    ${CMAKE_CURRENT_SOURCE_DIR}/qpdf_fuzzer.options
    ${SEED_CORPUS_ZIPS}
    DESTINATION ${FUZZ_OUT}
    EXCLUDE_FROM_ALL
    COMPONENT fuzz)
endif()