1 /*
2  * Copyright 2013 MongoDB, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 #include "bson.h"
19 #include "bson-config.h"
20 #include "b64_ntop.h"
21 #include "bson-private.h"
22 #include "bson-string.h"
23 #include "bson-iso8601-private.h"
24 
25 #include <string.h>
26 #include <math.h>
27 
28 
29 #ifndef BSON_MAX_RECURSION
30 #define BSON_MAX_RECURSION 200
31 #endif
32 
33 
34 typedef enum {
35    BSON_VALIDATE_PHASE_START,
36    BSON_VALIDATE_PHASE_TOP,
37    BSON_VALIDATE_PHASE_LF_REF_KEY,
38    BSON_VALIDATE_PHASE_LF_REF_UTF8,
39    BSON_VALIDATE_PHASE_LF_ID_KEY,
40    BSON_VALIDATE_PHASE_LF_DB_KEY,
41    BSON_VALIDATE_PHASE_LF_DB_UTF8,
42    BSON_VALIDATE_PHASE_NOT_DBREF,
43 } bson_validate_phase_t;
44 
45 
46 typedef enum {
47    BSON_JSON_MODE_LEGACY,
48    BSON_JSON_MODE_CANONICAL,
49    BSON_JSON_MODE_RELAXED,
50 } bson_json_mode_t;
51 
52 
53 /*
54  * Structures.
55  */
56 typedef struct {
57    bson_validate_flags_t flags;
58    ssize_t err_offset;
59    bson_validate_phase_t phase;
60    bson_error_t error;
61 } bson_validate_state_t;
62 
63 
64 typedef struct {
65    uint32_t count;
66    bool keys;
67    ssize_t *err_offset;
68    uint32_t depth;
69    bson_string_t *str;
70    bson_json_mode_t mode;
71 } bson_json_state_t;
72 
73 
74 /*
75  * Forward declarations.
76  */
77 static bool
78 _bson_as_json_visit_array (const bson_iter_t *iter,
79                            const char *key,
80                            const bson_t *v_array,
81                            void *data);
82 static bool
83 _bson_as_json_visit_document (const bson_iter_t *iter,
84                               const char *key,
85                               const bson_t *v_document,
86                               void *data);
87 static char *
88 _bson_as_json_visit_all (const bson_t *bson,
89                          size_t *length,
90                          bson_json_mode_t mode);
91 
92 /*
93  * Globals.
94  */
95 static const uint8_t gZero;
96 
97 /*
98  *--------------------------------------------------------------------------
99  *
100  * _bson_impl_inline_grow --
101  *
102  *       Document growth implementation for documents that currently
103  *       contain stack based buffers. The document may be switched to
104  *       a malloc based buffer.
105  *
106  * Returns:
107  *       true if successful; otherwise false indicating INT_MAX overflow.
108  *
109  * Side effects:
110  *       None.
111  *
112  *--------------------------------------------------------------------------
113  */
114 
115 static bool
_bson_impl_inline_grow(bson_impl_inline_t * impl,size_t size)116 _bson_impl_inline_grow (bson_impl_inline_t *impl, /* IN */
117                         size_t size)              /* IN */
118 {
119    bson_impl_alloc_t *alloc = (bson_impl_alloc_t *) impl;
120    uint8_t *data;
121    size_t req;
122 
123    if (((size_t) impl->len + size) <= sizeof impl->data) {
124       return true;
125    }
126 
127    req = bson_next_power_of_two (impl->len + size);
128 
129    if (req <= INT32_MAX) {
130       data = bson_malloc (req);
131 
132       memcpy (data, impl->data, impl->len);
133       alloc->flags &= ~BSON_FLAG_INLINE;
134       alloc->parent = NULL;
135       alloc->depth = 0;
136       alloc->buf = &alloc->alloc;
137       alloc->buflen = &alloc->alloclen;
138       alloc->offset = 0;
139       alloc->alloc = data;
140       alloc->alloclen = req;
141       alloc->realloc = bson_realloc_ctx;
142       alloc->realloc_func_ctx = NULL;
143 
144       return true;
145    }
146 
147    return false;
148 }
149 
150 
151 /*
152  *--------------------------------------------------------------------------
153  *
154  * _bson_impl_alloc_grow --
155  *
156  *       Document growth implementation for documents containing malloc
157  *       based buffers.
158  *
159  * Returns:
160  *       true if successful; otherwise false indicating INT_MAX overflow.
161  *
162  * Side effects:
163  *       None.
164  *
165  *--------------------------------------------------------------------------
166  */
167 
168 static bool
_bson_impl_alloc_grow(bson_impl_alloc_t * impl,size_t size)169 _bson_impl_alloc_grow (bson_impl_alloc_t *impl, /* IN */
170                        size_t size)             /* IN */
171 {
172    size_t req;
173 
174    /*
175     * Determine how many bytes we need for this document in the buffer
176     * including necessary trailing bytes for parent documents.
177     */
178    req = (impl->offset + impl->len + size + impl->depth);
179 
180    if (req <= *impl->buflen) {
181       return true;
182    }
183 
184    req = bson_next_power_of_two (req);
185 
186    if ((req <= INT32_MAX) && impl->realloc) {
187       *impl->buf = impl->realloc (*impl->buf, req, impl->realloc_func_ctx);
188       *impl->buflen = req;
189       return true;
190    }
191 
192    return false;
193 }
194 
195 
196 /*
197  *--------------------------------------------------------------------------
198  *
199  * _bson_grow --
200  *
201  *       Grows the bson_t structure to be large enough to contain @size
202  *       bytes.
203  *
204  * Returns:
205  *       true if successful, false if the size would overflow.
206  *
207  * Side effects:
208  *       None.
209  *
210  *--------------------------------------------------------------------------
211  */
212 
213 static bool
_bson_grow(bson_t * bson,uint32_t size)214 _bson_grow (bson_t *bson,  /* IN */
215             uint32_t size) /* IN */
216 {
217    if ((bson->flags & BSON_FLAG_INLINE)) {
218       return _bson_impl_inline_grow ((bson_impl_inline_t *) bson, size);
219    }
220 
221    return _bson_impl_alloc_grow ((bson_impl_alloc_t *) bson, size);
222 }
223 
224 
225 /*
226  *--------------------------------------------------------------------------
227  *
228  * _bson_data --
229  *
230  *       A helper function to return the contents of the bson document
231  *       taking into account the polymorphic nature of bson_t.
232  *
233  * Returns:
234  *       A buffer which should not be modified or freed.
235  *
236  * Side effects:
237  *       None.
238  *
239  *--------------------------------------------------------------------------
240  */
241 
242 static BSON_INLINE uint8_t *
_bson_data(const bson_t * bson)243 _bson_data (const bson_t *bson) /* IN */
244 {
245    if ((bson->flags & BSON_FLAG_INLINE)) {
246       return ((bson_impl_inline_t *) bson)->data;
247    } else {
248       bson_impl_alloc_t *impl = (bson_impl_alloc_t *) bson;
249       return (*impl->buf) + impl->offset;
250    }
251 }
252 
253 
254 /*
255  *--------------------------------------------------------------------------
256  *
257  * _bson_encode_length --
258  *
259  *       Helper to encode the length of the bson_t in the first 4 bytes
260  *       of the bson document. Little endian format is used as specified
261  *       by bsonspec.
262  *
263  * Returns:
264  *       None.
265  *
266  * Side effects:
267  *       None.
268  *
269  *--------------------------------------------------------------------------
270  */
271 
272 static BSON_INLINE void
_bson_encode_length(bson_t * bson)273 _bson_encode_length (bson_t *bson) /* IN */
274 {
275 #if BSON_BYTE_ORDER == BSON_LITTLE_ENDIAN
276    memcpy (_bson_data (bson), &bson->len, sizeof (bson->len));
277 #else
278    uint32_t length_le = BSON_UINT32_TO_LE (bson->len);
279    memcpy (_bson_data (bson), &length_le, sizeof (length_le));
280 #endif
281 }
282 
283 
284 /*
285  *--------------------------------------------------------------------------
286  *
287  * _bson_append_va --
288  *
289  *       Appends the length,buffer pairs to the bson_t. @n_bytes is an
290  *       optimization to perform one array growth rather than many small
291  *       growths.
292  *
293  *       @bson: A bson_t
294  *       @n_bytes: The number of bytes to append to the document.
295  *       @n_pairs: The number of length,buffer pairs.
296  *       @first_len: Length of first buffer.
297  *       @first_data: First buffer.
298  *       @args: va_list of additional tuples.
299  *
300  * Returns:
301  *       true if the bytes were appended successfully.
302  *       false if it bson would overflow INT_MAX.
303  *
304  * Side effects:
305  *       None.
306  *
307  *--------------------------------------------------------------------------
308  */
309 
310 static BSON_INLINE bool
_bson_append_va(bson_t * bson,uint32_t n_bytes,uint32_t n_pairs,uint32_t first_len,const uint8_t * first_data,va_list args)311 _bson_append_va (bson_t *bson,              /* IN */
312                  uint32_t n_bytes,          /* IN */
313                  uint32_t n_pairs,          /* IN */
314                  uint32_t first_len,        /* IN */
315                  const uint8_t *first_data, /* IN */
316                  va_list args)              /* IN */
317 {
318    const uint8_t *data;
319    uint32_t data_len;
320    uint8_t *buf;
321 
322    BSON_ASSERT (!(bson->flags & BSON_FLAG_IN_CHILD));
323    BSON_ASSERT (!(bson->flags & BSON_FLAG_RDONLY));
324 
325    if (BSON_UNLIKELY (!_bson_grow (bson, n_bytes))) {
326       return false;
327    }
328 
329    data = first_data;
330    data_len = first_len;
331 
332    buf = _bson_data (bson) + bson->len - 1;
333 
334    do {
335       n_pairs--;
336       memcpy (buf, data, data_len);
337       bson->len += data_len;
338       buf += data_len;
339 
340       if (n_pairs) {
341          data_len = va_arg (args, uint32_t);
342          data = va_arg (args, const uint8_t *);
343       }
344    } while (n_pairs);
345 
346    _bson_encode_length (bson);
347 
348    *buf = '\0';
349 
350    return true;
351 }
352 
353 
354 /*
355  *--------------------------------------------------------------------------
356  *
357  * _bson_append --
358  *
359  *       Variadic function to append length,buffer pairs to a bson_t. If the
360  *       append would cause the bson_t to overflow a 32-bit length, it will
361  *       return false and no append will have occurred.
362  *
363  * Parameters:
364  *       @bson: A bson_t.
365  *       @n_pairs: Number of length,buffer pairs.
366  *       @n_bytes: the total number of bytes being appended.
367  *       @first_len: Length of first buffer.
368  *       @first_data: First buffer.
369  *
370  * Returns:
371  *       true if successful; otherwise false indicating INT_MAX overflow.
372  *
373  * Side effects:
374  *       None.
375  *
376  *--------------------------------------------------------------------------
377  */
378 
379 static bool
_bson_append(bson_t * bson,uint32_t n_pairs,uint32_t n_bytes,uint32_t first_len,const uint8_t * first_data,...)380 _bson_append (bson_t *bson,              /* IN */
381               uint32_t n_pairs,          /* IN */
382               uint32_t n_bytes,          /* IN */
383               uint32_t first_len,        /* IN */
384               const uint8_t *first_data, /* IN */
385               ...)
386 {
387    va_list args;
388    bool ok;
389 
390    BSON_ASSERT (n_pairs);
391    BSON_ASSERT (first_len);
392    BSON_ASSERT (first_data);
393 
394    /*
395     * Check to see if this append would overflow 32-bit signed integer. I know
396     * what you're thinking. BSON uses a signed 32-bit length field? Yeah. It
397     * does.
398     */
399    if (BSON_UNLIKELY (n_bytes > (BSON_MAX_SIZE - bson->len))) {
400       return false;
401    }
402 
403    va_start (args, first_data);
404    ok = _bson_append_va (bson, n_bytes, n_pairs, first_len, first_data, args);
405    va_end (args);
406 
407    return ok;
408 }
409 
410 
411 /*
412  *--------------------------------------------------------------------------
413  *
414  * _bson_append_bson_begin --
415  *
416  *       Begin appending a subdocument or subarray to the document using
417  *       the key provided by @key.
418  *
419  *       If @key_length is < 0, then strlen() will be called on @key
420  *       to determine the length.
421  *
422  *       @key_type MUST be either BSON_TYPE_DOCUMENT or BSON_TYPE_ARRAY.
423  *
424  * Returns:
425  *       true if successful; otherwise false indicating INT_MAX overflow.
426  *
427  * Side effects:
428  *       @child is initialized if true is returned.
429  *
430  *--------------------------------------------------------------------------
431  */
432 
433 static bool
_bson_append_bson_begin(bson_t * bson,const char * key,int key_length,bson_type_t child_type,bson_t * child)434 _bson_append_bson_begin (bson_t *bson,           /* IN */
435                          const char *key,        /* IN */
436                          int key_length,         /* IN */
437                          bson_type_t child_type, /* IN */
438                          bson_t *child)          /* OUT */
439 {
440    const uint8_t type = child_type;
441    const uint8_t empty[5] = {5};
442    bson_impl_alloc_t *aparent = (bson_impl_alloc_t *) bson;
443    bson_impl_alloc_t *achild = (bson_impl_alloc_t *) child;
444 
445    BSON_ASSERT (!(bson->flags & BSON_FLAG_RDONLY));
446    BSON_ASSERT (!(bson->flags & BSON_FLAG_IN_CHILD));
447    BSON_ASSERT (key);
448    BSON_ASSERT ((child_type == BSON_TYPE_DOCUMENT) ||
449                 (child_type == BSON_TYPE_ARRAY));
450    BSON_ASSERT (child);
451 
452    if (key_length < 0) {
453       key_length = (int) strlen (key);
454    }
455 
456    /*
457     * If the parent is an inline bson_t, then we need to convert
458     * it to a heap allocated buffer. This makes extending buffers
459     * of child bson documents much simpler logic, as they can just
460     * realloc the *buf pointer.
461     */
462    if ((bson->flags & BSON_FLAG_INLINE)) {
463       BSON_ASSERT (bson->len <= 120);
464       if (!_bson_grow (bson, 128 - bson->len)) {
465          return false;
466       }
467       BSON_ASSERT (!(bson->flags & BSON_FLAG_INLINE));
468    }
469 
470    /*
471     * Append the type and key for the field.
472     */
473    if (!_bson_append (bson,
474                       4,
475                       (1 + key_length + 1 + 5),
476                       1,
477                       &type,
478                       key_length,
479                       key,
480                       1,
481                       &gZero,
482                       5,
483                       empty)) {
484       return false;
485    }
486 
487    /*
488     * Mark the document as working on a child document so that no
489     * further modifications can happen until the caller has called
490     * bson_append_{document,array}_end().
491     */
492    bson->flags |= BSON_FLAG_IN_CHILD;
493 
494    /*
495     * Initialize the child bson_t structure and point it at the parents
496     * buffers. This allows us to realloc directly from the child without
497     * walking up to the parent bson_t.
498     */
499    achild->flags = (BSON_FLAG_CHILD | BSON_FLAG_NO_FREE | BSON_FLAG_STATIC);
500 
501    if ((bson->flags & BSON_FLAG_CHILD)) {
502       achild->depth = ((bson_impl_alloc_t *) bson)->depth + 1;
503    } else {
504       achild->depth = 1;
505    }
506 
507    achild->parent = bson;
508    achild->buf = aparent->buf;
509    achild->buflen = aparent->buflen;
510    achild->offset = aparent->offset + aparent->len - 1 - 5;
511    achild->len = 5;
512    achild->alloc = NULL;
513    achild->alloclen = 0;
514    achild->realloc = aparent->realloc;
515    achild->realloc_func_ctx = aparent->realloc_func_ctx;
516 
517    return true;
518 }
519 
520 
521 /*
522  *--------------------------------------------------------------------------
523  *
524  * _bson_append_bson_end --
525  *
526  *       Complete a call to _bson_append_bson_begin.
527  *
528  * Returns:
529  *       true if successful.
530  *
531  * Side effects:
532  *       @child is destroyed and no longer valid after calling this
533  *       function.
534  *
535  *--------------------------------------------------------------------------
536  */
537 
538 static bool
_bson_append_bson_end(bson_t * bson,bson_t * child)539 _bson_append_bson_end (bson_t *bson,  /* IN */
540                        bson_t *child) /* IN */
541 {
542    BSON_ASSERT (bson);
543    BSON_ASSERT ((bson->flags & BSON_FLAG_IN_CHILD));
544    BSON_ASSERT (!(child->flags & BSON_FLAG_IN_CHILD));
545 
546    /*
547     * Unmark the IN_CHILD flag.
548     */
549    bson->flags &= ~BSON_FLAG_IN_CHILD;
550 
551    /*
552     * Now that we are done building the sub-document, add the size to the
553     * parent, not including the default 5 byte empty document already added.
554     */
555    bson->len = (bson->len + child->len - 5);
556 
557    /*
558     * Ensure we have a \0 byte at the end and proper length encoded at
559     * the beginning of the document.
560     */
561    _bson_data (bson)[bson->len - 1] = '\0';
562    _bson_encode_length (bson);
563 
564    return true;
565 }
566 
567 
568 /*
569  *--------------------------------------------------------------------------
570  *
571  * bson_append_array_begin --
572  *
573  *       Start appending a new array.
574  *
575  *       Use @child to append to the data area for the given field.
576  *
577  *       It is a programming error to call any other bson function on
578  *       @bson until bson_append_array_end() has been called. It is
579  *       valid to call bson_append*() functions on @child.
580  *
581  *       This function is useful to allow building nested documents using
582  *       a single buffer owned by the top-level bson document.
583  *
584  * Returns:
585  *       true if successful; otherwise false and @child is invalid.
586  *
587  * Side effects:
588  *       @child is initialized if true is returned.
589  *
590  *--------------------------------------------------------------------------
591  */
592 
593 bool
bson_append_array_begin(bson_t * bson,const char * key,int key_length,bson_t * child)594 bson_append_array_begin (bson_t *bson,    /* IN */
595                          const char *key, /* IN */
596                          int key_length,  /* IN */
597                          bson_t *child)   /* IN */
598 {
599    BSON_ASSERT (bson);
600    BSON_ASSERT (key);
601    BSON_ASSERT (child);
602 
603    return _bson_append_bson_begin (
604       bson, key, key_length, BSON_TYPE_ARRAY, child);
605 }
606 
607 
608 /*
609  *--------------------------------------------------------------------------
610  *
611  * bson_append_array_end --
612  *
613  *       Complete a call to bson_append_array_begin().
614  *
615  *       It is safe to append other fields to @bson after calling this
616  *       function.
617  *
618  * Returns:
619  *       true if successful.
620  *
621  * Side effects:
622  *       @child is invalid after calling this function.
623  *
624  *--------------------------------------------------------------------------
625  */
626 
627 bool
bson_append_array_end(bson_t * bson,bson_t * child)628 bson_append_array_end (bson_t *bson,  /* IN */
629                        bson_t *child) /* IN */
630 {
631    BSON_ASSERT (bson);
632    BSON_ASSERT (child);
633 
634    return _bson_append_bson_end (bson, child);
635 }
636 
637 
638 /*
639  *--------------------------------------------------------------------------
640  *
641  * bson_append_document_begin --
642  *
643  *       Start appending a new document.
644  *
645  *       Use @child to append to the data area for the given field.
646  *
647  *       It is a programming error to call any other bson function on
648  *       @bson until bson_append_document_end() has been called. It is
649  *       valid to call bson_append*() functions on @child.
650  *
651  *       This function is useful to allow building nested documents using
652  *       a single buffer owned by the top-level bson document.
653  *
654  * Returns:
655  *       true if successful; otherwise false and @child is invalid.
656  *
657  * Side effects:
658  *       @child is initialized if true is returned.
659  *
660  *--------------------------------------------------------------------------
661  */
662 bool
bson_append_document_begin(bson_t * bson,const char * key,int key_length,bson_t * child)663 bson_append_document_begin (bson_t *bson,    /* IN */
664                             const char *key, /* IN */
665                             int key_length,  /* IN */
666                             bson_t *child)   /* IN */
667 {
668    BSON_ASSERT (bson);
669    BSON_ASSERT (key);
670    BSON_ASSERT (child);
671 
672    return _bson_append_bson_begin (
673       bson, key, key_length, BSON_TYPE_DOCUMENT, child);
674 }
675 
676 
677 /*
678  *--------------------------------------------------------------------------
679  *
680  * bson_append_document_end --
681  *
682  *       Complete a call to bson_append_document_begin().
683  *
684  *       It is safe to append new fields to @bson after calling this
685  *       function, if true is returned.
686  *
687  * Returns:
688  *       true if successful; otherwise false indicating INT_MAX overflow.
689  *
690  * Side effects:
691  *       @child is destroyed and invalid after calling this function.
692  *
693  *--------------------------------------------------------------------------
694  */
695 
696 bool
bson_append_document_end(bson_t * bson,bson_t * child)697 bson_append_document_end (bson_t *bson,  /* IN */
698                           bson_t *child) /* IN */
699 {
700    BSON_ASSERT (bson);
701    BSON_ASSERT (child);
702 
703    return _bson_append_bson_end (bson, child);
704 }
705 
706 
707 /*
708  *--------------------------------------------------------------------------
709  *
710  * bson_append_array --
711  *
712  *       Append an array to @bson.
713  *
714  *       Generally, bson_append_array_begin() will result in faster code
715  *       since few buffers need to be malloced.
716  *
717  * Returns:
718  *       true if successful; otherwise false indicating INT_MAX overflow.
719  *
720  * Side effects:
721  *       None.
722  *
723  *--------------------------------------------------------------------------
724  */
725 
726 bool
bson_append_array(bson_t * bson,const char * key,int key_length,const bson_t * array)727 bson_append_array (bson_t *bson,        /* IN */
728                    const char *key,     /* IN */
729                    int key_length,      /* IN */
730                    const bson_t *array) /* IN */
731 {
732    static const uint8_t type = BSON_TYPE_ARRAY;
733 
734    BSON_ASSERT (bson);
735    BSON_ASSERT (key);
736    BSON_ASSERT (array);
737 
738    if (key_length < 0) {
739       key_length = (int) strlen (key);
740    }
741 
742    /*
743     * Let's be a bit pedantic and ensure the array has properly formatted key
744     * names.  We will verify this simply by checking the first element for "0"
745     * if the array is non-empty.
746     */
747    if (array && !bson_empty (array)) {
748       bson_iter_t iter;
749 
750       if (bson_iter_init (&iter, array) && bson_iter_next (&iter)) {
751          if (0 != strcmp ("0", bson_iter_key (&iter))) {
752             fprintf (stderr,
753                      "%s(): invalid array detected. first element of array "
754                      "parameter is not \"0\".\n",
755                      BSON_FUNC);
756          }
757       }
758    }
759 
760    return _bson_append (bson,
761                         4,
762                         (1 + key_length + 1 + array->len),
763                         1,
764                         &type,
765                         key_length,
766                         key,
767                         1,
768                         &gZero,
769                         array->len,
770                         _bson_data (array));
771 }
772 
773 
774 /*
775  *--------------------------------------------------------------------------
776  *
777  * bson_append_binary --
778  *
779  *       Append binary data to @bson. The field will have the
780  *       BSON_TYPE_BINARY type.
781  *
782  * Parameters:
783  *       @subtype: the BSON Binary Subtype. See bsonspec.org for more
784  *                 information.
785  *       @binary: a pointer to the raw binary data.
786  *       @length: the size of @binary in bytes.
787  *
788  * Returns:
789  *       true if successful; otherwise false.
790  *
791  * Side effects:
792  *       None.
793  *
794  *--------------------------------------------------------------------------
795  */
796 
797 bool
bson_append_binary(bson_t * bson,const char * key,int key_length,bson_subtype_t subtype,const uint8_t * binary,uint32_t length)798 bson_append_binary (bson_t *bson,           /* IN */
799                     const char *key,        /* IN */
800                     int key_length,         /* IN */
801                     bson_subtype_t subtype, /* IN */
802                     const uint8_t *binary,  /* IN */
803                     uint32_t length)        /* IN */
804 {
805    static const uint8_t type = BSON_TYPE_BINARY;
806    uint32_t length_le;
807    uint32_t deprecated_length_le;
808    uint8_t subtype8 = 0;
809 
810    BSON_ASSERT (bson);
811    BSON_ASSERT (key);
812    BSON_ASSERT (binary);
813 
814    if (key_length < 0) {
815       key_length = (int) strlen (key);
816    }
817 
818    subtype8 = subtype;
819 
820    if (subtype == BSON_SUBTYPE_BINARY_DEPRECATED) {
821       length_le = BSON_UINT32_TO_LE (length + 4);
822       deprecated_length_le = BSON_UINT32_TO_LE (length);
823 
824       return _bson_append (bson,
825                            7,
826                            (1 + key_length + 1 + 4 + 1 + 4 + length),
827                            1,
828                            &type,
829                            key_length,
830                            key,
831                            1,
832                            &gZero,
833                            4,
834                            &length_le,
835                            1,
836                            &subtype8,
837                            4,
838                            &deprecated_length_le,
839                            length,
840                            binary);
841    } else {
842       length_le = BSON_UINT32_TO_LE (length);
843 
844       return _bson_append (bson,
845                            6,
846                            (1 + key_length + 1 + 4 + 1 + length),
847                            1,
848                            &type,
849                            key_length,
850                            key,
851                            1,
852                            &gZero,
853                            4,
854                            &length_le,
855                            1,
856                            &subtype8,
857                            length,
858                            binary);
859    }
860 }
861 
862 
863 /*
864  *--------------------------------------------------------------------------
865  *
866  * bson_append_bool --
867  *
868  *       Append a new field to @bson with the name @key. The value is
869  *       a boolean indicated by @value.
870  *
871  * Returns:
872  *       true if succesful; otherwise false.
873  *
874  * Side effects:
875  *       None.
876  *
877  *--------------------------------------------------------------------------
878  */
879 
880 bool
bson_append_bool(bson_t * bson,const char * key,int key_length,bool value)881 bson_append_bool (bson_t *bson,    /* IN */
882                   const char *key, /* IN */
883                   int key_length,  /* IN */
884                   bool value)      /* IN */
885 {
886    static const uint8_t type = BSON_TYPE_BOOL;
887    uint8_t abyte = !!value;
888 
889    BSON_ASSERT (bson);
890    BSON_ASSERT (key);
891 
892    if (key_length < 0) {
893       key_length = (int) strlen (key);
894    }
895 
896    return _bson_append (bson,
897                         4,
898                         (1 + key_length + 1 + 1),
899                         1,
900                         &type,
901                         key_length,
902                         key,
903                         1,
904                         &gZero,
905                         1,
906                         &abyte);
907 }
908 
909 
910 /*
911  *--------------------------------------------------------------------------
912  *
913  * bson_append_code --
914  *
915  *       Append a new field to @bson containing javascript code.
916  *
917  *       @javascript MUST be a zero terminated UTF-8 string. It MUST NOT
918  *       containing embedded \0 characters.
919  *
920  * Returns:
921  *       true if successful; otherwise false.
922  *
923  * Side effects:
924  *       None.
925  *
926  * See also:
927  *       bson_append_code_with_scope().
928  *
929  *--------------------------------------------------------------------------
930  */
931 
932 bool
bson_append_code(bson_t * bson,const char * key,int key_length,const char * javascript)933 bson_append_code (bson_t *bson,           /* IN */
934                   const char *key,        /* IN */
935                   int key_length,         /* IN */
936                   const char *javascript) /* IN */
937 {
938    static const uint8_t type = BSON_TYPE_CODE;
939    uint32_t length;
940    uint32_t length_le;
941 
942    BSON_ASSERT (bson);
943    BSON_ASSERT (key);
944    BSON_ASSERT (javascript);
945 
946    if (key_length < 0) {
947       key_length = (int) strlen (key);
948    }
949 
950    length = (int) strlen (javascript) + 1;
951    length_le = BSON_UINT32_TO_LE (length);
952 
953    return _bson_append (bson,
954                         5,
955                         (1 + key_length + 1 + 4 + length),
956                         1,
957                         &type,
958                         key_length,
959                         key,
960                         1,
961                         &gZero,
962                         4,
963                         &length_le,
964                         length,
965                         javascript);
966 }
967 
968 
969 /*
970  *--------------------------------------------------------------------------
971  *
972  * bson_append_code_with_scope --
973  *
974  *       Append a new field to @bson containing javascript code with
975  *       supplied scope.
976  *
977  * Returns:
978  *       true if successful; otherwise false.
979  *
980  * Side effects:
981  *       None.
982  *
983  *--------------------------------------------------------------------------
984  */
985 
986 bool
bson_append_code_with_scope(bson_t * bson,const char * key,int key_length,const char * javascript,const bson_t * scope)987 bson_append_code_with_scope (bson_t *bson,           /* IN */
988                              const char *key,        /* IN */
989                              int key_length,         /* IN */
990                              const char *javascript, /* IN */
991                              const bson_t *scope)    /* IN */
992 {
993    static const uint8_t type = BSON_TYPE_CODEWSCOPE;
994    uint32_t codews_length_le;
995    uint32_t codews_length;
996    uint32_t js_length_le;
997    uint32_t js_length;
998 
999    BSON_ASSERT (bson);
1000    BSON_ASSERT (key);
1001    BSON_ASSERT (javascript);
1002 
1003    if (scope == NULL) {
1004       return bson_append_code (bson, key, key_length, javascript);
1005    }
1006 
1007    if (key_length < 0) {
1008       key_length = (int) strlen (key);
1009    }
1010 
1011    js_length = (int) strlen (javascript) + 1;
1012    js_length_le = BSON_UINT32_TO_LE (js_length);
1013 
1014    codews_length = 4 + 4 + js_length + scope->len;
1015    codews_length_le = BSON_UINT32_TO_LE (codews_length);
1016 
1017    return _bson_append (bson,
1018                         7,
1019                         (1 + key_length + 1 + 4 + 4 + js_length + scope->len),
1020                         1,
1021                         &type,
1022                         key_length,
1023                         key,
1024                         1,
1025                         &gZero,
1026                         4,
1027                         &codews_length_le,
1028                         4,
1029                         &js_length_le,
1030                         js_length,
1031                         javascript,
1032                         scope->len,
1033                         _bson_data (scope));
1034 }
1035 
1036 
1037 /*
1038  *--------------------------------------------------------------------------
1039  *
1040  * bson_append_dbpointer --
1041  *
1042  *       This BSON data type is DEPRECATED.
1043  *
1044  *       Append a BSON dbpointer field to @bson.
1045  *
1046  * Returns:
1047  *       true if successful; otherwise false.
1048  *
1049  * Side effects:
1050  *       None.
1051  *
1052  *--------------------------------------------------------------------------
1053  */
1054 
1055 bool
bson_append_dbpointer(bson_t * bson,const char * key,int key_length,const char * collection,const bson_oid_t * oid)1056 bson_append_dbpointer (bson_t *bson,           /* IN */
1057                        const char *key,        /* IN */
1058                        int key_length,         /* IN */
1059                        const char *collection, /* IN */
1060                        const bson_oid_t *oid)
1061 {
1062    static const uint8_t type = BSON_TYPE_DBPOINTER;
1063    uint32_t length;
1064    uint32_t length_le;
1065 
1066    BSON_ASSERT (bson);
1067    BSON_ASSERT (key);
1068    BSON_ASSERT (collection);
1069    BSON_ASSERT (oid);
1070 
1071    if (key_length < 0) {
1072       key_length = (int) strlen (key);
1073    }
1074 
1075    length = (int) strlen (collection) + 1;
1076    length_le = BSON_UINT32_TO_LE (length);
1077 
1078    return _bson_append (bson,
1079                         6,
1080                         (1 + key_length + 1 + 4 + length + 12),
1081                         1,
1082                         &type,
1083                         key_length,
1084                         key,
1085                         1,
1086                         &gZero,
1087                         4,
1088                         &length_le,
1089                         length,
1090                         collection,
1091                         12,
1092                         oid);
1093 }
1094 
1095 
1096 /*
1097  *--------------------------------------------------------------------------
1098  *
1099  * bson_append_document --
1100  *
1101  *       Append a new field to @bson containing a BSON document.
1102  *
1103  *       In general, using bson_append_document_begin() results in faster
1104  *       code and less memory fragmentation.
1105  *
1106  * Returns:
1107  *       true if successful; otherwise false.
1108  *
1109  * Side effects:
1110  *       None.
1111  *
1112  * See also:
1113  *       bson_append_document_begin().
1114  *
1115  *--------------------------------------------------------------------------
1116  */
1117 
1118 bool
bson_append_document(bson_t * bson,const char * key,int key_length,const bson_t * value)1119 bson_append_document (bson_t *bson,        /* IN */
1120                       const char *key,     /* IN */
1121                       int key_length,      /* IN */
1122                       const bson_t *value) /* IN */
1123 {
1124    static const uint8_t type = BSON_TYPE_DOCUMENT;
1125 
1126    BSON_ASSERT (bson);
1127    BSON_ASSERT (key);
1128    BSON_ASSERT (value);
1129 
1130    if (key_length < 0) {
1131       key_length = (int) strlen (key);
1132    }
1133 
1134    return _bson_append (bson,
1135                         4,
1136                         (1 + key_length + 1 + value->len),
1137                         1,
1138                         &type,
1139                         key_length,
1140                         key,
1141                         1,
1142                         &gZero,
1143                         value->len,
1144                         _bson_data (value));
1145 }
1146 
1147 
1148 bool
bson_append_double(bson_t * bson,const char * key,int key_length,double value)1149 bson_append_double (bson_t *bson, const char *key, int key_length, double value)
1150 {
1151    static const uint8_t type = BSON_TYPE_DOUBLE;
1152 
1153    BSON_ASSERT (bson);
1154    BSON_ASSERT (key);
1155 
1156    if (key_length < 0) {
1157       key_length = (int) strlen (key);
1158    }
1159 
1160 #if BSON_BYTE_ORDER == BSON_BIG_ENDIAN
1161    value = BSON_DOUBLE_TO_LE (value);
1162 #endif
1163 
1164    return _bson_append (bson,
1165                         4,
1166                         (1 + key_length + 1 + 8),
1167                         1,
1168                         &type,
1169                         key_length,
1170                         key,
1171                         1,
1172                         &gZero,
1173                         8,
1174                         &value);
1175 }
1176 
1177 
1178 bool
bson_append_int32(bson_t * bson,const char * key,int key_length,int32_t value)1179 bson_append_int32 (bson_t *bson, const char *key, int key_length, int32_t value)
1180 {
1181    static const uint8_t type = BSON_TYPE_INT32;
1182    uint32_t value_le;
1183 
1184    BSON_ASSERT (bson);
1185    BSON_ASSERT (key);
1186 
1187    if (key_length < 0) {
1188       key_length = (int) strlen (key);
1189    }
1190 
1191    value_le = BSON_UINT32_TO_LE (value);
1192 
1193    return _bson_append (bson,
1194                         4,
1195                         (1 + key_length + 1 + 4),
1196                         1,
1197                         &type,
1198                         key_length,
1199                         key,
1200                         1,
1201                         &gZero,
1202                         4,
1203                         &value_le);
1204 }
1205 
1206 
1207 bool
bson_append_int64(bson_t * bson,const char * key,int key_length,int64_t value)1208 bson_append_int64 (bson_t *bson, const char *key, int key_length, int64_t value)
1209 {
1210    static const uint8_t type = BSON_TYPE_INT64;
1211    uint64_t value_le;
1212 
1213    BSON_ASSERT (bson);
1214    BSON_ASSERT (key);
1215 
1216    if (key_length < 0) {
1217       key_length = (int) strlen (key);
1218    }
1219 
1220    value_le = BSON_UINT64_TO_LE (value);
1221 
1222    return _bson_append (bson,
1223                         4,
1224                         (1 + key_length + 1 + 8),
1225                         1,
1226                         &type,
1227                         key_length,
1228                         key,
1229                         1,
1230                         &gZero,
1231                         8,
1232                         &value_le);
1233 }
1234 
1235 
1236 bool
bson_append_decimal128(bson_t * bson,const char * key,int key_length,const bson_decimal128_t * value)1237 bson_append_decimal128 (bson_t *bson,
1238                         const char *key,
1239                         int key_length,
1240                         const bson_decimal128_t *value)
1241 {
1242    static const uint8_t type = BSON_TYPE_DECIMAL128;
1243    uint64_t value_le[2];
1244 
1245    BSON_ASSERT (bson);
1246    BSON_ASSERT (key);
1247    BSON_ASSERT (value);
1248 
1249    if (key_length < 0) {
1250       key_length = (int) strlen (key);
1251    }
1252 
1253    value_le[0] = BSON_UINT64_TO_LE (value->low);
1254    value_le[1] = BSON_UINT64_TO_LE (value->high);
1255 
1256    return _bson_append (bson,
1257                         4,
1258                         (1 + key_length + 1 + 16),
1259                         1,
1260                         &type,
1261                         key_length,
1262                         key,
1263                         1,
1264                         &gZero,
1265                         16,
1266                         value_le);
1267 }
1268 
1269 
1270 bool
bson_append_iter(bson_t * bson,const char * key,int key_length,const bson_iter_t * iter)1271 bson_append_iter (bson_t *bson,
1272                   const char *key,
1273                   int key_length,
1274                   const bson_iter_t *iter)
1275 {
1276    bool ret = false;
1277 
1278    BSON_ASSERT (bson);
1279    BSON_ASSERT (iter);
1280 
1281    if (!key) {
1282       key = bson_iter_key (iter);
1283       key_length = -1;
1284    }
1285 
1286    switch (bson_iter_type_unsafe (iter)) {
1287    case BSON_TYPE_EOD:
1288       return false;
1289    case BSON_TYPE_DOUBLE:
1290       ret = bson_append_double (bson, key, key_length, bson_iter_double (iter));
1291       break;
1292    case BSON_TYPE_UTF8: {
1293       uint32_t len = 0;
1294       const char *str;
1295 
1296       str = bson_iter_utf8 (iter, &len);
1297       ret = bson_append_utf8 (bson, key, key_length, str, len);
1298    } break;
1299    case BSON_TYPE_DOCUMENT: {
1300       const uint8_t *buf = NULL;
1301       uint32_t len = 0;
1302       bson_t doc;
1303 
1304       bson_iter_document (iter, &len, &buf);
1305 
1306       if (bson_init_static (&doc, buf, len)) {
1307          ret = bson_append_document (bson, key, key_length, &doc);
1308          bson_destroy (&doc);
1309       }
1310    } break;
1311    case BSON_TYPE_ARRAY: {
1312       const uint8_t *buf = NULL;
1313       uint32_t len = 0;
1314       bson_t doc;
1315 
1316       bson_iter_array (iter, &len, &buf);
1317 
1318       if (bson_init_static (&doc, buf, len)) {
1319          ret = bson_append_array (bson, key, key_length, &doc);
1320          bson_destroy (&doc);
1321       }
1322    } break;
1323    case BSON_TYPE_BINARY: {
1324       const uint8_t *binary = NULL;
1325       bson_subtype_t subtype = BSON_SUBTYPE_BINARY;
1326       uint32_t len = 0;
1327 
1328       bson_iter_binary (iter, &subtype, &len, &binary);
1329       ret = bson_append_binary (bson, key, key_length, subtype, binary, len);
1330    } break;
1331    case BSON_TYPE_UNDEFINED:
1332       ret = bson_append_undefined (bson, key, key_length);
1333       break;
1334    case BSON_TYPE_OID:
1335       ret = bson_append_oid (bson, key, key_length, bson_iter_oid (iter));
1336       break;
1337    case BSON_TYPE_BOOL:
1338       ret = bson_append_bool (bson, key, key_length, bson_iter_bool (iter));
1339       break;
1340    case BSON_TYPE_DATE_TIME:
1341       ret = bson_append_date_time (
1342          bson, key, key_length, bson_iter_date_time (iter));
1343       break;
1344    case BSON_TYPE_NULL:
1345       ret = bson_append_null (bson, key, key_length);
1346       break;
1347    case BSON_TYPE_REGEX: {
1348       const char *regex;
1349       const char *options;
1350 
1351       regex = bson_iter_regex (iter, &options);
1352       ret = bson_append_regex (bson, key, key_length, regex, options);
1353    } break;
1354    case BSON_TYPE_DBPOINTER: {
1355       const bson_oid_t *oid;
1356       uint32_t len;
1357       const char *collection;
1358 
1359       bson_iter_dbpointer (iter, &len, &collection, &oid);
1360       ret = bson_append_dbpointer (bson, key, key_length, collection, oid);
1361    } break;
1362    case BSON_TYPE_CODE: {
1363       uint32_t len;
1364       const char *code;
1365 
1366       code = bson_iter_code (iter, &len);
1367       ret = bson_append_code (bson, key, key_length, code);
1368    } break;
1369    case BSON_TYPE_SYMBOL: {
1370       uint32_t len;
1371       const char *symbol;
1372 
1373       symbol = bson_iter_symbol (iter, &len);
1374       ret = bson_append_symbol (bson, key, key_length, symbol, len);
1375    } break;
1376    case BSON_TYPE_CODEWSCOPE: {
1377       const uint8_t *scope = NULL;
1378       uint32_t scope_len = 0;
1379       uint32_t len = 0;
1380       const char *javascript = NULL;
1381       bson_t doc;
1382 
1383       javascript = bson_iter_codewscope (iter, &len, &scope_len, &scope);
1384 
1385       if (bson_init_static (&doc, scope, scope_len)) {
1386          ret = bson_append_code_with_scope (
1387             bson, key, key_length, javascript, &doc);
1388          bson_destroy (&doc);
1389       }
1390    } break;
1391    case BSON_TYPE_INT32:
1392       ret = bson_append_int32 (bson, key, key_length, bson_iter_int32 (iter));
1393       break;
1394    case BSON_TYPE_TIMESTAMP: {
1395       uint32_t ts;
1396       uint32_t inc;
1397 
1398       bson_iter_timestamp (iter, &ts, &inc);
1399       ret = bson_append_timestamp (bson, key, key_length, ts, inc);
1400    } break;
1401    case BSON_TYPE_INT64:
1402       ret = bson_append_int64 (bson, key, key_length, bson_iter_int64 (iter));
1403       break;
1404    case BSON_TYPE_DECIMAL128: {
1405       bson_decimal128_t dec;
1406 
1407       if (!bson_iter_decimal128 (iter, &dec)) {
1408          return false;
1409       }
1410 
1411       ret = bson_append_decimal128 (bson, key, key_length, &dec);
1412    } break;
1413    case BSON_TYPE_MAXKEY:
1414       ret = bson_append_maxkey (bson, key, key_length);
1415       break;
1416    case BSON_TYPE_MINKEY:
1417       ret = bson_append_minkey (bson, key, key_length);
1418       break;
1419    default:
1420       break;
1421    }
1422 
1423    return ret;
1424 }
1425 
1426 
1427 bool
bson_append_maxkey(bson_t * bson,const char * key,int key_length)1428 bson_append_maxkey (bson_t *bson, const char *key, int key_length)
1429 {
1430    static const uint8_t type = BSON_TYPE_MAXKEY;
1431 
1432    BSON_ASSERT (bson);
1433    BSON_ASSERT (key);
1434 
1435    if (key_length < 0) {
1436       key_length = (int) strlen (key);
1437    }
1438 
1439    return _bson_append (
1440       bson, 3, (1 + key_length + 1), 1, &type, key_length, key, 1, &gZero);
1441 }
1442 
1443 
1444 bool
bson_append_minkey(bson_t * bson,const char * key,int key_length)1445 bson_append_minkey (bson_t *bson, const char *key, int key_length)
1446 {
1447    static const uint8_t type = BSON_TYPE_MINKEY;
1448 
1449    BSON_ASSERT (bson);
1450    BSON_ASSERT (key);
1451 
1452    if (key_length < 0) {
1453       key_length = (int) strlen (key);
1454    }
1455 
1456    return _bson_append (
1457       bson, 3, (1 + key_length + 1), 1, &type, key_length, key, 1, &gZero);
1458 }
1459 
1460 
1461 bool
bson_append_null(bson_t * bson,const char * key,int key_length)1462 bson_append_null (bson_t *bson, const char *key, int key_length)
1463 {
1464    static const uint8_t type = BSON_TYPE_NULL;
1465 
1466    BSON_ASSERT (bson);
1467    BSON_ASSERT (key);
1468 
1469    if (key_length < 0) {
1470       key_length = (int) strlen (key);
1471    }
1472 
1473    return _bson_append (
1474       bson, 3, (1 + key_length + 1), 1, &type, key_length, key, 1, &gZero);
1475 }
1476 
1477 
1478 bool
bson_append_oid(bson_t * bson,const char * key,int key_length,const bson_oid_t * value)1479 bson_append_oid (bson_t *bson,
1480                  const char *key,
1481                  int key_length,
1482                  const bson_oid_t *value)
1483 {
1484    static const uint8_t type = BSON_TYPE_OID;
1485 
1486    BSON_ASSERT (bson);
1487    BSON_ASSERT (key);
1488    BSON_ASSERT (value);
1489 
1490    if (key_length < 0) {
1491       key_length = (int) strlen (key);
1492    }
1493 
1494    return _bson_append (bson,
1495                         4,
1496                         (1 + key_length + 1 + 12),
1497                         1,
1498                         &type,
1499                         key_length,
1500                         key,
1501                         1,
1502                         &gZero,
1503                         12,
1504                         value);
1505 }
1506 
1507 
1508 /*
1509  *--------------------------------------------------------------------------
1510  *
1511  * _bson_append_regex_options_sorted --
1512  *
1513  *       Helper to append regex options to a buffer in a sorted order.
1514  *       Any duplicate or unsupported options will be ignored.
1515  *
1516  * Parameters:
1517  *       @buffer: Buffer to which sorted options will be appended
1518  *       @options: Regex options
1519  *
1520  * Returns:
1521  *       None.
1522  *
1523  * Side effects:
1524  *       None.
1525  *
1526  *--------------------------------------------------------------------------
1527  */
1528 
1529 static BSON_INLINE void
_bson_append_regex_options_sorted(bson_string_t * buffer,const char * options)1530 _bson_append_regex_options_sorted (bson_string_t *buffer, /* IN */
1531                                    const char *options)   /* IN */
1532 {
1533    const char *c;
1534 
1535    for (c = BSON_REGEX_OPTIONS_SORTED; *c; c++) {
1536       if (strchr (options, *c)) {
1537          bson_string_append_c (buffer, *c);
1538       }
1539    }
1540 }
1541 
1542 
1543 bool
bson_append_regex(bson_t * bson,const char * key,int key_length,const char * regex,const char * options)1544 bson_append_regex (bson_t *bson,
1545                    const char *key,
1546                    int key_length,
1547                    const char *regex,
1548                    const char *options)
1549 {
1550    static const uint8_t type = BSON_TYPE_REGEX;
1551    uint32_t regex_len;
1552    bson_string_t *options_sorted;
1553    bool r;
1554 
1555    BSON_ASSERT (bson);
1556    BSON_ASSERT (key);
1557 
1558    if (key_length < 0) {
1559       key_length = (int) strlen (key);
1560    }
1561 
1562    if (!regex) {
1563       regex = "";
1564    }
1565 
1566    if (!options) {
1567       options = "";
1568    }
1569 
1570    regex_len = (int) strlen (regex) + 1;
1571    options_sorted = bson_string_new (NULL);
1572 
1573    _bson_append_regex_options_sorted (options_sorted, options);
1574 
1575    r =  _bson_append (bson,
1576                       5,
1577                       (1 + key_length + 1 + regex_len + options_sorted->len),
1578                       1,
1579                       &type,
1580                       key_length,
1581                       key,
1582                       1,
1583                       &gZero,
1584                       regex_len,
1585                       regex,
1586                       options_sorted->len + 1,
1587                       options_sorted->str);
1588 
1589    bson_string_free (options_sorted, true);
1590 
1591    return r;
1592 }
1593 
1594 
1595 bool
bson_append_utf8(bson_t * bson,const char * key,int key_length,const char * value,int length)1596 bson_append_utf8 (
1597    bson_t *bson, const char *key, int key_length, const char *value, int length)
1598 {
1599    static const uint8_t type = BSON_TYPE_UTF8;
1600    uint32_t length_le;
1601 
1602    BSON_ASSERT (bson);
1603    BSON_ASSERT (key);
1604 
1605    if (BSON_UNLIKELY (!value)) {
1606       return bson_append_null (bson, key, key_length);
1607    }
1608 
1609    if (BSON_UNLIKELY (key_length < 0)) {
1610       key_length = (int) strlen (key);
1611    }
1612 
1613    if (BSON_UNLIKELY (length < 0)) {
1614       length = (int) strlen (value);
1615    }
1616 
1617    length_le = BSON_UINT32_TO_LE (length + 1);
1618 
1619    return _bson_append (bson,
1620                         6,
1621                         (1 + key_length + 1 + 4 + length + 1),
1622                         1,
1623                         &type,
1624                         key_length,
1625                         key,
1626                         1,
1627                         &gZero,
1628                         4,
1629                         &length_le,
1630                         length,
1631                         value,
1632                         1,
1633                         &gZero);
1634 }
1635 
1636 
1637 bool
bson_append_symbol(bson_t * bson,const char * key,int key_length,const char * value,int length)1638 bson_append_symbol (
1639    bson_t *bson, const char *key, int key_length, const char *value, int length)
1640 {
1641    static const uint8_t type = BSON_TYPE_SYMBOL;
1642    uint32_t length_le;
1643 
1644    BSON_ASSERT (bson);
1645    BSON_ASSERT (key);
1646 
1647    if (!value) {
1648       return bson_append_null (bson, key, key_length);
1649    }
1650 
1651    if (key_length < 0) {
1652       key_length = (int) strlen (key);
1653    }
1654 
1655    if (length < 0) {
1656       length = (int) strlen (value);
1657    }
1658 
1659    length_le = BSON_UINT32_TO_LE (length + 1);
1660 
1661    return _bson_append (bson,
1662                         6,
1663                         (1 + key_length + 1 + 4 + length + 1),
1664                         1,
1665                         &type,
1666                         key_length,
1667                         key,
1668                         1,
1669                         &gZero,
1670                         4,
1671                         &length_le,
1672                         length,
1673                         value,
1674                         1,
1675                         &gZero);
1676 }
1677 
1678 
1679 bool
bson_append_time_t(bson_t * bson,const char * key,int key_length,time_t value)1680 bson_append_time_t (bson_t *bson, const char *key, int key_length, time_t value)
1681 {
1682 #ifdef BSON_OS_WIN32
1683    struct timeval tv = {(long) value, 0};
1684 #else
1685    struct timeval tv = {value, 0};
1686 #endif
1687 
1688    BSON_ASSERT (bson);
1689    BSON_ASSERT (key);
1690 
1691    return bson_append_timeval (bson, key, key_length, &tv);
1692 }
1693 
1694 
1695 bool
bson_append_timestamp(bson_t * bson,const char * key,int key_length,uint32_t timestamp,uint32_t increment)1696 bson_append_timestamp (bson_t *bson,
1697                        const char *key,
1698                        int key_length,
1699                        uint32_t timestamp,
1700                        uint32_t increment)
1701 {
1702    static const uint8_t type = BSON_TYPE_TIMESTAMP;
1703    uint64_t value;
1704 
1705    BSON_ASSERT (bson);
1706    BSON_ASSERT (key);
1707 
1708    if (key_length < 0) {
1709       key_length = (int) strlen (key);
1710    }
1711 
1712    value = ((((uint64_t) timestamp) << 32) | ((uint64_t) increment));
1713    value = BSON_UINT64_TO_LE (value);
1714 
1715    return _bson_append (bson,
1716                         4,
1717                         (1 + key_length + 1 + 8),
1718                         1,
1719                         &type,
1720                         key_length,
1721                         key,
1722                         1,
1723                         &gZero,
1724                         8,
1725                         &value);
1726 }
1727 
1728 
1729 bool
bson_append_now_utc(bson_t * bson,const char * key,int key_length)1730 bson_append_now_utc (bson_t *bson, const char *key, int key_length)
1731 {
1732    BSON_ASSERT (bson);
1733    BSON_ASSERT (key);
1734    BSON_ASSERT (key_length >= -1);
1735 
1736    return bson_append_time_t (bson, key, key_length, time (NULL));
1737 }
1738 
1739 
1740 bool
bson_append_date_time(bson_t * bson,const char * key,int key_length,int64_t value)1741 bson_append_date_time (bson_t *bson,
1742                        const char *key,
1743                        int key_length,
1744                        int64_t value)
1745 {
1746    static const uint8_t type = BSON_TYPE_DATE_TIME;
1747    uint64_t value_le;
1748 
1749    BSON_ASSERT (bson);
1750    BSON_ASSERT (key);
1751 
1752    if (key_length < 0) {
1753       key_length = (int) strlen (key);
1754    }
1755 
1756    value_le = BSON_UINT64_TO_LE (value);
1757 
1758    return _bson_append (bson,
1759                         4,
1760                         (1 + key_length + 1 + 8),
1761                         1,
1762                         &type,
1763                         key_length,
1764                         key,
1765                         1,
1766                         &gZero,
1767                         8,
1768                         &value_le);
1769 }
1770 
1771 
1772 bool
bson_append_timeval(bson_t * bson,const char * key,int key_length,struct timeval * value)1773 bson_append_timeval (bson_t *bson,
1774                      const char *key,
1775                      int key_length,
1776                      struct timeval *value)
1777 {
1778    uint64_t unix_msec;
1779 
1780    BSON_ASSERT (bson);
1781    BSON_ASSERT (key);
1782    BSON_ASSERT (value);
1783 
1784    unix_msec =
1785       (((uint64_t) value->tv_sec) * 1000UL) + (value->tv_usec / 1000UL);
1786    return bson_append_date_time (bson, key, key_length, unix_msec);
1787 }
1788 
1789 
1790 bool
bson_append_undefined(bson_t * bson,const char * key,int key_length)1791 bson_append_undefined (bson_t *bson, const char *key, int key_length)
1792 {
1793    static const uint8_t type = BSON_TYPE_UNDEFINED;
1794 
1795    BSON_ASSERT (bson);
1796    BSON_ASSERT (key);
1797 
1798    if (key_length < 0) {
1799       key_length = (int) strlen (key);
1800    }
1801 
1802    return _bson_append (
1803       bson, 3, (1 + key_length + 1), 1, &type, key_length, key, 1, &gZero);
1804 }
1805 
1806 
1807 bool
bson_append_value(bson_t * bson,const char * key,int key_length,const bson_value_t * value)1808 bson_append_value (bson_t *bson,
1809                    const char *key,
1810                    int key_length,
1811                    const bson_value_t *value)
1812 {
1813    bson_t local;
1814    bool ret = false;
1815 
1816    BSON_ASSERT (bson);
1817    BSON_ASSERT (key);
1818    BSON_ASSERT (value);
1819 
1820    switch (value->value_type) {
1821    case BSON_TYPE_DOUBLE:
1822       ret = bson_append_double (bson, key, key_length, value->value.v_double);
1823       break;
1824    case BSON_TYPE_UTF8:
1825       ret = bson_append_utf8 (bson,
1826                               key,
1827                               key_length,
1828                               value->value.v_utf8.str,
1829                               value->value.v_utf8.len);
1830       break;
1831    case BSON_TYPE_DOCUMENT:
1832       if (bson_init_static (
1833              &local, value->value.v_doc.data, value->value.v_doc.data_len)) {
1834          ret = bson_append_document (bson, key, key_length, &local);
1835          bson_destroy (&local);
1836       }
1837       break;
1838    case BSON_TYPE_ARRAY:
1839       if (bson_init_static (
1840              &local, value->value.v_doc.data, value->value.v_doc.data_len)) {
1841          ret = bson_append_array (bson, key, key_length, &local);
1842          bson_destroy (&local);
1843       }
1844       break;
1845    case BSON_TYPE_BINARY:
1846       ret = bson_append_binary (bson,
1847                                 key,
1848                                 key_length,
1849                                 value->value.v_binary.subtype,
1850                                 value->value.v_binary.data,
1851                                 value->value.v_binary.data_len);
1852       break;
1853    case BSON_TYPE_UNDEFINED:
1854       ret = bson_append_undefined (bson, key, key_length);
1855       break;
1856    case BSON_TYPE_OID:
1857       ret = bson_append_oid (bson, key, key_length, &value->value.v_oid);
1858       break;
1859    case BSON_TYPE_BOOL:
1860       ret = bson_append_bool (bson, key, key_length, value->value.v_bool);
1861       break;
1862    case BSON_TYPE_DATE_TIME:
1863       ret =
1864          bson_append_date_time (bson, key, key_length, value->value.v_datetime);
1865       break;
1866    case BSON_TYPE_NULL:
1867       ret = bson_append_null (bson, key, key_length);
1868       break;
1869    case BSON_TYPE_REGEX:
1870       ret = bson_append_regex (bson,
1871                                key,
1872                                key_length,
1873                                value->value.v_regex.regex,
1874                                value->value.v_regex.options);
1875       break;
1876    case BSON_TYPE_DBPOINTER:
1877       ret = bson_append_dbpointer (bson,
1878                                    key,
1879                                    key_length,
1880                                    value->value.v_dbpointer.collection,
1881                                    &value->value.v_dbpointer.oid);
1882       break;
1883    case BSON_TYPE_CODE:
1884       ret = bson_append_code (bson, key, key_length, value->value.v_code.code);
1885       break;
1886    case BSON_TYPE_SYMBOL:
1887       ret = bson_append_symbol (bson,
1888                                 key,
1889                                 key_length,
1890                                 value->value.v_symbol.symbol,
1891                                 value->value.v_symbol.len);
1892       break;
1893    case BSON_TYPE_CODEWSCOPE:
1894       if (bson_init_static (&local,
1895                             value->value.v_codewscope.scope_data,
1896                             value->value.v_codewscope.scope_len)) {
1897          ret = bson_append_code_with_scope (
1898             bson, key, key_length, value->value.v_codewscope.code, &local);
1899          bson_destroy (&local);
1900       }
1901       break;
1902    case BSON_TYPE_INT32:
1903       ret = bson_append_int32 (bson, key, key_length, value->value.v_int32);
1904       break;
1905    case BSON_TYPE_TIMESTAMP:
1906       ret = bson_append_timestamp (bson,
1907                                    key,
1908                                    key_length,
1909                                    value->value.v_timestamp.timestamp,
1910                                    value->value.v_timestamp.increment);
1911       break;
1912    case BSON_TYPE_INT64:
1913       ret = bson_append_int64 (bson, key, key_length, value->value.v_int64);
1914       break;
1915    case BSON_TYPE_DECIMAL128:
1916       ret = bson_append_decimal128 (
1917          bson, key, key_length, &(value->value.v_decimal128));
1918       break;
1919    case BSON_TYPE_MAXKEY:
1920       ret = bson_append_maxkey (bson, key, key_length);
1921       break;
1922    case BSON_TYPE_MINKEY:
1923       ret = bson_append_minkey (bson, key, key_length);
1924       break;
1925    case BSON_TYPE_EOD:
1926    default:
1927       break;
1928    }
1929 
1930    return ret;
1931 }
1932 
1933 
1934 void
bson_init(bson_t * bson)1935 bson_init (bson_t *bson)
1936 {
1937    bson_impl_inline_t *impl = (bson_impl_inline_t *) bson;
1938 
1939    BSON_ASSERT (bson);
1940 
1941    impl->flags = BSON_FLAG_INLINE | BSON_FLAG_STATIC;
1942    impl->len = 5;
1943    impl->data[0] = 5;
1944    impl->data[1] = 0;
1945    impl->data[2] = 0;
1946    impl->data[3] = 0;
1947    impl->data[4] = 0;
1948 }
1949 
1950 
1951 void
bson_reinit(bson_t * bson)1952 bson_reinit (bson_t *bson)
1953 {
1954    uint8_t *data;
1955 
1956    BSON_ASSERT (bson);
1957 
1958    data = _bson_data (bson);
1959 
1960    bson->len = 5;
1961 
1962    data[0] = 5;
1963    data[1] = 0;
1964    data[2] = 0;
1965    data[3] = 0;
1966    data[4] = 0;
1967 }
1968 
1969 
1970 bool
bson_init_static(bson_t * bson,const uint8_t * data,size_t length)1971 bson_init_static (bson_t *bson, const uint8_t *data, size_t length)
1972 {
1973    bson_impl_alloc_t *impl = (bson_impl_alloc_t *) bson;
1974    uint32_t len_le;
1975 
1976    BSON_ASSERT (bson);
1977    BSON_ASSERT (data);
1978 
1979    if ((length < 5) || (length > INT_MAX)) {
1980       return false;
1981    }
1982 
1983    memcpy (&len_le, data, sizeof (len_le));
1984 
1985    if ((size_t) BSON_UINT32_FROM_LE (len_le) != length) {
1986       return false;
1987    }
1988 
1989    if (data[length - 1]) {
1990       return false;
1991    }
1992 
1993    impl->flags = BSON_FLAG_STATIC | BSON_FLAG_RDONLY;
1994    impl->len = (uint32_t) length;
1995    impl->parent = NULL;
1996    impl->depth = 0;
1997    impl->buf = &impl->alloc;
1998    impl->buflen = &impl->alloclen;
1999    impl->offset = 0;
2000    impl->alloc = (uint8_t *) data;
2001    impl->alloclen = length;
2002    impl->realloc = NULL;
2003    impl->realloc_func_ctx = NULL;
2004 
2005    return true;
2006 }
2007 
2008 
2009 bson_t *
bson_new(void)2010 bson_new (void)
2011 {
2012    bson_impl_inline_t *impl;
2013    bson_t *bson;
2014 
2015    bson = bson_malloc (sizeof *bson);
2016 
2017    impl = (bson_impl_inline_t *) bson;
2018    impl->flags = BSON_FLAG_INLINE;
2019    impl->len = 5;
2020    impl->data[0] = 5;
2021    impl->data[1] = 0;
2022    impl->data[2] = 0;
2023    impl->data[3] = 0;
2024    impl->data[4] = 0;
2025 
2026    return bson;
2027 }
2028 
2029 
2030 bson_t *
bson_sized_new(size_t size)2031 bson_sized_new (size_t size)
2032 {
2033    bson_impl_alloc_t *impl_a;
2034    bson_t *b;
2035 
2036    BSON_ASSERT (size <= INT32_MAX);
2037 
2038    b = bson_malloc (sizeof *b);
2039    impl_a = (bson_impl_alloc_t *) b;
2040 
2041    if (size <= BSON_INLINE_DATA_SIZE) {
2042       bson_init (b);
2043       b->flags &= ~BSON_FLAG_STATIC;
2044    } else {
2045       impl_a->flags = BSON_FLAG_NONE;
2046       impl_a->len = 5;
2047       impl_a->parent = NULL;
2048       impl_a->depth = 0;
2049       impl_a->buf = &impl_a->alloc;
2050       impl_a->buflen = &impl_a->alloclen;
2051       impl_a->offset = 0;
2052       impl_a->alloclen = BSON_MAX (5, size);
2053       impl_a->alloc = bson_malloc (impl_a->alloclen);
2054       impl_a->alloc[0] = 5;
2055       impl_a->alloc[1] = 0;
2056       impl_a->alloc[2] = 0;
2057       impl_a->alloc[3] = 0;
2058       impl_a->alloc[4] = 0;
2059       impl_a->realloc = bson_realloc_ctx;
2060       impl_a->realloc_func_ctx = NULL;
2061    }
2062 
2063    return b;
2064 }
2065 
2066 
2067 bson_t *
bson_new_from_data(const uint8_t * data,size_t length)2068 bson_new_from_data (const uint8_t *data, size_t length)
2069 {
2070    uint32_t len_le;
2071    bson_t *bson;
2072 
2073    BSON_ASSERT (data);
2074 
2075    if ((length < 5) || (length > INT_MAX) || data[length - 1]) {
2076       return NULL;
2077    }
2078 
2079    memcpy (&len_le, data, sizeof (len_le));
2080 
2081    if (length != (size_t) BSON_UINT32_FROM_LE (len_le)) {
2082       return NULL;
2083    }
2084 
2085    bson = bson_sized_new (length);
2086    memcpy (_bson_data (bson), data, length);
2087    bson->len = (uint32_t) length;
2088 
2089    return bson;
2090 }
2091 
2092 
2093 bson_t *
bson_new_from_buffer(uint8_t ** buf,size_t * buf_len,bson_realloc_func realloc_func,void * realloc_func_ctx)2094 bson_new_from_buffer (uint8_t **buf,
2095                       size_t *buf_len,
2096                       bson_realloc_func realloc_func,
2097                       void *realloc_func_ctx)
2098 {
2099    bson_impl_alloc_t *impl;
2100    uint32_t len_le;
2101    uint32_t length;
2102    bson_t *bson;
2103 
2104    BSON_ASSERT (buf);
2105    BSON_ASSERT (buf_len);
2106 
2107    if (!realloc_func) {
2108       realloc_func = bson_realloc_ctx;
2109    }
2110 
2111    bson = bson_malloc0 (sizeof *bson);
2112    impl = (bson_impl_alloc_t *) bson;
2113 
2114    if (!*buf) {
2115       length = 5;
2116       len_le = BSON_UINT32_TO_LE (length);
2117       *buf_len = 5;
2118       *buf = realloc_func (*buf, *buf_len, realloc_func_ctx);
2119       memcpy (*buf, &len_le, sizeof (len_le));
2120       (*buf)[4] = '\0';
2121    } else {
2122       if ((*buf_len < 5) || (*buf_len > INT_MAX)) {
2123          bson_free (bson);
2124          return NULL;
2125       }
2126 
2127       memcpy (&len_le, *buf, sizeof (len_le));
2128       length = BSON_UINT32_FROM_LE (len_le);
2129    }
2130 
2131    if ((*buf)[length - 1]) {
2132       bson_free (bson);
2133       return NULL;
2134    }
2135 
2136    impl->flags = BSON_FLAG_NO_FREE;
2137    impl->len = length;
2138    impl->buf = buf;
2139    impl->buflen = buf_len;
2140    impl->realloc = realloc_func;
2141    impl->realloc_func_ctx = realloc_func_ctx;
2142 
2143    return bson;
2144 }
2145 
2146 
2147 bson_t *
bson_copy(const bson_t * bson)2148 bson_copy (const bson_t *bson)
2149 {
2150    const uint8_t *data;
2151 
2152    BSON_ASSERT (bson);
2153 
2154    data = _bson_data (bson);
2155    return bson_new_from_data (data, bson->len);
2156 }
2157 
2158 
2159 void
bson_copy_to(const bson_t * src,bson_t * dst)2160 bson_copy_to (const bson_t *src, bson_t *dst)
2161 {
2162    const uint8_t *data;
2163    bson_impl_alloc_t *adst;
2164    size_t len;
2165 
2166    BSON_ASSERT (src);
2167    BSON_ASSERT (dst);
2168 
2169    if ((src->flags & BSON_FLAG_INLINE)) {
2170       memcpy (dst, src, sizeof *dst);
2171       dst->flags = (BSON_FLAG_STATIC | BSON_FLAG_INLINE);
2172       return;
2173    }
2174 
2175    data = _bson_data (src);
2176    len = bson_next_power_of_two ((size_t) src->len);
2177 
2178    adst = (bson_impl_alloc_t *) dst;
2179    adst->flags = BSON_FLAG_STATIC;
2180    adst->len = src->len;
2181    adst->parent = NULL;
2182    adst->depth = 0;
2183    adst->buf = &adst->alloc;
2184    adst->buflen = &adst->alloclen;
2185    adst->offset = 0;
2186    adst->alloc = bson_malloc (len);
2187    adst->alloclen = len;
2188    adst->realloc = bson_realloc_ctx;
2189    adst->realloc_func_ctx = NULL;
2190    memcpy (adst->alloc, data, src->len);
2191 }
2192 
2193 
2194 static bool
should_ignore(const char * first_exclude,va_list args,const char * name)2195 should_ignore (const char *first_exclude, va_list args, const char *name)
2196 {
2197    bool ret = false;
2198    const char *exclude = first_exclude;
2199    va_list args_copy;
2200 
2201    va_copy (args_copy, args);
2202 
2203    do {
2204       if (!strcmp (name, exclude)) {
2205          ret = true;
2206          break;
2207       }
2208    } while ((exclude = va_arg (args_copy, const char *)));
2209 
2210    va_end (args_copy);
2211 
2212    return ret;
2213 }
2214 
2215 
2216 static void
_bson_copy_to_excluding_va(const bson_t * src,bson_t * dst,const char * first_exclude,va_list args)2217 _bson_copy_to_excluding_va (const bson_t *src,
2218                             bson_t *dst,
2219                             const char *first_exclude,
2220                             va_list args)
2221 {
2222    bson_iter_t iter;
2223 
2224    if (bson_iter_init (&iter, src)) {
2225       while (bson_iter_next (&iter)) {
2226          if (!should_ignore (first_exclude, args, bson_iter_key (&iter))) {
2227             if (!bson_append_iter (dst, NULL, 0, &iter)) {
2228                /*
2229                 * This should not be able to happen since we are copying
2230                 * from within a valid bson_t.
2231                 */
2232                BSON_ASSERT (false);
2233                return;
2234             }
2235          }
2236       }
2237    }
2238 }
2239 
2240 
2241 void
bson_copy_to_excluding(const bson_t * src,bson_t * dst,const char * first_exclude,...)2242 bson_copy_to_excluding (const bson_t *src,
2243                         bson_t *dst,
2244                         const char *first_exclude,
2245                         ...)
2246 {
2247    va_list args;
2248 
2249    BSON_ASSERT (src);
2250    BSON_ASSERT (dst);
2251    BSON_ASSERT (first_exclude);
2252 
2253    bson_init (dst);
2254 
2255    va_start (args, first_exclude);
2256    _bson_copy_to_excluding_va (src, dst, first_exclude, args);
2257    va_end (args);
2258 }
2259 
2260 void
bson_copy_to_excluding_noinit(const bson_t * src,bson_t * dst,const char * first_exclude,...)2261 bson_copy_to_excluding_noinit (const bson_t *src,
2262                                bson_t *dst,
2263                                const char *first_exclude,
2264                                ...)
2265 {
2266    va_list args;
2267 
2268    BSON_ASSERT (src);
2269    BSON_ASSERT (dst);
2270    BSON_ASSERT (first_exclude);
2271 
2272    va_start (args, first_exclude);
2273    _bson_copy_to_excluding_va (src, dst, first_exclude, args);
2274    va_end (args);
2275 }
2276 
2277 
2278 void
bson_destroy(bson_t * bson)2279 bson_destroy (bson_t *bson)
2280 {
2281    BSON_ASSERT (bson);
2282 
2283    if (!(bson->flags &
2284          (BSON_FLAG_RDONLY | BSON_FLAG_INLINE | BSON_FLAG_NO_FREE))) {
2285       bson_free (*((bson_impl_alloc_t *) bson)->buf);
2286    }
2287 
2288    if (!(bson->flags & BSON_FLAG_STATIC)) {
2289       bson_free (bson);
2290    }
2291 }
2292 
2293 
2294 uint8_t *
bson_reserve_buffer(bson_t * bson,uint32_t size)2295 bson_reserve_buffer (bson_t *bson, uint32_t size)
2296 {
2297    if (bson->flags &
2298        (BSON_FLAG_CHILD | BSON_FLAG_IN_CHILD | BSON_FLAG_RDONLY)) {
2299       return NULL;
2300    }
2301 
2302    if (!_bson_grow (bson, size)) {
2303       return NULL;
2304    }
2305 
2306    if (bson->flags & BSON_FLAG_INLINE) {
2307       /* bson_grow didn't spill over */
2308       ((bson_impl_inline_t *) bson)->len = size;
2309    } else {
2310       ((bson_impl_alloc_t *) bson)->len = size;
2311    }
2312 
2313    return _bson_data (bson);
2314 }
2315 
2316 
2317 bool
bson_steal(bson_t * dst,bson_t * src)2318 bson_steal (bson_t *dst, bson_t *src)
2319 {
2320    bson_impl_inline_t *src_inline;
2321    bson_impl_inline_t *dst_inline;
2322    bson_impl_alloc_t *alloc;
2323 
2324    BSON_ASSERT (dst);
2325    BSON_ASSERT (src);
2326 
2327    bson_init (dst);
2328 
2329    if (src->flags & (BSON_FLAG_CHILD | BSON_FLAG_IN_CHILD | BSON_FLAG_RDONLY)) {
2330       return false;
2331    }
2332 
2333    if (src->flags & BSON_FLAG_INLINE) {
2334       src_inline = (bson_impl_inline_t *) src;
2335       dst_inline = (bson_impl_inline_t *) dst;
2336       dst_inline->len = src_inline->len;
2337       memcpy (dst_inline->data, src_inline->data, sizeof src_inline->data);
2338 
2339       /* for consistency, src is always invalid after steal, even if inline */
2340       src->len = 0;
2341    } else {
2342       memcpy (dst, src, sizeof (bson_t));
2343       alloc = (bson_impl_alloc_t *) dst;
2344       alloc->flags |= BSON_FLAG_STATIC;
2345       alloc->buf = &alloc->alloc;
2346       alloc->buflen = &alloc->alloclen;
2347    }
2348 
2349    if (!(src->flags & BSON_FLAG_STATIC)) {
2350       bson_free (src);
2351    } else {
2352       /* src is invalid after steal */
2353       src->len = 0;
2354    }
2355 
2356    return true;
2357 }
2358 
2359 
2360 uint8_t *
bson_destroy_with_steal(bson_t * bson,bool steal,uint32_t * length)2361 bson_destroy_with_steal (bson_t *bson, bool steal, uint32_t *length)
2362 {
2363    uint8_t *ret = NULL;
2364 
2365    BSON_ASSERT (bson);
2366 
2367    if (length) {
2368       *length = bson->len;
2369    }
2370 
2371    if (!steal) {
2372       bson_destroy (bson);
2373       return NULL;
2374    }
2375 
2376    if ((bson->flags &
2377         (BSON_FLAG_CHILD | BSON_FLAG_IN_CHILD | BSON_FLAG_RDONLY))) {
2378       /* Do nothing */
2379    } else if ((bson->flags & BSON_FLAG_INLINE)) {
2380       bson_impl_inline_t *inl;
2381 
2382       inl = (bson_impl_inline_t *) bson;
2383       ret = bson_malloc (bson->len);
2384       memcpy (ret, inl->data, bson->len);
2385    } else {
2386       bson_impl_alloc_t *alloc;
2387 
2388       alloc = (bson_impl_alloc_t *) bson;
2389       ret = *alloc->buf;
2390       *alloc->buf = NULL;
2391    }
2392 
2393    bson_destroy (bson);
2394 
2395    return ret;
2396 }
2397 
2398 
2399 const uint8_t *
bson_get_data(const bson_t * bson)2400 bson_get_data (const bson_t *bson)
2401 {
2402    BSON_ASSERT (bson);
2403 
2404    return _bson_data (bson);
2405 }
2406 
2407 
2408 uint32_t
bson_count_keys(const bson_t * bson)2409 bson_count_keys (const bson_t *bson)
2410 {
2411    uint32_t count = 0;
2412    bson_iter_t iter;
2413 
2414    BSON_ASSERT (bson);
2415 
2416    if (bson_iter_init (&iter, bson)) {
2417       while (bson_iter_next (&iter)) {
2418          count++;
2419       }
2420    }
2421 
2422    return count;
2423 }
2424 
2425 
2426 bool
bson_has_field(const bson_t * bson,const char * key)2427 bson_has_field (const bson_t *bson, const char *key)
2428 {
2429    bson_iter_t iter;
2430    bson_iter_t child;
2431 
2432    BSON_ASSERT (bson);
2433    BSON_ASSERT (key);
2434 
2435    if (NULL != strchr (key, '.')) {
2436       return (bson_iter_init (&iter, bson) &&
2437               bson_iter_find_descendant (&iter, key, &child));
2438    }
2439 
2440    return bson_iter_init_find (&iter, bson, key);
2441 }
2442 
2443 
2444 int
bson_compare(const bson_t * bson,const bson_t * other)2445 bson_compare (const bson_t *bson, const bson_t *other)
2446 {
2447    const uint8_t *data1;
2448    const uint8_t *data2;
2449    size_t len1;
2450    size_t len2;
2451    int64_t ret;
2452 
2453    data1 = _bson_data (bson) + 4;
2454    len1 = bson->len - 4;
2455 
2456    data2 = _bson_data (other) + 4;
2457    len2 = other->len - 4;
2458 
2459    if (len1 == len2) {
2460       return memcmp (data1, data2, len1);
2461    }
2462 
2463    ret = memcmp (data1, data2, BSON_MIN (len1, len2));
2464 
2465    if (ret == 0) {
2466       ret = (int64_t) (len1 - len2);
2467    }
2468 
2469    return (ret < 0) ? -1 : (ret > 0);
2470 }
2471 
2472 
2473 bool
bson_equal(const bson_t * bson,const bson_t * other)2474 bson_equal (const bson_t *bson, const bson_t *other)
2475 {
2476    return !bson_compare (bson, other);
2477 }
2478 
2479 
2480 static bool
_bson_as_json_visit_utf8(const bson_iter_t * iter,const char * key,size_t v_utf8_len,const char * v_utf8,void * data)2481 _bson_as_json_visit_utf8 (const bson_iter_t *iter,
2482                           const char *key,
2483                           size_t v_utf8_len,
2484                           const char *v_utf8,
2485                           void *data)
2486 {
2487    bson_json_state_t *state = data;
2488    char *escaped;
2489 
2490    escaped = bson_utf8_escape_for_json (v_utf8, v_utf8_len);
2491 
2492    if (escaped) {
2493       bson_string_append (state->str, "\"");
2494       bson_string_append (state->str, escaped);
2495       bson_string_append (state->str, "\"");
2496       bson_free (escaped);
2497       return false;
2498    }
2499 
2500    return true;
2501 }
2502 
2503 
2504 static bool
_bson_as_json_visit_int32(const bson_iter_t * iter,const char * key,int32_t v_int32,void * data)2505 _bson_as_json_visit_int32 (const bson_iter_t *iter,
2506                            const char *key,
2507                            int32_t v_int32,
2508                            void *data)
2509 {
2510    bson_json_state_t *state = data;
2511 
2512    if (state->mode == BSON_JSON_MODE_CANONICAL) {
2513       bson_string_append_printf (
2514          state->str, "{ \"$numberInt\" : \"%" PRId32 "\" }", v_int32);
2515    } else {
2516       bson_string_append_printf (state->str, "%" PRId32, v_int32);
2517    }
2518 
2519    return false;
2520 }
2521 
2522 
2523 static bool
_bson_as_json_visit_int64(const bson_iter_t * iter,const char * key,int64_t v_int64,void * data)2524 _bson_as_json_visit_int64 (const bson_iter_t *iter,
2525                            const char *key,
2526                            int64_t v_int64,
2527                            void *data)
2528 {
2529    bson_json_state_t *state = data;
2530 
2531    if (state->mode == BSON_JSON_MODE_CANONICAL) {
2532       bson_string_append_printf (
2533          state->str, "{ \"$numberLong\" : \"%" PRId64 "\"}", v_int64);
2534    } else {
2535       bson_string_append_printf (state->str, "%" PRId64, v_int64);
2536    }
2537 
2538    return false;
2539 }
2540 
2541 
2542 static bool
_bson_as_json_visit_decimal128(const bson_iter_t * iter,const char * key,const bson_decimal128_t * value,void * data)2543 _bson_as_json_visit_decimal128 (const bson_iter_t *iter,
2544                                 const char *key,
2545                                 const bson_decimal128_t *value,
2546                                 void *data)
2547 {
2548    bson_json_state_t *state = data;
2549    char decimal128_string[BSON_DECIMAL128_STRING];
2550    bson_decimal128_to_string (value, decimal128_string);
2551 
2552    bson_string_append (state->str, "{ \"$numberDecimal\" : \"");
2553    bson_string_append (state->str, decimal128_string);
2554    bson_string_append (state->str, "\" }");
2555 
2556    return false;
2557 }
2558 
2559 
2560 static bool
_bson_as_json_visit_double(const bson_iter_t * iter,const char * key,double v_double,void * data)2561 _bson_as_json_visit_double (const bson_iter_t *iter,
2562                             const char *key,
2563                             double v_double,
2564                             void *data)
2565 {
2566    bson_json_state_t *state = data;
2567    bson_string_t *str = state->str;
2568    uint32_t start_len;
2569    bool legacy;
2570 
2571    /* Determine if legacy (i.e. unwrapped) output should be used. Relaxed mode
2572     * will use this for nan and inf values, which we check manually since old
2573     * platforms may not have isinf or isnan. */
2574    legacy = state->mode == BSON_JSON_MODE_LEGACY ||
2575             (state->mode == BSON_JSON_MODE_RELAXED &&
2576              !(v_double != v_double || v_double * 0 != 0));
2577 
2578    if (!legacy) {
2579       bson_string_append (state->str, "{ \"$numberDouble\" : \"");
2580    }
2581 
2582    if (!legacy && v_double != v_double) {
2583       bson_string_append (str, "NaN");
2584    } else if (!legacy && v_double * 0 != 0) {
2585       if (v_double > 0) {
2586          bson_string_append (str, "Infinity");
2587       } else {
2588          bson_string_append (str, "-Infinity");
2589       }
2590    } else {
2591       start_len = str->len;
2592       bson_string_append_printf (str, "%.20g", v_double);
2593 
2594       /* ensure trailing ".0" to distinguish "3" from "3.0" */
2595       if (strspn (&str->str[start_len], "0123456789-") ==
2596           str->len - start_len) {
2597          bson_string_append (str, ".0");
2598       }
2599    }
2600 
2601    if (!legacy) {
2602       bson_string_append (state->str, "\" }");
2603    }
2604 
2605    return false;
2606 }
2607 
2608 
2609 static bool
_bson_as_json_visit_undefined(const bson_iter_t * iter,const char * key,void * data)2610 _bson_as_json_visit_undefined (const bson_iter_t *iter,
2611                                const char *key,
2612                                void *data)
2613 {
2614    bson_json_state_t *state = data;
2615 
2616    bson_string_append (state->str, "{ \"$undefined\" : true }");
2617 
2618    return false;
2619 }
2620 
2621 
2622 static bool
_bson_as_json_visit_null(const bson_iter_t * iter,const char * key,void * data)2623 _bson_as_json_visit_null (const bson_iter_t *iter, const char *key, void *data)
2624 {
2625    bson_json_state_t *state = data;
2626 
2627    bson_string_append (state->str, "null");
2628 
2629    return false;
2630 }
2631 
2632 
2633 static bool
_bson_as_json_visit_oid(const bson_iter_t * iter,const char * key,const bson_oid_t * oid,void * data)2634 _bson_as_json_visit_oid (const bson_iter_t *iter,
2635                          const char *key,
2636                          const bson_oid_t *oid,
2637                          void *data)
2638 {
2639    bson_json_state_t *state = data;
2640    char str[25];
2641 
2642    bson_oid_to_string (oid, str);
2643    bson_string_append (state->str, "{ \"$oid\" : \"");
2644    bson_string_append (state->str, str);
2645    bson_string_append (state->str, "\" }");
2646 
2647    return false;
2648 }
2649 
2650 
2651 static bool
_bson_as_json_visit_binary(const bson_iter_t * iter,const char * key,bson_subtype_t v_subtype,size_t v_binary_len,const uint8_t * v_binary,void * data)2652 _bson_as_json_visit_binary (const bson_iter_t *iter,
2653                             const char *key,
2654                             bson_subtype_t v_subtype,
2655                             size_t v_binary_len,
2656                             const uint8_t *v_binary,
2657                             void *data)
2658 {
2659    bson_json_state_t *state = data;
2660    size_t b64_len;
2661    char *b64;
2662 
2663    b64_len = (v_binary_len / 3 + 1) * 4 + 1;
2664    b64 = bson_malloc0 (b64_len);
2665    b64_ntop (v_binary, v_binary_len, b64, b64_len);
2666 
2667    if (state->mode == BSON_JSON_MODE_CANONICAL ||
2668        state->mode == BSON_JSON_MODE_RELAXED) {
2669       bson_string_append (state->str, "{ \"$binary\" : { \"base64\": \"");
2670       bson_string_append (state->str, b64);
2671       bson_string_append (state->str, "\", \"subType\" : \"");
2672       bson_string_append_printf (state->str, "%02x", v_subtype);
2673       bson_string_append (state->str, "\" } }");
2674    } else {
2675       bson_string_append (state->str, "{ \"$binary\" : \"");
2676       bson_string_append (state->str, b64);
2677       bson_string_append (state->str, "\", \"$type\" : \"");
2678       bson_string_append_printf (state->str, "%02x", v_subtype);
2679       bson_string_append (state->str, "\" }");
2680    }
2681 
2682    bson_free (b64);
2683 
2684    return false;
2685 }
2686 
2687 
2688 static bool
_bson_as_json_visit_bool(const bson_iter_t * iter,const char * key,bool v_bool,void * data)2689 _bson_as_json_visit_bool (const bson_iter_t *iter,
2690                           const char *key,
2691                           bool v_bool,
2692                           void *data)
2693 {
2694    bson_json_state_t *state = data;
2695 
2696    bson_string_append (state->str, v_bool ? "true" : "false");
2697 
2698    return false;
2699 }
2700 
2701 
2702 static bool
_bson_as_json_visit_date_time(const bson_iter_t * iter,const char * key,int64_t msec_since_epoch,void * data)2703 _bson_as_json_visit_date_time (const bson_iter_t *iter,
2704                                const char *key,
2705                                int64_t msec_since_epoch,
2706                                void *data)
2707 {
2708    bson_json_state_t *state = data;
2709 
2710    if (state->mode == BSON_JSON_MODE_CANONICAL ||
2711        (state->mode == BSON_JSON_MODE_RELAXED && msec_since_epoch < 0)) {
2712       bson_string_append (state->str, "{ \"$date\" : { \"$numberLong\" : \"");
2713       bson_string_append_printf (state->str, "%" PRId64, msec_since_epoch);
2714       bson_string_append (state->str, "\" } }");
2715    } else if (state->mode == BSON_JSON_MODE_RELAXED) {
2716       bson_string_append (state->str, "{ \"$date\" : \"");
2717       _bson_iso8601_date_format (msec_since_epoch, state->str);
2718       bson_string_append (state->str, "\" }");
2719    } else {
2720       bson_string_append (state->str, "{ \"$date\" : ");
2721       bson_string_append_printf (state->str, "%" PRId64, msec_since_epoch);
2722       bson_string_append (state->str, " }");
2723    }
2724 
2725    return false;
2726 }
2727 
2728 
2729 static bool
_bson_as_json_visit_regex(const bson_iter_t * iter,const char * key,const char * v_regex,const char * v_options,void * data)2730 _bson_as_json_visit_regex (const bson_iter_t *iter,
2731                            const char *key,
2732                            const char *v_regex,
2733                            const char *v_options,
2734                            void *data)
2735 {
2736    bson_json_state_t *state = data;
2737    char *escaped;
2738 
2739    escaped = bson_utf8_escape_for_json (v_regex, -1);
2740    if (!escaped) {
2741       return true;
2742    }
2743 
2744    if (state->mode == BSON_JSON_MODE_CANONICAL ||
2745        state->mode == BSON_JSON_MODE_RELAXED) {
2746       bson_string_append (state->str,
2747                           "{ \"$regularExpression\" : { \"pattern\" : \"");
2748       bson_string_append (state->str, escaped);
2749       bson_string_append (state->str, "\", \"options\" : \"");
2750       _bson_append_regex_options_sorted (state->str, v_options);
2751       bson_string_append (state->str, "\" } }");
2752    } else {
2753       bson_string_append (state->str, "{ \"$regex\" : \"");
2754       bson_string_append (state->str, escaped);
2755       bson_string_append (state->str, "\", \"$options\" : \"");
2756       _bson_append_regex_options_sorted (state->str, v_options);
2757       bson_string_append (state->str, "\" }");
2758    }
2759 
2760    bson_free (escaped);
2761 
2762    return false;
2763 }
2764 
2765 
2766 static bool
_bson_as_json_visit_timestamp(const bson_iter_t * iter,const char * key,uint32_t v_timestamp,uint32_t v_increment,void * data)2767 _bson_as_json_visit_timestamp (const bson_iter_t *iter,
2768                                const char *key,
2769                                uint32_t v_timestamp,
2770                                uint32_t v_increment,
2771                                void *data)
2772 {
2773    bson_json_state_t *state = data;
2774 
2775    bson_string_append (state->str, "{ \"$timestamp\" : { \"t\" : ");
2776    bson_string_append_printf (state->str, "%u", v_timestamp);
2777    bson_string_append (state->str, ", \"i\" : ");
2778    bson_string_append_printf (state->str, "%u", v_increment);
2779    bson_string_append (state->str, " } }");
2780 
2781    return false;
2782 }
2783 
2784 
2785 static bool
_bson_as_json_visit_dbpointer(const bson_iter_t * iter,const char * key,size_t v_collection_len,const char * v_collection,const bson_oid_t * v_oid,void * data)2786 _bson_as_json_visit_dbpointer (const bson_iter_t *iter,
2787                                const char *key,
2788                                size_t v_collection_len,
2789                                const char *v_collection,
2790                                const bson_oid_t *v_oid,
2791                                void *data)
2792 {
2793    bson_json_state_t *state = data;
2794    char *escaped;
2795    char str[25];
2796 
2797    escaped = bson_utf8_escape_for_json (v_collection, -1);
2798    if (!escaped) {
2799       return true;
2800    }
2801 
2802    if (state->mode == BSON_JSON_MODE_CANONICAL ||
2803        state->mode == BSON_JSON_MODE_RELAXED) {
2804       bson_string_append (state->str, "{ \"$dbPointer\" : { \"$ref\" : \"");
2805       bson_string_append (state->str, escaped);
2806       bson_string_append (state->str, "\"");
2807 
2808       if (v_oid) {
2809          bson_oid_to_string (v_oid, str);
2810          bson_string_append (state->str, ", \"$id\" : { \"$oid\" : \"");
2811          bson_string_append (state->str, str);
2812          bson_string_append (state->str, "\" }");
2813       }
2814 
2815       bson_string_append (state->str, " } }");
2816    } else {
2817       bson_string_append (state->str, "{ \"$ref\" : \"");
2818       bson_string_append (state->str, escaped);
2819       bson_string_append (state->str, "\"");
2820 
2821       if (v_oid) {
2822          bson_oid_to_string (v_oid, str);
2823          bson_string_append (state->str, ", \"$id\" : \"");
2824          bson_string_append (state->str, str);
2825          bson_string_append (state->str, "\"");
2826       }
2827 
2828       bson_string_append (state->str, " }");
2829    }
2830 
2831    bson_free (escaped);
2832 
2833    return false;
2834 }
2835 
2836 
2837 static bool
_bson_as_json_visit_minkey(const bson_iter_t * iter,const char * key,void * data)2838 _bson_as_json_visit_minkey (const bson_iter_t *iter,
2839                             const char *key,
2840                             void *data)
2841 {
2842    bson_json_state_t *state = data;
2843 
2844    bson_string_append (state->str, "{ \"$minKey\" : 1 }");
2845 
2846    return false;
2847 }
2848 
2849 
2850 static bool
_bson_as_json_visit_maxkey(const bson_iter_t * iter,const char * key,void * data)2851 _bson_as_json_visit_maxkey (const bson_iter_t *iter,
2852                             const char *key,
2853                             void *data)
2854 {
2855    bson_json_state_t *state = data;
2856 
2857    bson_string_append (state->str, "{ \"$maxKey\" : 1 }");
2858 
2859    return false;
2860 }
2861 
2862 
2863 static bool
_bson_as_json_visit_before(const bson_iter_t * iter,const char * key,void * data)2864 _bson_as_json_visit_before (const bson_iter_t *iter,
2865                             const char *key,
2866                             void *data)
2867 {
2868    bson_json_state_t *state = data;
2869    char *escaped;
2870 
2871    if (state->count) {
2872       bson_string_append (state->str, ", ");
2873    }
2874 
2875    if (state->keys) {
2876       escaped = bson_utf8_escape_for_json (key, -1);
2877       if (escaped) {
2878          bson_string_append (state->str, "\"");
2879          bson_string_append (state->str, escaped);
2880          bson_string_append (state->str, "\" : ");
2881          bson_free (escaped);
2882       } else {
2883          return true;
2884       }
2885    }
2886 
2887    state->count++;
2888 
2889    return false;
2890 }
2891 
2892 
2893 static void
_bson_as_json_visit_corrupt(const bson_iter_t * iter,void * data)2894 _bson_as_json_visit_corrupt (const bson_iter_t *iter, void *data)
2895 {
2896    *(((bson_json_state_t *) data)->err_offset) = iter->off;
2897 }
2898 
2899 
2900 static bool
_bson_as_json_visit_code(const bson_iter_t * iter,const char * key,size_t v_code_len,const char * v_code,void * data)2901 _bson_as_json_visit_code (const bson_iter_t *iter,
2902                           const char *key,
2903                           size_t v_code_len,
2904                           const char *v_code,
2905                           void *data)
2906 {
2907    bson_json_state_t *state = data;
2908    char *escaped;
2909 
2910    escaped = bson_utf8_escape_for_json (v_code, v_code_len);
2911    if (!escaped) {
2912       return true;
2913    }
2914 
2915    bson_string_append (state->str, "{ \"$code\" : \"");
2916    bson_string_append (state->str, escaped);
2917    bson_string_append (state->str, "\" }");
2918    bson_free (escaped);
2919 
2920    return false;
2921 }
2922 
2923 
2924 static bool
_bson_as_json_visit_symbol(const bson_iter_t * iter,const char * key,size_t v_symbol_len,const char * v_symbol,void * data)2925 _bson_as_json_visit_symbol (const bson_iter_t *iter,
2926                                      const char *key,
2927                                      size_t v_symbol_len,
2928                                      const char *v_symbol,
2929                                      void *data)
2930 {
2931    bson_json_state_t *state = data;
2932    char *escaped;
2933 
2934    escaped = bson_utf8_escape_for_json (v_symbol, v_symbol_len);
2935    if (!escaped) {
2936       return true;
2937    }
2938 
2939    if (state->mode == BSON_JSON_MODE_CANONICAL ||
2940        state->mode == BSON_JSON_MODE_RELAXED) {
2941       bson_string_append (state->str, "{ \"$symbol\" : \"");
2942       bson_string_append (state->str, escaped);
2943       bson_string_append (state->str, "\" }");
2944    } else {
2945       bson_string_append (state->str, "\"");
2946       bson_string_append (state->str, escaped);
2947       bson_string_append (state->str, "\"");
2948    }
2949 
2950    bson_free (escaped);
2951 
2952    return false;
2953 }
2954 
2955 
2956 static bool
_bson_as_json_visit_codewscope(const bson_iter_t * iter,const char * key,size_t v_code_len,const char * v_code,const bson_t * v_scope,void * data)2957 _bson_as_json_visit_codewscope (const bson_iter_t *iter,
2958                                 const char *key,
2959                                 size_t v_code_len,
2960                                 const char *v_code,
2961                                 const bson_t *v_scope,
2962                                 void *data)
2963 {
2964    bson_json_state_t *state = data;
2965    char *code_escaped;
2966    char *scope;
2967 
2968    code_escaped = bson_utf8_escape_for_json (v_code, v_code_len);
2969    if (!code_escaped) {
2970       return true;
2971    }
2972 
2973    /* Encode scope with the same mode */
2974    scope = _bson_as_json_visit_all (v_scope, NULL, state->mode);
2975 
2976    if (!scope) {
2977       bson_free (code_escaped);
2978       return true;
2979    }
2980 
2981    bson_string_append (state->str, "{ \"$code\" : \"");
2982    bson_string_append (state->str, code_escaped);
2983    bson_string_append (state->str, "\", \"$scope\" : ");
2984    bson_string_append (state->str, scope);
2985    bson_string_append (state->str, " }");
2986 
2987    bson_free (code_escaped);
2988    bson_free (scope);
2989 
2990    return false;
2991 }
2992 
2993 
2994 static const bson_visitor_t bson_as_json_visitors = {
2995    _bson_as_json_visit_before,
2996    NULL, /* visit_after */
2997    _bson_as_json_visit_corrupt,
2998    _bson_as_json_visit_double,
2999    _bson_as_json_visit_utf8,
3000    _bson_as_json_visit_document,
3001    _bson_as_json_visit_array,
3002    _bson_as_json_visit_binary,
3003    _bson_as_json_visit_undefined,
3004    _bson_as_json_visit_oid,
3005    _bson_as_json_visit_bool,
3006    _bson_as_json_visit_date_time,
3007    _bson_as_json_visit_null,
3008    _bson_as_json_visit_regex,
3009    _bson_as_json_visit_dbpointer,
3010    _bson_as_json_visit_code,
3011    _bson_as_json_visit_symbol,
3012    _bson_as_json_visit_codewscope,
3013    _bson_as_json_visit_int32,
3014    _bson_as_json_visit_timestamp,
3015    _bson_as_json_visit_int64,
3016    _bson_as_json_visit_maxkey,
3017    _bson_as_json_visit_minkey,
3018    NULL, /* visit_unsupported_type */
3019    _bson_as_json_visit_decimal128,
3020 };
3021 
3022 
3023 static bool
_bson_as_json_visit_document(const bson_iter_t * iter,const char * key,const bson_t * v_document,void * data)3024 _bson_as_json_visit_document (const bson_iter_t *iter,
3025                               const char *key,
3026                               const bson_t *v_document,
3027                               void *data)
3028 {
3029    bson_json_state_t *state = data;
3030    bson_json_state_t child_state = {0, true, state->err_offset};
3031    bson_iter_t child;
3032 
3033    if (state->depth >= BSON_MAX_RECURSION) {
3034       bson_string_append (state->str, "{ ... }");
3035       return false;
3036    }
3037 
3038    if (bson_iter_init (&child, v_document)) {
3039       child_state.str = bson_string_new ("{ ");
3040       child_state.depth = state->depth + 1;
3041       child_state.mode = state->mode;
3042       if (bson_iter_visit_all (&child, &bson_as_json_visitors, &child_state)) {
3043          return true;
3044       }
3045 
3046       bson_string_append (child_state.str, " }");
3047       bson_string_append (state->str, child_state.str->str);
3048       bson_string_free (child_state.str, true);
3049    }
3050 
3051    return false;
3052 }
3053 
3054 
3055 static bool
_bson_as_json_visit_array(const bson_iter_t * iter,const char * key,const bson_t * v_array,void * data)3056 _bson_as_json_visit_array (const bson_iter_t *iter,
3057                            const char *key,
3058                            const bson_t *v_array,
3059                            void *data)
3060 {
3061    bson_json_state_t *state = data;
3062    bson_json_state_t child_state = {0, false, state->err_offset};
3063    bson_iter_t child;
3064 
3065    if (state->depth >= BSON_MAX_RECURSION) {
3066       bson_string_append (state->str, "{ ... }");
3067       return false;
3068    }
3069 
3070    if (bson_iter_init (&child, v_array)) {
3071       child_state.str = bson_string_new ("[ ");
3072       child_state.depth = state->depth + 1;
3073       child_state.mode = state->mode;
3074       if (bson_iter_visit_all (&child, &bson_as_json_visitors, &child_state)) {
3075          return true;
3076       }
3077 
3078       bson_string_append (child_state.str, " ]");
3079       bson_string_append (state->str, child_state.str->str);
3080       bson_string_free (child_state.str, true);
3081    }
3082 
3083    return false;
3084 }
3085 
3086 
3087 static char *
_bson_as_json_visit_all(const bson_t * bson,size_t * length,bson_json_mode_t mode)3088 _bson_as_json_visit_all (const bson_t *bson,
3089                          size_t *length,
3090                          bson_json_mode_t mode)
3091 {
3092    bson_json_state_t state;
3093    bson_iter_t iter;
3094    ssize_t err_offset = -1;
3095 
3096    BSON_ASSERT (bson);
3097 
3098    if (length) {
3099       *length = 0;
3100    }
3101 
3102    if (bson_empty0 (bson)) {
3103       if (length) {
3104          *length = 3;
3105       }
3106 
3107       return bson_strdup ("{ }");
3108    }
3109 
3110    if (!bson_iter_init (&iter, bson)) {
3111       return NULL;
3112    }
3113 
3114    state.count = 0;
3115    state.keys = true;
3116    state.str = bson_string_new ("{ ");
3117    state.depth = 0;
3118    state.err_offset = &err_offset;
3119    state.mode = mode;
3120 
3121    if (bson_iter_visit_all (&iter, &bson_as_json_visitors, &state) ||
3122        err_offset != -1) {
3123       /*
3124        * We were prematurely exited due to corruption or failed visitor.
3125        */
3126       bson_string_free (state.str, true);
3127       if (length) {
3128          *length = 0;
3129       }
3130       return NULL;
3131    }
3132 
3133    bson_string_append (state.str, " }");
3134 
3135    if (length) {
3136       *length = state.str->len;
3137    }
3138 
3139    return bson_string_free (state.str, false);
3140 }
3141 
3142 
3143 char *
bson_as_canonical_extended_json(const bson_t * bson,size_t * length)3144 bson_as_canonical_extended_json (const bson_t *bson, size_t *length)
3145 {
3146    return _bson_as_json_visit_all (bson, length, BSON_JSON_MODE_CANONICAL);
3147 }
3148 
3149 
3150 char *
bson_as_json(const bson_t * bson,size_t * length)3151 bson_as_json (const bson_t *bson, size_t *length)
3152 {
3153    return _bson_as_json_visit_all (bson, length, BSON_JSON_MODE_LEGACY);
3154 }
3155 
3156 
3157 char *
bson_as_relaxed_extended_json(const bson_t * bson,size_t * length)3158 bson_as_relaxed_extended_json (const bson_t *bson, size_t *length)
3159 {
3160    return _bson_as_json_visit_all (bson, length, BSON_JSON_MODE_RELAXED);
3161 }
3162 
3163 
3164 char *
bson_array_as_json(const bson_t * bson,size_t * length)3165 bson_array_as_json (const bson_t *bson, size_t *length)
3166 {
3167    bson_json_state_t state;
3168    bson_iter_t iter;
3169    ssize_t err_offset = -1;
3170 
3171    BSON_ASSERT (bson);
3172 
3173    if (length) {
3174       *length = 0;
3175    }
3176 
3177    if (bson_empty0 (bson)) {
3178       if (length) {
3179          *length = 3;
3180       }
3181 
3182       return bson_strdup ("[ ]");
3183    }
3184 
3185    if (!bson_iter_init (&iter, bson)) {
3186       return NULL;
3187    }
3188 
3189    state.count = 0;
3190    state.keys = false;
3191    state.str = bson_string_new ("[ ");
3192    state.depth = 0;
3193    state.err_offset = &err_offset;
3194    state.mode = BSON_JSON_MODE_LEGACY;
3195    bson_iter_visit_all (&iter, &bson_as_json_visitors, &state);
3196 
3197    if (bson_iter_visit_all (&iter, &bson_as_json_visitors, &state) ||
3198        err_offset != -1) {
3199       /*
3200        * We were prematurely exited due to corruption or failed visitor.
3201        */
3202       bson_string_free (state.str, true);
3203       if (length) {
3204          *length = 0;
3205       }
3206       return NULL;
3207    }
3208 
3209    bson_string_append (state.str, " ]");
3210 
3211    if (length) {
3212       *length = state.str->len;
3213    }
3214 
3215    return bson_string_free (state.str, false);
3216 }
3217 
3218 
3219 #define VALIDATION_ERR(_flag, _msg, ...) \
3220    bson_set_error (&state->error, BSON_ERROR_INVALID, _flag, _msg, __VA_ARGS__)
3221 
3222 static bool
_bson_iter_validate_utf8(const bson_iter_t * iter,const char * key,size_t v_utf8_len,const char * v_utf8,void * data)3223 _bson_iter_validate_utf8 (const bson_iter_t *iter,
3224                           const char *key,
3225                           size_t v_utf8_len,
3226                           const char *v_utf8,
3227                           void *data)
3228 {
3229    bson_validate_state_t *state = data;
3230    bool allow_null;
3231 
3232    if ((state->flags & BSON_VALIDATE_UTF8)) {
3233       allow_null = !!(state->flags & BSON_VALIDATE_UTF8_ALLOW_NULL);
3234 
3235       if (!bson_utf8_validate (v_utf8, v_utf8_len, allow_null)) {
3236          state->err_offset = iter->off;
3237          VALIDATION_ERR (
3238             BSON_VALIDATE_UTF8, "invalid utf8 string for key \"%s\"", key);
3239          return true;
3240       }
3241    }
3242 
3243    if ((state->flags & BSON_VALIDATE_DOLLAR_KEYS)) {
3244       if (state->phase == BSON_VALIDATE_PHASE_LF_REF_UTF8) {
3245          state->phase = BSON_VALIDATE_PHASE_LF_ID_KEY;
3246       } else if (state->phase == BSON_VALIDATE_PHASE_LF_DB_UTF8) {
3247          state->phase = BSON_VALIDATE_PHASE_NOT_DBREF;
3248       }
3249    }
3250 
3251    return false;
3252 }
3253 
3254 
3255 static void
_bson_iter_validate_corrupt(const bson_iter_t * iter,void * data)3256 _bson_iter_validate_corrupt (const bson_iter_t *iter, void *data)
3257 {
3258    bson_validate_state_t *state = data;
3259 
3260    state->err_offset = iter->err_off;
3261    VALIDATION_ERR (BSON_VALIDATE_NONE, "%s", "corrupt BSON");
3262 }
3263 
3264 
3265 static bool
_bson_iter_validate_before(const bson_iter_t * iter,const char * key,void * data)3266 _bson_iter_validate_before (const bson_iter_t *iter,
3267                             const char *key,
3268                             void *data)
3269 {
3270    bson_validate_state_t *state = data;
3271 
3272    if ((state->flags & BSON_VALIDATE_EMPTY_KEYS)) {
3273       if (key[0] == '\0') {
3274          state->err_offset = iter->off;
3275          VALIDATION_ERR (BSON_VALIDATE_EMPTY_KEYS, "%s", "empty key");
3276          return true;
3277       }
3278    }
3279 
3280    if ((state->flags & BSON_VALIDATE_DOLLAR_KEYS)) {
3281       if (key[0] == '$') {
3282          if (state->phase == BSON_VALIDATE_PHASE_LF_REF_KEY &&
3283              strcmp (key, "$ref") == 0) {
3284             state->phase = BSON_VALIDATE_PHASE_LF_REF_UTF8;
3285          } else if (state->phase == BSON_VALIDATE_PHASE_LF_ID_KEY &&
3286                     strcmp (key, "$id") == 0) {
3287             state->phase = BSON_VALIDATE_PHASE_LF_DB_KEY;
3288          } else if (state->phase == BSON_VALIDATE_PHASE_LF_DB_KEY &&
3289                     strcmp (key, "$db") == 0) {
3290             state->phase = BSON_VALIDATE_PHASE_LF_DB_UTF8;
3291          } else {
3292             state->err_offset = iter->off;
3293             VALIDATION_ERR (BSON_VALIDATE_DOLLAR_KEYS,
3294                             "keys cannot begin with \"$\": \"%s\"",
3295                             key);
3296             return true;
3297          }
3298       } else if (state->phase == BSON_VALIDATE_PHASE_LF_ID_KEY ||
3299                  state->phase == BSON_VALIDATE_PHASE_LF_REF_UTF8 ||
3300                  state->phase == BSON_VALIDATE_PHASE_LF_DB_UTF8) {
3301          state->err_offset = iter->off;
3302          VALIDATION_ERR (BSON_VALIDATE_DOLLAR_KEYS,
3303                          "invalid key within DBRef subdocument: \"%s\"",
3304                          key);
3305          return true;
3306       } else {
3307          state->phase = BSON_VALIDATE_PHASE_NOT_DBREF;
3308       }
3309    }
3310 
3311    if ((state->flags & BSON_VALIDATE_DOT_KEYS)) {
3312       if (strstr (key, ".")) {
3313          state->err_offset = iter->off;
3314          VALIDATION_ERR (
3315             BSON_VALIDATE_DOT_KEYS, "keys cannot contain \".\": \"%s\"", key);
3316          return true;
3317       }
3318    }
3319 
3320    return false;
3321 }
3322 
3323 
3324 static bool
_bson_iter_validate_codewscope(const bson_iter_t * iter,const char * key,size_t v_code_len,const char * v_code,const bson_t * v_scope,void * data)3325 _bson_iter_validate_codewscope (const bson_iter_t *iter,
3326                                 const char *key,
3327                                 size_t v_code_len,
3328                                 const char *v_code,
3329                                 const bson_t *v_scope,
3330                                 void *data)
3331 {
3332    bson_validate_state_t *state = data;
3333    size_t offset = 0;
3334 
3335    if (!bson_validate (v_scope, state->flags, &offset)) {
3336       state->err_offset = iter->off + offset;
3337       VALIDATION_ERR (BSON_VALIDATE_NONE, "%s", "corrupt code-with-scope");
3338       return false;
3339    }
3340 
3341    return true;
3342 }
3343 
3344 
3345 static bool
3346 _bson_iter_validate_document (const bson_iter_t *iter,
3347                               const char *key,
3348                               const bson_t *v_document,
3349                               void *data);
3350 
3351 
3352 static const bson_visitor_t bson_validate_funcs = {
3353    _bson_iter_validate_before,
3354    NULL, /* visit_after */
3355    _bson_iter_validate_corrupt,
3356    NULL, /* visit_double */
3357    _bson_iter_validate_utf8,
3358    _bson_iter_validate_document,
3359    _bson_iter_validate_document, /* visit_array */
3360    NULL,                         /* visit_binary */
3361    NULL,                         /* visit_undefined */
3362    NULL,                         /* visit_oid */
3363    NULL,                         /* visit_bool */
3364    NULL,                         /* visit_date_time */
3365    NULL,                         /* visit_null */
3366    NULL,                         /* visit_regex */
3367    NULL,                         /* visit_dbpoint */
3368    NULL,                         /* visit_code */
3369    NULL,                         /* visit_symbol */
3370    _bson_iter_validate_codewscope,
3371 };
3372 
3373 
3374 static bool
_bson_iter_validate_document(const bson_iter_t * iter,const char * key,const bson_t * v_document,void * data)3375 _bson_iter_validate_document (const bson_iter_t *iter,
3376                               const char *key,
3377                               const bson_t *v_document,
3378                               void *data)
3379 {
3380    bson_validate_state_t *state = data;
3381    bson_iter_t child;
3382    bson_validate_phase_t phase = state->phase;
3383 
3384    if (!bson_iter_init (&child, v_document)) {
3385       state->err_offset = iter->off;
3386       return true;
3387    }
3388 
3389    if (state->phase == BSON_VALIDATE_PHASE_START) {
3390       state->phase = BSON_VALIDATE_PHASE_TOP;
3391    } else {
3392       state->phase = BSON_VALIDATE_PHASE_LF_REF_KEY;
3393    }
3394 
3395    bson_iter_visit_all (&child, &bson_validate_funcs, state);
3396 
3397    if (state->phase == BSON_VALIDATE_PHASE_LF_ID_KEY ||
3398        state->phase == BSON_VALIDATE_PHASE_LF_REF_UTF8 ||
3399        state->phase == BSON_VALIDATE_PHASE_LF_DB_UTF8) {
3400       if (state->err_offset <= 0) {
3401          state->err_offset = iter->off;
3402       }
3403 
3404       return true;
3405    }
3406 
3407    state->phase = phase;
3408 
3409    return false;
3410 }
3411 
3412 
3413 static void
_bson_validate_internal(const bson_t * bson,bson_validate_state_t * state)3414 _bson_validate_internal (const bson_t *bson, bson_validate_state_t *state)
3415 {
3416    bson_iter_t iter;
3417 
3418    state->err_offset = -1;
3419    state->phase = BSON_VALIDATE_PHASE_START;
3420    memset (&state->error, 0, sizeof state->error);
3421 
3422    if (!bson_iter_init (&iter, bson)) {
3423       state->err_offset = 0;
3424       VALIDATION_ERR (BSON_VALIDATE_NONE, "%s", "corrupt BSON");
3425    } else {
3426       _bson_iter_validate_document (&iter, NULL, bson, state);
3427    }
3428 }
3429 
3430 
3431 bool
bson_validate(const bson_t * bson,bson_validate_flags_t flags,size_t * offset)3432 bson_validate (const bson_t *bson, bson_validate_flags_t flags, size_t *offset)
3433 {
3434    bson_validate_state_t state;
3435 
3436    state.flags = flags;
3437    _bson_validate_internal (bson, &state);
3438 
3439    if (state.err_offset > 0 && offset) {
3440       *offset = (size_t) state.err_offset;
3441    }
3442 
3443    return state.err_offset < 0;
3444 }
3445 
3446 
3447 bool
bson_validate_with_error(const bson_t * bson,bson_validate_flags_t flags,bson_error_t * error)3448 bson_validate_with_error (const bson_t *bson,
3449                           bson_validate_flags_t flags,
3450                           bson_error_t *error)
3451 {
3452    bson_validate_state_t state;
3453 
3454    state.flags = flags;
3455    _bson_validate_internal (bson, &state);
3456 
3457    if (state.err_offset > 0 && error) {
3458       memcpy (error, &state.error, sizeof *error);
3459    }
3460 
3461    return state.err_offset < 0;
3462 }
3463 
3464 
3465 bool
bson_concat(bson_t * dst,const bson_t * src)3466 bson_concat (bson_t *dst, const bson_t *src)
3467 {
3468    BSON_ASSERT (dst);
3469    BSON_ASSERT (src);
3470 
3471    if (!bson_empty (src)) {
3472       return _bson_append (
3473          dst, 1, src->len - 5, src->len - 5, _bson_data (src) + 4);
3474    }
3475 
3476    return true;
3477 }
3478