/src/igraph/fuzzing/write_all_gml.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | IGraph library. |
3 | | Copyright (C) 2024 The igraph development team |
4 | | |
5 | | This program is free software; you can redistribute it and/or modify |
6 | | it under the terms of the GNU General Public License as published by |
7 | | the Free Software Foundation; either version 2 of the License, or |
8 | | (at your option) any later version. |
9 | | |
10 | | This program is distributed in the hope that it will be useful, |
11 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | GNU General Public License for more details. |
14 | | |
15 | | You should have received a copy of the GNU General Public License |
16 | | along with this program; if not, write to the Free Software |
17 | | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
18 | | 02110-1301 USA |
19 | | */ |
20 | | |
21 | | #include <igraph.h> |
22 | | #include <cstdio> |
23 | | |
24 | | // This fuzzer checks two things: |
25 | | // - Test writers for formats that igraph can only write but not read |
26 | | // - Test that files that igraph writes can be read back |
27 | | |
28 | | #define CHECK_ERR(expr) \ |
29 | 53.0k | do { \ |
30 | 53.0k | igraph_error_handler_t *handler = igraph_set_error_handler(igraph_error_handler_abort); \ |
31 | 53.0k | expr; \ |
32 | 53.0k | igraph_set_error_handler(handler); \ |
33 | 53.0k | } while (0) |
34 | | |
35 | | extern "C" |
36 | 26.7k | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
37 | | |
38 | 26.7k | igraph_set_error_handler(igraph_error_handler_ignore); |
39 | 26.7k | igraph_set_warning_handler(igraph_warning_handler_ignore); |
40 | | |
41 | | // Turn on attribute handling |
42 | 26.7k | igraph_set_attribute_table(&igraph_cattribute_table); |
43 | | |
44 | | // Read input file |
45 | 26.7k | FILE *ifile = fmemopen((void*) data, size, "r"); |
46 | 26.7k | if (!ifile) { |
47 | 0 | return 0; |
48 | 0 | } |
49 | | |
50 | | // Do the fuzzing |
51 | 26.7k | igraph_t g; |
52 | 26.7k | if (igraph_read_graph_gml(&g, ifile) == IGRAPH_SUCCESS) { |
53 | 8.93k | FILE *file; |
54 | 8.93k | igraph_t g2; |
55 | | |
56 | 8.93k | file = tmpfile(); |
57 | 8.93k | IGRAPH_ASSERT(file != NULL); |
58 | | // Do not check error because: |
59 | | // "Vertex attribute values cannot contain newline characters." |
60 | 8.93k | igraph_write_graph_leda(&g, file, "label", "weight"); |
61 | 8.93k | fclose(file); |
62 | | |
63 | 8.93k | file = tmpfile(); |
64 | 8.93k | IGRAPH_ASSERT(file != NULL); |
65 | 8.93k | CHECK_ERR(igraph_write_graph_dot(&g, file)); |
66 | 8.93k | fclose(file); |
67 | | |
68 | 8.93k | file = tmpfile(); |
69 | 8.93k | IGRAPH_ASSERT(file != NULL); |
70 | 8.93k | CHECK_ERR(igraph_write_graph_gml(&g, file, IGRAPH_WRITE_GML_DEFAULT_SW, NULL, "no one")); |
71 | 8.93k | rewind(file); |
72 | 8.93k | CHECK_ERR(igraph_read_graph_gml(&g2, file)); |
73 | 8.93k | igraph_destroy(&g2); |
74 | 8.93k | fclose(file); |
75 | | |
76 | | // Reading Pajek files back is disabled because of |
77 | | // https://github.com/igraph/igraph/issues/2560 |
78 | 8.93k | file = tmpfile(); |
79 | 8.93k | IGRAPH_ASSERT(file != NULL); |
80 | 8.93k | CHECK_ERR(igraph_write_graph_pajek(&g, file)); |
81 | | /* |
82 | | rewind(file); |
83 | | CHECK_ERR(igraph_read_graph_pajek(&g2, file)); |
84 | | igraph_destroy(&g2); |
85 | | */ |
86 | 8.93k | fclose(file); |
87 | | |
88 | 8.93k | file = tmpfile(); |
89 | 8.93k | IGRAPH_ASSERT(file != NULL); |
90 | | // Do not check error when writing GraphML because string attributes |
91 | | // may contain forbidden control characters. |
92 | 8.93k | if (igraph_write_graph_graphml(&g, file, false) == IGRAPH_SUCCESS) { |
93 | 8.62k | rewind(file); |
94 | | // Do not check error when reading because strings may not be |
95 | | // in a valid encoding, which confuses libxml2. |
96 | 8.62k | if (igraph_read_graph_graphml(&g2, file, 0) == IGRAPH_SUCCESS) { |
97 | 7.56k | igraph_destroy(&g2); |
98 | 7.56k | } |
99 | 8.62k | } |
100 | 8.93k | fclose(file); |
101 | | |
102 | 8.93k | file = tmpfile(); |
103 | 8.93k | IGRAPH_ASSERT(file != NULL); |
104 | | // Do not check error when writing LGL because not all possible |
105 | | // vertex names are supported by this format. |
106 | 8.93k | if (igraph_write_graph_lgl(&g, file, "label", "weight", false) == IGRAPH_SUCCESS) { |
107 | 8.62k | rewind(file); |
108 | 8.62k | CHECK_ERR(igraph_read_graph_lgl(&g2, file, true, IGRAPH_ADD_WEIGHTS_IF_PRESENT, true)); |
109 | 8.62k | igraph_destroy(&g2); |
110 | 8.62k | } |
111 | 8.93k | fclose(file); |
112 | | |
113 | 8.93k | file = tmpfile(); |
114 | 8.93k | IGRAPH_ASSERT(file != NULL); |
115 | | // Do not check error when writing NCOL because not all possible |
116 | | // vertex names are supported by this format. |
117 | 8.93k | if (igraph_write_graph_ncol(&g, file, "label", "weight") == IGRAPH_SUCCESS) { |
118 | 8.68k | rewind(file); |
119 | 8.68k | CHECK_ERR(igraph_read_graph_ncol(&g2, file, NULL, true, IGRAPH_ADD_WEIGHTS_IF_PRESENT, true)); |
120 | 8.68k | igraph_destroy(&g2); |
121 | 8.68k | } |
122 | 8.93k | fclose(file); |
123 | | |
124 | | // Clean up |
125 | 8.93k | igraph_destroy(&g); |
126 | 8.93k | } |
127 | | |
128 | | // no need to call igraph_destroy() if igraph_read_graph_gml() returns an |
129 | | // error code as we don't have a valid graph object in that case |
130 | | |
131 | 26.7k | fclose(ifile); |
132 | | |
133 | 26.7k | IGRAPH_ASSERT(IGRAPH_FINALLY_STACK_EMPTY); |
134 | | |
135 | 26.7k | return 0; |
136 | 26.7k | } |