1BSON_VISITOR_T(3) libbson BSON_VISITOR_T(3)
2
3
4
6 bson_visitor_t - bson_visitor_t
7
9 #include <bson/bson.h>
10
11 typedef struct {
12 /* run before / after descending into a document */
13 bool (*visit_before) (const bson_iter_t *iter, const char *key, void *data);
14 bool (*visit_after) (const bson_iter_t *iter, const char *key, void *data);
15 /* corrupt BSON, or unsupported type and visit_unsupported_type not set */
16 void (*visit_corrupt) (const bson_iter_t *iter, void *data);
17 /* normal bson field callbacks */
18 bool (*visit_double) (const bson_iter_t *iter,
19 const char *key,
20 double v_double,
21 void *data);
22 bool (*visit_utf8) (const bson_iter_t *iter,
23 const char *key,
24 size_t v_utf8_len,
25 const char *v_utf8,
26 void *data);
27 bool (*visit_document) (const bson_iter_t *iter,
28 const char *key,
29 const bson_t *v_document,
30 void *data);
31 bool (*visit_array) (const bson_iter_t *iter,
32 const char *key,
33 const bson_t *v_array,
34 void *data);
35 bool (*visit_binary) (const bson_iter_t *iter,
36 const char *key,
37 bson_subtype_t v_subtype,
38 size_t v_binary_len,
39 const uint8_t *v_binary,
40 void *data);
41 /* normal field with deprecated "Undefined" BSON type */
42 bool (*visit_undefined) (const bson_iter_t *iter,
43 const char *key,
44 void *data);
45 bool (*visit_oid) (const bson_iter_t *iter,
46 const char *key,
47 const bson_oid_t *v_oid,
48 void *data);
49 bool (*visit_bool) (const bson_iter_t *iter,
50 const char *key,
51 bool v_bool,
52 void *data);
53 bool (*visit_date_time) (const bson_iter_t *iter,
54 const char *key,
55 int64_t msec_since_epoch,
56 void *data);
57 bool (*visit_null) (const bson_iter_t *iter, const char *key, void *data);
58 bool (*visit_regex) (const bson_iter_t *iter,
59 const char *key,
60 const char *v_regex,
61 const char *v_options,
62 void *data);
63 bool (*visit_dbpointer) (const bson_iter_t *iter,
64 const char *key,
65 size_t v_collection_len,
66 const char *v_collection,
67 const bson_oid_t *v_oid,
68 void *data);
69 bool (*visit_code) (const bson_iter_t *iter,
70 const char *key,
71 size_t v_code_len,
72 const char *v_code,
73 void *data);
74 bool (*visit_symbol) (const bson_iter_t *iter,
75 const char *key,
76 size_t v_symbol_len,
77 const char *v_symbol,
78 void *data);
79 bool (*visit_codewscope) (const bson_iter_t *iter,
80 const char *key,
81 size_t v_code_len,
82 const char *v_code,
83 const bson_t *v_scope,
84 void *data);
85 bool (*visit_int32) (const bson_iter_t *iter,
86 const char *key,
87 int32_t v_int32,
88 void *data);
89 bool (*visit_timestamp) (const bson_iter_t *iter,
90 const char *key,
91 uint32_t v_timestamp,
92 uint32_t v_increment,
93 void *data);
94 bool (*visit_int64) (const bson_iter_t *iter,
95 const char *key,
96 int64_t v_int64,
97 void *data);
98 bool (*visit_maxkey) (const bson_iter_t *iter, const char *key, void *data);
99 bool (*visit_minkey) (const bson_iter_t *iter, const char *key, void *data);
100 /* if set, called instead of visit_corrupt when an apparently valid BSON
101 * includes an unrecognized field type (reading future version of BSON) */
102 void (*visit_unsupported_type) (const bson_iter_t *iter,
103 const char *key,
104 uint32_t type_code,
105 void *data);
106 bool (*visit_decimal128) (const bson_iter_t *iter,
107 const char *key,
108 const bson_decimal128_t *v_decimal128,
109 void *data);
110
111 void *padding[7];
112 } bson_visitor_t bson_visitor_t;
113
115 The bson_visitor_t structure provides a series of callbacks that can be
116 called while iterating a BSON document. This may simplify the converā
117 sion of a bson_t to a higher level language structure.
118
119 If the optional callback visit_unsupported_type is set, it is called
120 instead of visit_corrupt in the specific case of an unrecognized field
121 type. (Parsing is aborted in either case.) Use this callback to report
122 an error like "unrecognized type" instead of simply "corrupt BSON".
123 This future-proofs code that may use an older version of libbson to
124 parse future BSON formats.
125
127 #include <bson/bson.h>
128 #include <stdio.h>
129
130 static bool
131 my_visit_before (const bson_iter_t *iter, const char *key, void *data)
132 {
133 int *count = (int *) data;
134
135 (*count)++;
136
137 /* returning true stops further iteration of the document */
138
139 return false;
140 }
141
142 static void
143 count_fields (bson_t *doc)
144 {
145 bson_visitor_t visitor = {0};
146 bson_iter_t iter;
147 int count = 0;
148
149 visitor.visit_before = my_visit_before;
150
151 if (bson_iter_init (&iter, doc)) {
152 bson_iter_visit_all (&iter, &visitor, &count);
153 }
154
155 printf ("Found %d fields.\n", count);
156 }
157
158 The example below demonstrates how to set your own callbacks to provide
159 information about the location of corrupt or unsupported BSON document
160 entries.
161
163 #include <bson/bson.h>
164 #include <stdio.h>
165
166 typedef struct {
167 ssize_t *err_offset;
168 } my_state_t;
169
170 static void
171 my_visit_corrupt (const bson_iter_t *iter, void *data)
172 {
173 *(((my_state_t *) data)->err_offset) = iter->off;
174 }
175
176 static void
177 my_visit_unsupported_type (const bson_iter_t *iter,
178 const char *key,
179 uint32_t type_code,
180 void *data)
181 {
182 *(((my_state_t *) data)->err_offset) = iter->off;
183 }
184
185 static void
186 find_error_location (bson_t *doc)
187 {
188 bson_visitor_t visitors = {0};
189 bson_iter_t iter;
190 my_state_t state;
191 ssize_t err_offset = -1;
192
193 visitors.visit_corrupt = my_visit_corrupt;
194 visitors.visit_unsupported_type = my_visit_unsupported_type;
195 /* provide additional visitors as needed based on your requirements */
196 state.err_offset = &err_offset;
197
198 if (!bson_iter_init (&iter, doc)) {
199 printf ("Could not initialize iterator!");
200 exit (1);
201 }
202
203 if (bson_iter_visit_all (&iter, &visitors, &state) ||
204 err_offset != -1) {
205 printf ("Found error at offset %d.\n", err_offset);
206 } else {
207 printf ("BSON document had no errors.\n");
208 }
209 }
210
211 The example below demonstrates how to use a visitor to validate a BSON
212 document's maximum depth.
213
215 bson-check-depth.c
216
217 /* Reports the maximum nested depth of a BSON document. */
218 #include <bson/bson.h>
219
220 #include <assert.h>
221 #include <stdio.h>
222 #include <stdlib.h>
223
224 typedef struct {
225 uint32_t depth;
226 int max_depth;
227 bool valid;
228 } check_depth_t;
229
230 bool
231 _check_depth_document (const bson_iter_t *iter,
232 const char *key,
233 const bson_t *v_document,
234 void *data);
235
236 static const bson_visitor_t check_depth_funcs = {
237 NULL,
238 NULL,
239 NULL,
240 NULL,
241 NULL,
242 _check_depth_document,
243 _check_depth_document,
244 NULL,
245 };
246
247 bool
248 _check_depth_document (const bson_iter_t *iter,
249 const char *key,
250 const bson_t *v_document,
251 void *data)
252 {
253 check_depth_t *state = (check_depth_t *) data;
254 bson_iter_t child;
255
256 BSON_UNUSED (iter);
257 BSON_UNUSED (key);
258
259 if (!bson_iter_init (&child, v_document)) {
260 fprintf (stderr, "corrupt\n");
261 return true; /* cancel */
262 }
263
264 state->depth++;
265 if (state->depth > state->max_depth) {
266 state->valid = false;
267 return true; /* cancel */
268 }
269
270 bson_iter_visit_all (&child, &check_depth_funcs, state);
271 state->depth--;
272 return false; /* continue */
273 }
274
275 void
276 check_depth (const bson_t *bson, int max_depth)
277 {
278 bson_iter_t iter;
279 check_depth_t state = {0};
280
281 if (!bson_iter_init (&iter, bson)) {
282 fprintf (stderr, "corrupt\n");
283 }
284
285 state.valid = true;
286 state.max_depth = max_depth;
287 _check_depth_document (&iter, NULL, bson, &state);
288 if (!state.valid) {
289 printf ("document exceeds maximum depth of %d\n", state.max_depth);
290 } else {
291 char *as_json = bson_as_canonical_extended_json (bson, NULL);
292 printf ("document %s ", as_json);
293 printf ("is valid\n");
294 bson_free (as_json);
295 }
296 }
297
298 int
299 main (int argc, char **argv)
300 {
301 bson_reader_t *bson_reader;
302 const bson_t *bson;
303 bool reached_eof;
304 char *filename;
305 bson_error_t error;
306 int max_depth;
307
308 if (argc != 3) {
309 fprintf (stderr, "usage: %s FILE MAX_DEPTH\n", argv[0]);
310 fprintf (stderr, "Checks that the depth of the BSON contained in FILE\n");
311 fprintf (stderr, "does not exceed MAX_DEPTH\n");
312 }
313
314 filename = argv[1];
315 max_depth = atoi (argv[2]);
316 bson_reader = bson_reader_new_from_file (filename, &error);
317 if (!bson_reader) {
318 printf ("could not read %s: %s\n", filename, error.message);
319 return 1;
320 }
321
322 while ((bson = bson_reader_read (bson_reader, &reached_eof))) {
323 check_depth (bson, max_depth);
324 }
325
326 if (!reached_eof) {
327 printf ("error reading BSON\n");
328 }
329
330 bson_reader_destroy (bson_reader);
331 return 0;
332 }
333
334
336 MongoDB, Inc
337
339 2017-present, MongoDB, Inc
340
341
342
343
3441.23.1 Oct 20, 2022 BSON_VISITOR_T(3)