aresdb icon indicating copy to clipboard operation
aresdb copied to clipboard

fix Size computation for allocation may overflow

Open odaysec opened this issue 7 months ago • 1 comments

fix the problem need to ensure that the size computation does not overflow. This can be achieved by validating the size of hll.SparseData before performing the arithmetic operation. Specifically, we should check if len(hll.SparseData) is within a safe range that guarantees no overflow will occur when multiplied by recordValueBytes.

Performing calculations involving the size of potentially large strings or slices can result in an overflow (for signed integer types) or a wraparound (for unsigned types). An overflow causes the result of the calculation to become negative, while a wraparound results in a small (positive) number. This can cause further issues. If, the result is then used in an allocation, it will cause a runtime panic if it is negative, and allocate an unexpectedly small buffer otherwise.

POC

In the following example, assume that there is a function encryptBuffer that encrypts byte slices whose length must be padded to be a multiple of 16. The function encryptValue provides a convenience wrapper around this function: when passed an arbitrary value, it first encodes that value as JSON, pads the resulting byte slice, and then passes it to encryptBuffer.

package main

import "encoding/json"

func encryptValue(v interface{}) ([]byte, error) {
	jsonData, err := json.Marshal(v)
	if err != nil {
		return nil, err
	}
	size := len(jsonData) + (len(jsonData) % 16)
	buffer := make([]byte, size)
	copy(buffer, jsonData)
	return encryptBuffer(buffer)
}

When passed a value whose JSON encoding is close to the maximum value of type int in length, the computation of size will overflow, producing a negative value. When that negative value is passed to make, a runtime panic will occur.

To guard against this, the function should be improved to check the length of the JSON-encoded value. For example, here is a version of encryptValue that ensures the value is no larger than 64 MB, which fits comfortably within an int and avoids the overflow:

package main

import (
	"encoding/json"
	"errors"
)

func encryptValueGood(v interface{}) ([]byte, error) {
	jsonData, err := json.Marshal(v)
	if err != nil {
		return nil, err
	}
	if len(jsonData) > 64*1024*1024 {
		return nil, errors.New("value too large")
	}
	size := len(jsonData) + (len(jsonData) % 16)
	buffer := make([]byte, size)
	copy(buffer, jsonData)
	return encryptBuffer(buffer)
}

References

Integer overflow Making slices, maps and channels CWE-190

odaysec avatar Apr 15 '25 23:04 odaysec

CLA assistant check
All committers have signed the CLA.

CLAassistant avatar Apr 15 '25 23:04 CLAassistant