Summary
The avg, variance, and stddev functions in the Statistics contract lack validation for non-empty input arrays, which can result in a division by zero error.
function avg(uint256[] memory data) internal pure returns (uint256 ans) {
uint256 sum = 0;
for (uint256 i = 0; i < data.length; i++) {
sum += data[i];
}
ans = sum / data.length;
}
function variance(uint256[] memory data) internal pure returns (uint256 ans, uint256 mean) {
mean = avg(data);
uint256 sum = 0;
for (uint256 i = 0; i < data.length; i++) {
uint256 diff = data[i] - mean;
sum += diff * diff;
}
ans = sum / data.length;
}
function stddev(uint256[] memory data) internal pure returns (uint256 ans, uint256 mean) {
(uint256 _variance, uint256 _mean) = variance(data);
mean = _mean;
ans = sqrt(_variance);
}
Vulnerability Details
The avg, variance, and stddev functions in the Statistics contract perform division operations based on the length of an input array, data.length, without validating that the array is non-empty. This missing input validation can cause a division by zero error, resulting in contract reversion.
Impact
If the array passed to the aforementioned functions is empty, division by zero will revert the transaction, causing disruptions for any users or contracts relying on these functions. Repeated errors of this type could lead to unexpected failures across dependent systems.
Tools Used
Manual Review
Recommendations
Add an input validation check to ensure the array is not empty before performing the division. This can be done by adding a requirement statement to the start of each function, as shown below:
function avg(uint256[] memory data) internal pure returns (uint256 ans) {
require(data.length > 0, "Data array is empty");
uint256 sum = 0;
for (uint256 i = 0; i < data.length; i++) {
sum += data[i];
}
ans = sum / data.length;
}
function variance(uint256[] memory data) internal pure returns (uint256 ans, uint256 mean) {
require(data.length > 0, "Data array is empty");
mean = avg(data);
uint256 sum = 0;
for (uint256 i = 0; i < data.length; i++) {
uint256 diff = data[i] - mean;
sum += diff * diff;
}
ans = sum / data.length;
}
function stddev(uint256[] memory data) internal pure returns (uint256 ans, uint256 mean) {
require(data.length > 0, "Data array is empty");
(uint256 _variance, uint256 _mean) = variance(data);
mean = _mean;
ans = sqrt(_variance);
}