aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeth Moore <sethmo@google.com>2021-06-30 18:38:23 -0700
committerSeth Moore <sethmo@google.com>2021-06-30 18:38:23 -0700
commitb0c9795e040ef73f9d2cf5b44a104dd99d531644 (patch)
tree225b39f6a07685ac03481890a6b618ee99b514d9
parent7d548df91959ac4dc30c8c1c8dc3db12894e7229 (diff)
downloadlibcppbor-b0c9795e040ef73f9d2cf5b44a104dd99d531644.tar.gz
The variadic Array constructor would implicitly make an Array object from a single input that is convertable to an Item. This leads to surprising behaviors wherein Arrays could be created unintentionally. Fix this by making the variadic constructor only work for more than one argument. Add an additional, single-item constructor that is explicit. Bug: 191778240 Test: cppbor_host_test_external Change-Id: Ifadc6d3137ee285a81076a4125b6053f1d7c21c4
-rw-r--r--include/cppbor/cppbor.h20
1 files changed, 17 insertions, 3 deletions
diff --git a/include/cppbor/cppbor.h b/include/cppbor/cppbor.h
index b78c41f..9bad233 100644
--- a/include/cppbor/cppbor.h
+++ b/include/cppbor/cppbor.h
@@ -598,6 +598,13 @@ class Array : public Item {
Array(Args&&... args);
/**
+ * The above variadic constructor is disabled if sizeof(Args) != 1, so special
+ * case an explicit Array constructor for creating an Array with one Item.
+ */
+ template <typename T, typename Enable>
+ explicit Array(T&& v);
+
+ /**
* Append a single element to the Array, of any compatible type.
*/
template <typename T>
@@ -1039,14 +1046,21 @@ inline void map_helper(Map& map, Key&& key, Value&& value, Rest&&... rest) {
} // namespace details
template <typename... Args,
- /* Prevent use as copy ctor */ typename = std::enable_if_t<
- (sizeof...(Args)) != 1 ||
- !(std::is_same_v<Array, std::remove_cv_t<std::remove_reference_t<Args>>> || ...)>>
+ /* Prevent implicit construction with a single argument. */
+ typename = std::enable_if_t<(sizeof...(Args)) != 1>>
Array::Array(Args&&... args) {
mEntries.reserve(sizeof...(args));
(mEntries.push_back(details::makeItem(std::forward<Args>(args))), ...);
}
+template <typename T,
+ /* Prevent use as copy constructor. */
+ typename = std::enable_if_t<
+ !std::is_same_v<Array, std::remove_cv_t<std::remove_reference_t<T>>>>>
+Array::Array(T&& v) {
+ mEntries.push_back(details::makeItem(std::forward<T>(v)));
+}
+
template <typename T>
Array& Array::add(T&& v) & {
mEntries.push_back(details::makeItem(std::forward<T>(v)));