/src/htslib/test/fuzz/hts_open_fuzzer.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* test/fuzz/hts_open_fuzzer.c -- Fuzz driver for hts_open. |
2 | | |
3 | | Copyright (C) 2018 Google LLC. |
4 | | Copyright (C) 2019-2020 Genome Research Ltd. |
5 | | |
6 | | Author: Markus Kusano <kusano@google.com> |
7 | | |
8 | | Permission is hereby granted, free of charge, to any person obtaining a copy |
9 | | of this software and associated documentation files (the "Software"), to deal |
10 | | in the Software without restriction, including without limitation the rights |
11 | | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
12 | | copies of the Software, and to permit persons to whom the Software is |
13 | | furnished to do so, subject to the following conditions: |
14 | | |
15 | | The above copyright notice and this permission notice shall be included in |
16 | | all copies or substantial portions of the Software. |
17 | | |
18 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
19 | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
20 | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
21 | | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
22 | | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
23 | | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
24 | | DEALINGS IN THE SOFTWARE. */ |
25 | | |
26 | | #include <config.h> |
27 | | |
28 | | #include <stddef.h> |
29 | | #include <stdint.h> |
30 | | #include <stdio.h> |
31 | | #include <stdlib.h> |
32 | | #include <string.h> |
33 | | #include <unistd.h> |
34 | | |
35 | | #include "../../htslib/hfile.h" |
36 | | #include "../../htslib/hts.h" |
37 | | #include "../../htslib/sam.h" |
38 | | #include "../../htslib/vcf.h" |
39 | | |
40 | 1.76k | static void hts_close_or_abort(htsFile* file) { |
41 | 1.76k | if (hts_close(file) != 0) { |
42 | 0 | abort(); |
43 | 0 | } |
44 | 1.76k | } |
45 | | |
46 | 919 | static void view_sam(htsFile *in) { |
47 | 919 | if (!in) { |
48 | 0 | return; |
49 | 0 | } |
50 | 919 | samFile *out = sam_open("/dev/null", "w"); |
51 | 919 | if (!out) { |
52 | 0 | abort(); |
53 | 0 | } |
54 | 919 | sam_hdr_t *hdr = sam_hdr_read(in); |
55 | 919 | if (hdr == NULL) { |
56 | 34 | hts_close_or_abort(out); |
57 | 34 | return; |
58 | 34 | } |
59 | | |
60 | | // This will force the header to be parsed. |
61 | 885 | (void) sam_hdr_count_lines(hdr, "SQ"); |
62 | | |
63 | 885 | if (sam_hdr_write(out, hdr) != 0) { |
64 | 0 | sam_hdr_destroy(hdr); |
65 | 0 | hts_close_or_abort(out); |
66 | 0 | return; |
67 | 0 | } |
68 | 885 | bam1_t *b = bam_init1(); |
69 | 885 | if (b == NULL) { |
70 | 0 | sam_hdr_destroy(hdr); |
71 | 0 | hts_close_or_abort(out); |
72 | 0 | return; |
73 | 0 | } |
74 | 18.6k | while (sam_read1(in, hdr, b) >= 0) { |
75 | 17.7k | if (sam_write1(out, hdr, b) < 0) { |
76 | 17 | break; |
77 | 17 | } |
78 | 17.7k | } |
79 | 885 | bam_destroy1(b); |
80 | | |
81 | 885 | sam_hdr_destroy(hdr); |
82 | 885 | hts_close_or_abort(out); |
83 | 885 | } |
84 | | |
85 | 847 | static void view_vcf(htsFile *in) { |
86 | 847 | if (!in) { |
87 | 0 | return; |
88 | 0 | } |
89 | 847 | vcfFile *out = vcf_open("/dev/null", "w"); |
90 | 847 | if (!out) { |
91 | 0 | abort(); |
92 | 0 | } |
93 | 847 | bcf_hdr_t *hdr = bcf_hdr_read(in); |
94 | 847 | if (hdr == NULL) { |
95 | 120 | hts_close_or_abort(out); |
96 | 120 | return; |
97 | 120 | } |
98 | | |
99 | 727 | if (bcf_hdr_write(out, hdr) != 0) { |
100 | 0 | bcf_hdr_destroy(hdr); |
101 | 0 | hts_close_or_abort(out); |
102 | 0 | } |
103 | 727 | bcf1_t *rec = bcf_init(); |
104 | 727 | if (rec == NULL) { |
105 | 0 | bcf_hdr_destroy(hdr); |
106 | 0 | hts_close_or_abort(out); |
107 | 0 | } |
108 | 37.9k | while (bcf_read(in, hdr, rec) >= 0) { |
109 | 37.2k | if (bcf_write(out, hdr, rec) < 0) { |
110 | 39 | break; |
111 | 39 | } |
112 | 37.2k | } |
113 | 727 | bcf_destroy(rec); |
114 | | |
115 | 727 | bcf_hdr_destroy(hdr); |
116 | 727 | hts_close_or_abort(out); |
117 | 727 | } |
118 | | |
119 | 1.79k | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
120 | 1.79k | hFILE *memfile; |
121 | 1.79k | uint8_t *copy = malloc(size); |
122 | 1.79k | if (copy == NULL) { |
123 | 0 | abort(); |
124 | 0 | } |
125 | 1.79k | memcpy(copy, data, size); |
126 | | // hopen does not take ownership of `copy`, but hts_hopen does. |
127 | 1.79k | memfile = hopen("mem:", "rb:", copy, size); |
128 | 1.79k | if (memfile == NULL) { |
129 | 0 | free(copy); |
130 | 0 | return 0; |
131 | 0 | } |
132 | | |
133 | 1.79k | htsFile *ht_file = hts_hopen(memfile, "data", "rb"); |
134 | 1.79k | if (ht_file == NULL) { |
135 | 33 | if (hclose(memfile) != 0) { |
136 | 0 | abort(); |
137 | 0 | } |
138 | 33 | return 0; |
139 | 33 | } |
140 | 1.76k | switch (ht_file->format.category) { |
141 | 919 | case sequence_data: |
142 | 919 | view_sam(ht_file); |
143 | 919 | break; |
144 | 847 | case variant_data: |
145 | 847 | view_vcf(ht_file); |
146 | 847 | break; |
147 | 0 | default: |
148 | 0 | break; |
149 | 1.76k | } |
150 | 1.76k | hts_close(ht_file); |
151 | 1.76k | return 0; |
152 | 1.76k | } |