Add inline variant of BSON array builder

XMLWordPrintableJSON

    • Type: Task
    • Resolution: Won't Do
    • Priority: Unknown
    • None
    • Affects Version/s: None
    • Component/s: None
    • None
    • Not Needed
    • None
    • C Drivers
    • Hide

      1. What would you like to communicate to the user about this feature?
      2. Would you like the user to see examples of the syntax and/or executable code and its output?
      3. Which versions of the driver/connector does this apply to?

      Show
      1. What would you like to communicate to the user about this feature? 2. Would you like the user to see examples of the syntax and/or executable code and its output? 3. Which versions of the driver/connector does this apply to?
    • None
    • None
    • None
    • None
    • None
    • None

      Proposal

      Add an inline variant of bson_append_array_builder_t

      Details

      CDRIVER-6180 proposes deprecating bson_append_array_begin for the safer alternative of bson_append_array_builder_t. However, bson_append_array_buider_t has slightly different API expectations.

      bson_append_array_begin does not require a call to bson_append_array_end to free memory:

      bool append_array (bson_t *out) {
          bson_t array;
          if (!BSON_APPEND_ARRAY_BEGIN(out, "foo", &array)) {
              return false;
          }
          if (!something()) {
              // OK. No leak.
              return false;
          }
          return bson_append_array_end(&doc);
      }
      

      Naively migrating this to bson_array_builder_t may result in a leak:

      bool
      append_array_builder(bson_t *out)
      {
         bson_array_builder_t *array_builder;
         if (!BSON_APPEND_ARRAY_BUILDER_BEGIN(out, "foo", &array_builder)) {
            return false;
         }
         if (!something()) {
            // Leaks `*array_builder`! Missing call to `bson_append_array_builder_end` or `bson_array_builder_destroy`.
            return false;
         }
         return bson_append_array_builder_end(out, array_builder);
      }
      

      This ticket proposes an inline API to ease migration (and avoid an extra allocation):

      bool
      append_inline_array_builder(bson_t *out)
      {
         bson_array_builder_t inline_array_builder = BSON_ARRAY_BUILDER_INITIALIZER;
         if (!BSON_APPEND_ARRAY_BUILDER_INLINE_BEGIN(out, "foo", &inline_array_builder)) {
            return false;
         }
         if (!something()) {
            // OK. No leak.
            return false;
         }
         return bson_append_array_builder_end(out, &inline_array_builder);
      }
      

      Further motivation:

      GitHub code search shows examples that do not call bson_append_array_end on some failures:

      https://github.com/collectd/collectd/blob/2cd055fe855a3168bbe38e7ca83bd805fb9acb3e/src/write_mongodb.c#L114

      BSON_APPEND_ARRAY_BEGIN(ret, "values", &subarray);
      // ...
      else {
          ERROR("write_mongodb plugin: Unknown ds_type %d for index %" PRIsz,
              ds->ds[i].type, i);
          bson_destroy(ret);
          return NULL;
      }
      // ...
      bson_append_array_end(ret, &subarray);
      

      https://github.com/OpenSIPS/opensips/blob/2a1c511265d82648c984807c02c4b50ed073ca42/modules/cachedb_mongodb/cachedb_mongodb_json.c#L123

      BSON_APPEND_ARRAY_BEGIN(doc, k, &child);
      if (json_to_bson_append_array(&child, v) < 0) {
          LM_ERR("Failed to append array to bson_t\n");
          return -1;
      }
      bson_append_array_end(doc, &child);
      

      If these examples were migrated to bson_array_builder_t and a call to bson_append_array_builder_end or bson_array_builder_destroy was not added on early returns, that could risk leaks.

            Assignee:
            Kevin Albertson
            Reporter:
            Kevin Albertson
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: