Out-of-bounds write in update test instruction
Description
Pyth exposes two instructions associated with test price accounts - one to initialize them, and another to update the account's pricing information. The update instruction sets pricing, status, and confidence intervals for the test account's price components using a loop that copies over values from the instruction data to the account. This loop iterates a number of times as specified by the caller, incrementing a variable used to index into the price components.
for( uint32_t i=0; i != cmd->num_; ++i ) {
pc_price_comp_t *ptr = &px->comp_[i];
ptr->latest_.status_ = PC_STATUS_TRADING;
ptr->latest_.price_ = cmd->price_[i];
ptr->latest_.conf_ = cmd->conf_[i];
ptr->latest_.pub_slot_ = slot + (uint64_t)cmd->slot_diff_[i];
}
upd_aggregate( px, slot+1 );
The supplied number of iterations this loop should run is not bound in any way. This allows a caller to index past the end of the array, which has a fixed size of 32, and can allow an attacker to manipulate memory outside of the pricing components.
Impact
Memory corruption is a critical violation of program integrity and safety guarantees. The ability to write out-of-bounds can violate the integrity of data structures and invariants in the contract. Thankfully, this instruction validates that only two accounts can be supplied in invocation which does help reduce the impact, but this behavior is still dangerous and may result in an attack that could result in price manipulation.
The num_
variable is also referenced in upd_aggregate
, which eventually leads an out-of-bound stack write that can be potentially leveraged to redirect control flow.
Recommendations
The upd_test
instruction should validate that cmd->num_
is equal to or less than PC_COMP_SIZE
. This will preventing the out-of-bound indexing and write behavior.
Remediation
The finding has been acknowledged by Pyth Data Association. Their official response is reproduced below:
Pyth Data Association acknowledges the finding and a security fix for this issue will be deployed on or before April 18th.