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 <inttypes.h>
222 #include <stdio.h>
223 #include <stdlib.h>
224
225 typedef struct {
226 uint32_t depth;
227 uint32_t max_depth;
228 bool valid;
229 } check_depth_t;
230
231 bool
232 _check_depth_document (const bson_iter_t *iter,
233 const char *key,
234 const bson_t *v_document,
235 void *data);
236
237 static const bson_visitor_t check_depth_funcs = {
238 NULL,
239 NULL,
240 NULL,
241 NULL,
242 NULL,
243 _check_depth_document,
244 _check_depth_document,
245 NULL,
246 };
247
248 bool
249 _check_depth_document (const bson_iter_t *iter,
250 const char *key,
251 const bson_t *v_document,
252 void *data)
253 {
254 check_depth_t *state = (check_depth_t *) data;
255 bson_iter_t child;
256
257 BSON_UNUSED (iter);
258 BSON_UNUSED (key);
259
260 if (!bson_iter_init (&child, v_document)) {
261 fprintf (stderr, "corrupt\n");
262 return true; /* cancel */
263 }
264
265 state->depth++;
266 if (state->depth > state->max_depth) {
267 state->valid = false;
268 return true; /* cancel */
269 }
270
271 bson_iter_visit_all (&child, &check_depth_funcs, state);
272 state->depth--;
273 return false; /* continue */
274 }
275
276 void
277 check_depth (const bson_t *bson, uint32_t max_depth)
278 {
279 bson_iter_t iter;
280 check_depth_t state = {0};
281
282 if (!bson_iter_init (&iter, bson)) {
283 fprintf (stderr, "corrupt\n");
284 }
285
286 state.valid = true;
287 state.max_depth = max_depth;
288 _check_depth_document (&iter, NULL, bson, &state);
289 if (!state.valid) {
290 printf ("document exceeds maximum depth of %" PRIu32 "\n",
291 state.max_depth);
292 } else {
293 char *as_json = bson_as_canonical_extended_json (bson, NULL);
294 printf ("document %s ", as_json);
295 printf ("is valid\n");
296 bson_free (as_json);
297 }
298 }
299
300 int
301 main (int argc, char **argv)
302 {
303 bson_reader_t *bson_reader;
304 const bson_t *bson;
305 bool reached_eof;
306 bson_error_t error;
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 const char *const filename = argv[1];
315 const int max_depth = atoi (argv[2]);
316
317 bson_reader = bson_reader_new_from_file (filename, &error);
318 if (!bson_reader) {
319 printf ("could not read %s: %s\n", filename, error.message);
320 return 1;
321 }
322
323 BSON_ASSERT (bson_in_range_signed (uint32_t, max_depth));
324
325 while ((bson = bson_reader_read (bson_reader, &reached_eof))) {
326 check_depth (bson, (uint32_t) max_depth);
327 }
328
329 if (!reached_eof) {
330 printf ("error reading BSON\n");
331 }
332
333 bson_reader_destroy (bson_reader);
334 return 0;
335 }
336
337
339 MongoDB, Inc
340
342 2017-present, MongoDB, Inc
343
344
345
346
3471.24.3 Aug 17, 2023 BSON_VISITOR_T(3)