Added numeric value guards to ValueMetric.

[ Merge of http://go/wvgerrit/137951 ]

ValueMetric was not checking whether certain unsigned types will
overflow when casted to protobuf's signed int64 type.  This CL
adds a max value to prevent potential overflows.

The value metric has also been updated to an emum to represent its
possible three state, as opposed to using two boolean flags.  For basic
value metrics, this saves about 4 bytes of space.  This works out to
being ~100 bytes per crypto session, ~20 bytes per CDM session and ~20
bytes per engine metrics.

Bug: 204946540
Test: Metric unit tests
Change-Id: I688bece8f31cccaf2a25bd8f99d9b080b0efd0de
This commit is contained in:
Alex Dale
2021-11-04 19:19:24 -07:00
parent f5759c5149
commit 08c703a7b8
3 changed files with 106 additions and 63 deletions

View File

@@ -6,89 +6,111 @@
// ValueMetric class.
#include "value_metric.h"
#include <limits>
#include "OEMCryptoCENC.h"
#include "metrics_collections.h"
#include "wv_cdm_types.h"
namespace wvcdm {
namespace metrics {
namespace impl {
namespace internal {
namespace {
// Max value of protobuf's int64 type.
constexpr uint64_t kMaxValueCmp =
static_cast<uint64_t>(std::numeric_limits<int64_t>::max());
constexpr int64_t kMaxValue = std::numeric_limits<int64_t>::max();
template <typename T>
constexpr bool WillOverflow(T value) {
return static_cast<uint64_t>(value) > kMaxValueCmp;
}
// Prevents an overflow of very large numbers. If the value attempted to
// be assigned is greater than the maximum value supported by protobuf's
// int64 type, then the value is capped at the max.
template <typename T>
constexpr int64_t SafeAssign(T value) {
return WillOverflow(value) ? kMaxValue : static_cast<int64_t>(value);
}
} // namespace
template <>
void SetValue<int>(drm_metrics::ValueMetric* value_proto, const int& value) {
value_proto->set_int_value(value);
value_proto->set_int_value(static_cast<int64_t>(value));
}
template <>
void SetValue<long>(drm_metrics::ValueMetric* value_proto, const long& value) {
value_proto->set_int_value(value);
value_proto->set_int_value(static_cast<int64_t>(value));
}
template <>
void SetValue<long long>(drm_metrics::ValueMetric* value_proto,
const long long& value) {
value_proto->set_int_value(value);
value_proto->set_int_value(SafeAssign(value));
}
template <>
void SetValue<unsigned int>(drm_metrics::ValueMetric* value_proto,
const unsigned int& value) {
value_proto->set_int_value((int64_t)value);
value_proto->set_int_value(SafeAssign(value));
}
template <>
void SetValue<unsigned short>(drm_metrics::ValueMetric* value_proto,
const unsigned short& value) {
value_proto->set_int_value((int64_t)value);
value_proto->set_int_value(SafeAssign(value));
}
template <>
void SetValue<unsigned long>(drm_metrics::ValueMetric* value_proto,
const unsigned long& value) {
value_proto->set_int_value((int64_t)value);
value_proto->set_int_value(SafeAssign(value));
}
template <>
void SetValue<unsigned long long>(drm_metrics::ValueMetric* value_proto,
const unsigned long long& value) {
value_proto->set_int_value((int64_t)value);
value_proto->set_int_value(SafeAssign(value));
}
template <>
void SetValue<bool>(drm_metrics::ValueMetric* value_proto, const bool& value) {
value_proto->set_int_value(value);
value_proto->set_int_value(value ? 1 : 0);
}
template <>
void SetValue<OEMCrypto_HDCP_Capability>(
drm_metrics::ValueMetric* value_proto,
const OEMCrypto_HDCP_Capability& value) {
value_proto->set_int_value(value);
value_proto->set_int_value(static_cast<int64_t>(value));
}
template <>
void SetValue<OEMCrypto_ProvisioningMethod>(
drm_metrics::ValueMetric* value_proto,
const OEMCrypto_ProvisioningMethod& value) {
value_proto->set_int_value(value);
value_proto->set_int_value(static_cast<int64_t>(value));
}
template <>
void SetValue<OEMCryptoInitializationMode>(
drm_metrics::ValueMetric* value_proto,
const OEMCryptoInitializationMode& value) {
value_proto->set_int_value(value);
value_proto->set_int_value(static_cast<int64_t>(value));
}
template <>
void SetValue<CdmSecurityLevel>(drm_metrics::ValueMetric* value_proto,
const CdmSecurityLevel& value) {
value_proto->set_int_value(value);
value_proto->set_int_value(static_cast<int64_t>(value));
}
template <>
void SetValue<CdmUsageSupportType>(drm_metrics::ValueMetric* value_proto,
const CdmUsageSupportType& value) {
value_proto->set_int_value(value);
value_proto->set_int_value(static_cast<int64_t>(value));
}
template <>
@@ -102,6 +124,6 @@ void SetValue<std::string>(drm_metrics::ValueMetric* value_proto,
const std::string& value) {
value_proto->set_string_value(value);
}
} // namespace impl
} // namespace internal
} // namespace metrics
} // namespace wvcdm