Assessment reports>Brevis>Low findings>Data might be arranged incorrectly by ,rawData[T].list
Category: Coding Mistakes

Data might be arranged incorrectly by rawData[T].list

Low Severity
Low Impact
Low Likelihood

Description

As also discussed in Finding ref, the rawData type in sdk/app.go is used to hold receipt, storage, and transaction data. Raw data can be added by pinning to a specific index (stored in the field special) and added to a list ordered. The list function is then used to convert a rawData to an actual list (slice). The pinned entries from special will be added at the respective index, and the remaining entries will be filled with the entries from ordered. It is implemented as follows:

func (q *rawData[T]) list(max int) []T {
	var empty T
	var l []T
	ordered := q.ordered
	for i := 0; i < max; i++ {
		if q.special[i] != empty {
			l = append(l, q.special[i])
		} else if len(ordered) > 0 {
			l = append(l, ordered[0])
			ordered = ordered[1:]
		}
	}
	return l
}

Detection of whether q.special holds an entry at a particular index is done by comparing the value against the default value of the data type, which is what map access will return at uninitialized keys. This will correctly identify indexes at which no data point was added to q.special. However, data points that were added but happened to be the default value of that type will also be found, as false positives.

Because of this, the ultimate order of the data returned may be other than intended whenever a pinned entry has the default value.

For example, assume that there is a pinned entry A at index 0, and there is additionally an ordered entry B. The expectation is that B occurs as the second entry and A as the first. But if A happens to have the default value, then B will actually occur as the first entry. As A is not detected as a real data entry, it will not explicitly be added, but padding with default values may ultimately act as if A had been added as the second entry, as A also has the default value.

Entries with default value are unlikely to occur in practice. However, their occurrence is not impossible, as the default value of a StorageData data point would state that at the genesis block, address zero had value zero at storage slot zero, which is a sensible statement about historical Ethereum storage data.

Impact

In very rare edge cases, list might return incorrectly ordered data.

Recommendations

We recommend to check whether the map has a value at the relevant key rather than only checking whether the returned value is the default. This can be done by replacing the q.special[i] != empty check by something like the following:

-if q.special[i] != empty {
+// The second return value of a map access is a Boolean indicating whether a value was found at that key.
+value, exists := q.special[i]
+if exists {

Remediation

This issue has been acknowledged by Brevis, and a fix was implemented in commit 7b2df59a.

Zellic © 2025Back to top ↑