aboutsummaryrefslogtreecommitdiffstats
path: root/fuzz/build.mk
blob: ac38457699c139b719841ed5b710cec2d5483eca (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
# This directory contains support for Google's oss-fuzz project. See
# https://github.com/google/oss-fuzz/tree/master/projects/qpdf

FUZZERS = \
    qpdf_fuzzer \
    ascii85_fuzzer \
    dct_fuzzer \
    flate_fuzzer \
    hex_fuzzer \
    lzw_fuzzer \
    pngpredictor_fuzzer \
    runlength_fuzzer \
    tiffpredictor_fuzzer

DEFAULT_FUZZ_RUNNER := standalone_fuzz_target_runner
OBJ_DEFAULT_FUZZ := fuzz/$(OUTPUT_DIR)/$(DEFAULT_FUZZ_RUNNER).$(OBJ)

BINS_fuzz = $(foreach B,$(FUZZERS),fuzz/$(OUTPUT_DIR)/$(call binname,$(B)))
TARGETS_fuzz = $(OBJ_DEFAULT_FUZZ) $(BINS_fuzz) fuzz_corpus

# Fuzzers test private classes too, so we need libqpdf in the include path
INCLUDES_fuzz = include libqpdf

# LIB_FUZZING_ENGINE is overridden by oss-fuzz
LIB_FUZZING_ENGINE ?= $(OBJ_DEFAULT_FUZZ)

# Depend on OBJ_DEFAULT_FUZZ to ensure that it is always compiled.
# Don't depend on LIB_FUZZING_ENGINE, which we can't build. When used
# by oss-fuzz, it will be there.
$(BINS_fuzz): $(TARGETS_libqpdf) $(OBJ_DEFAULT_FUZZ)

# Files from the test suite that are good for seeding the fuzzer.
# Update $qpdf_n_test_files in qtest/fuzz.test if you change this list.
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 this directory.
CORPUS_OTHER = $(wildcard fuzz/qpdf_extra/*.fuzz)

# -----

CORPUS_EXTRA := $(foreach F,$(CORPUS_FROM_TEST),qpdf/qtest/qpdf/$F) \
	$(CORPUS_OTHER)
CORPUS_DIR := fuzz/$(OUTPUT_DIR)/qpdf_fuzzer_seed_corpus

.PHONY: fuzz_corpus
fuzz_corpus:: fuzz/$(OUTPUT_DIR)/fuzz_corpus.stamp
$(foreach F,$(CORPUS_EXTRA),$(eval \
  SHA1_$(notdir $(F)) := $(shell perl fuzz/get_sha1 < $F)))
$(foreach F,$(CORPUS_EXTRA),$(eval \
  fuzz_corpus:: $(CORPUS_DIR)/$(SHA1_$(notdir $(F)))))
$(foreach F,$(CORPUS_EXTRA),$(eval \
  $(CORPUS_DIR)/$(SHA1_$(notdir $(F))): $(F) ; \
	mkdir -p $(CORPUS_DIR); \
	cp $(F) $(CORPUS_DIR)/$(SHA1_$(notdir $(F)))))

fuzz/$(OUTPUT_DIR)/fuzz_corpus.stamp: $(CORPUS_EXTRA)
	mkdir -p $(CORPUS_DIR)
	touch $@

$(foreach B,$(FUZZERS),$(eval \
  OBJS_$(B) = $(call src_to_obj,fuzz/$(B).cc)))

ifeq ($(GENDEPS),1)
-include $(foreach B,$(FUZZERS),$(call obj_to_dep,$(OBJS_$(B))))
endif

$(foreach B,$(DEFAULT_FUZZ_RUNNER),$(eval \
  fuzz/$(OUTPUT_DIR)/%.$(OBJ): fuzz/$(B).cc ; \
	$(call compile,fuzz/$(B).cc,$(INCLUDES_fuzz))))

$(foreach B,$(FUZZERS),$(eval \
  $(OBJS_$(B)): fuzz/$(OUTPUT_DIR)/%.$(OBJ): fuzz/$(B).cc ; \
	$(call compile,fuzz/$(B).cc,$(INCLUDES_fuzz))))

ifeq ($(suffix $(LIB_FUZZING_ENGINE)),.$(OBJ))
  FUZZ_as_obj := $(LIB_FUZZING_ENGINE)
  FUZZ_as_lib :=
else
  FUZZ_as_obj :=
  FUZZ_as_lib := $(LIB_FUZZING_ENGINE)
endif

$(foreach B,$(FUZZERS),$(eval \
  fuzz/$(OUTPUT_DIR)/$(call binname,$(B)): $(OBJS_$(B)) ; \
	$(call makebin,$(OBJS_$(B)) $(FUZZ_as_obj),$$@,$(LDFLAGS_libqpdf) $(LDFLAGS),$(FUZZ_as_lib) $(LIBS_libqpdf) $(LIBS))))

ifeq ($(OSS_FUZZ),1)

# Build fuzzers linked with static libraries and installed into a
# location provided by oss-fuzz. This is specifically to support the
# oss-fuzz project. These rules won't on systems that don't allow main
# to be in a library or don't name their libraries libsomething.a.

STATIC_BINS_fuzz := $(foreach B,$(FUZZERS),fuzz/$(OUTPUT_DIR)/static/$(call binname,$(B)))
$(STATIC_BINS_fuzz): $(TARGETS_libqpdf) $(OBJ_DEFAULT_FUZZ)

# OUT is provided in the oss-fuzz environment
OUT ?= $(CURDIR)/fuzz/$(OUTPUT_DIR)/fuzz-install

# These are not fully static, but they statically link with qpdf and
# our external dependencies other than system libraries.
$(foreach B,$(FUZZERS),$(eval \
  fuzz/$(OUTPUT_DIR)/static/$(call binname,$(B)): $(OBJS_$(B)) ; \
	$(call makebin,$(OBJS_$(B)),$$@,$(LDFLAGS_libqpdf) $(LDFLAGS),$(LIB_FUZZING_ENGINE) $(patsubst -l%,-l:lib%.a,$(LIBS_libqpdf) $(LIBS)))))

# The install_fuzz target is used by build.sh in oss-fuzz's qpdf project.
install_fuzz: $(STATIC_BINS_fuzz)
	mkdir -p $(OUT)
	cp fuzz/pdf.dict $(STATIC_BINS_fuzz) $(OUT)/
	for B in $(FUZZERS); do \
	  if test -f fuzz/$${B}.options; then \
	    cp fuzz/$${B}.options $(OUT)/$${B}.options; \
	  fi; \
	  if test -d fuzz/$(OUTPUT_DIR)/$${B}_seed_corpus; then \
	    (cd fuzz/$(OUTPUT_DIR)/$${B}_seed_corpus; zip -q -r $(OUT)/$${B}_seed_corpus.zip .); \
	  elif test -d fuzz/$${B}_seed_corpus; then \
	    (cd fuzz/$${B}_seed_corpus; zip -q -r $(OUT)/$${B}_seed_corpus.zip .); \
	  fi; \
	done

endif # OSS_FUZZ