Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]🐛 Size computation for allocation may overflow #4525

Closed
odaysec opened this issue Feb 27, 2025 · 1 comment
Closed

[Bug]🐛 Size computation for allocation may overflow #4525

odaysec opened this issue Feb 27, 2025 · 1 comment

Comments

@odaysec
Copy link

odaysec commented Feb 27, 2025

buf := make([]byte, len(b.buf), 2*cap(b.buf)+n)

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, for 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 vulnerable, 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. 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)
}

Recommendation

Always guard against overflow in arithmetic operations involving potentially large numbers by doing one of the following:

  • Validate the size of the data from which the numbers are computed.
  • Define a guard on the arithmetic expression, so that the operation is performed only if the result can be known to be less than, or equal to, the maximum value for the type.
  • Use a wider type (such as uint64 instead of int), so that larger input values do not cause overflow.

References

Integer overflow.
Making slices, maps and channels.
CWE-190.

For confirmed bugs, please report:

@odaysec
Copy link
Author

odaysec commented Feb 27, 2025

The patch: #4527

@cmacknz cmacknz closed this as not planned Won't fix, can't repro, duplicate, stale Mar 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants