[CXX-2143] Throwing in bsoncxx::document::element::get_*() if the element is invalid. Created: 10/Dec/20  Updated: 28/Oct/23  Resolved: 15/Mar/21

Status: Closed
Project: C++ Driver
Component/s: API
Affects Version/s: None
Fix Version/s: 3.6.6

Type: Bug Priority: Major - P3
Reporter: Adrian B Assignee: Samantha Ritter (Inactive)
Resolution: Fixed Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Hello,

Could bsoncxx::document::element::get_() functions - like get_oid(), get_double(), etc. -  throw a *bsoncxx::exception{error_code::k_unset_element} when the element is invalid ?
Currently, a BSON_ASSERT() abort the program in that case.

This would allow to do something like that :

try {
 
  myOID          = documentView["_id"].get_oid().value;
  myIntegerValue = documentView["count"].get_int32().value;
 
} catch (const std::exception& e) {
 
  if (e.code() == bsoncxx::error_code::k_unset_element) {
 
    throwIfFieldElementUnset(documentView, "_id");
    throwIfFieldElementUnset(documentView, "count");
 
  } else {
    
    throw;
  }
}

 

Also, it would be safer for case where the programmer wrongly use these methods on an invalid element : instead of aborting. exceptions would probably already be handled.

 



 Comments   
Comment by Githook User [ 05/Oct/21 ]

Author:

{'name': 'samantharitter', 'email': 'samantha.ritter@10gen.com', 'username': 'samantharitter'}

Message: CXX-2143 throw an exception when getting types from an unset element
Branch: releases/stable
https://github.com/mongodb/mongo-cxx-driver/commit/b4b6371cec8267b91df94d4501899b0a53f1b75d

Comment by Kevin Albertson [ 04/Aug/21 ]

Note, this ticket originally listed 3.6.3 as the fix version. The commit 33416f88f1d59e19eb103fedab59d73399332a7c was not cherry-picked onto the releases/v3.6 branch. This is now cherry-picked on releases/v3.6 with the following commit: https://github.com/mongodb/mongo-cxx-driver/commit/b4b6371cec8267b91df94d4501899b0a53f1b75d and will be included in the 3.6.6 release.

Comment by Samantha Ritter (Inactive) [ 15/Mar/21 ]

Hi adrian.blandin@sovo-tech.com,

The fix for this issue has now been merged into the codebase. I'm closing this ticket. Thank you for bringing it to our attention!

Best,
Samantha

Comment by Githook User [ 15/Mar/21 ]

Author:

{'name': 'samantharitter', 'email': 'samantha.ritter@10gen.com', 'username': 'samantharitter'}

Message: CXX-2143 throw an exception when getting types from an unset element
Branch: master
https://github.com/mongodb/mongo-cxx-driver/commit/33416f88f1d59e19eb103fedab59d73399332a7c

Comment by Adrian B [ 04/Mar/21 ]

Hi, 
Thanks for the fix .

Comment by Samantha Ritter (Inactive) [ 04/Mar/21 ]

Hi adrian.blandin@sovo-tech.com,

Thanks for bringing this to our attention! A fix is now in code review: https://github.com/mongodb/mongo-cxx-driver/pull/771

All the best,
Samantha Ritter

Comment by Kevin Chen [ 16/Jan/21 ]

I think bsoncxx would throw this exception until recently. There was a macro BSONCXX_TYPE_CHECK that would fail if the element is unset, since it calls element::type(), which throws an exception https://github.com/mongodb/mongo-cxx-driver/blob/9bdb4829ed05612b5fa6386f323a8650b4f342eb/src/bsoncxx/document/element.cpp#L109-L110

However, the behavior was subtly changed in the refactor 600142f13f5de060ca5b974dd8b662d7cd549f27 which moved the error checking to bsoncxx::value. I believe this is because value's constructor calls libbson (e.g. bson_iter_double) directly, while the error checking was placed in the getter after construction (e.g. get_double).

Comment by Kevin Albertson [ 10/Dec/20 ]

Hi Adrian! Thank you for the feature request. I was able to reproduce this behavior with this example:

#include <mongocxx/client.hpp>
#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/builder/basic/kvp.hpp>
#include <bsoncxx/types.hpp>
#include <bsoncxx/exception/error_code.hpp>
#include <bsoncxx/exception/exception.hpp>
#include <bsoncxx/json.hpp>
#include <iostream>
 
// Try to read an int32 from "view".
void run_test (bsoncxx::document::view view, std::string key) {
    try {
        std::cout << "Reading " << key << " from document" << bsoncxx::to_json (view) << std::endl;
        int32_t value = view[key].get_int32().value;
    } catch (bsoncxx::exception& e) {
        if (e.code() == bsoncxx::error_code::k_unset_element) {
            std::cout << " k_unset_element exception thrown" << std::endl;
        } else if (e.code() == bsoncxx::error_code::k_need_element_type_k_int32) {
            std::cout << " k_need_element_type_k_int32 exception thrown" << std::endl;
        } else {
            std::cout << " unexpected exception thrown" << std::endl;
        }
    }
}
 
int main () {
    auto doc = bsoncxx::builder::basic::document{};
    using bsoncxx::builder::basic::kvp;
 
    doc.append(kvp("foo", "bar"));
    run_test (doc, "foo");
    run_test (doc, "unknown");
}

This aborts when trying to read the field "unknown":

Reading foo from document{ "foo" : "bar" }
 k_need_element_type_k_int32 exception thrown
Reading unknown from document{ "foo" : "bar" }
/var/folders/pv/p1jss0l97mq0ddr7rjbcbdt00000gp/T/tmp.lD2bx9iV/mongo-c-driver-1.17.0/src/libbson/src/bson/bson-iter.c:2500 bson_iter_init_from_data_at_offset(): precondition failed: data

I agree, an exception would be an improvement, I am opening this ticket.

Generated at Wed Feb 07 22:05:02 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.