Skip to content

Commit 71a3786

Browse files
committed
refactor(pyth-sdk-solana): refactor attribute iterators
There are some assumptions outside this SDK on the product attributes and the `size` field in particular that guarantee that the accesses are safe. This commit refactors it to add extra levels of safety to not rely on those assumptions.
1 parent 8c56e4f commit 71a3786

File tree

3 files changed

+18
-12
lines changed

3 files changed

+18
-12
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyth-sdk-solana/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pyth-sdk-solana"
3-
version = "0.10.4"
3+
version = "0.10.5"
44
authors = ["Pyth Data Foundation"]
55
workspace = "../"
66
edition = "2018"

pyth-sdk-solana/src/state.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use pyth_sdk::{
1818
};
1919
use solana_program::clock::Clock;
2020
use solana_program::pubkey::Pubkey;
21+
use std::cmp::min;
2122
use std::mem::size_of;
2223

2324
pub use pyth_sdk::{
@@ -192,7 +193,10 @@ pub struct ProductAccount {
192193
impl ProductAccount {
193194
pub fn iter(&self) -> AttributeIter {
194195
AttributeIter {
195-
attrs: &self.attr[..(self.size as usize - PROD_HDR_SIZE)],
196+
attrs: &self.attr[..min(
197+
(self.size as usize).saturating_sub(PROD_HDR_SIZE),
198+
PROD_ATTR_SIZE,
199+
)],
196200
}
197201
}
198202
}
@@ -321,7 +325,8 @@ where
321325
/// space for future derived values
322326
pub drv2: u8,
323327
/// space for future derived values
324-
pub drv3: u16,
328+
pub drv31: u8,
329+
pub drv32: u8,
325330
/// space for future derived values
326331
pub drv4: u32,
327332
/// product account key
@@ -366,7 +371,8 @@ where
366371
timestamp: Default::default(),
367372
min_pub: Default::default(),
368373
drv2: Default::default(),
369-
drv3: Default::default(),
374+
drv31: Default::default(),
375+
drv32: Default::default(),
370376
drv4: Default::default(),
371377
prod: Default::default(),
372378
next: Default::default(),
@@ -574,21 +580,21 @@ impl<'a> Iterator for AttributeIter<'a> {
574580
if self.attrs.is_empty() {
575581
return None;
576582
}
577-
let (key, data) = get_attr_str(self.attrs);
578-
let (val, data) = get_attr_str(data);
583+
let (key, data) = get_attr_str(self.attrs)?;
584+
let (val, data) = get_attr_str(data)?;
579585
self.attrs = data;
580586
Some((key, val))
581587
}
582588
}
583589

584-
fn get_attr_str(buf: &[u8]) -> (&str, &[u8]) {
590+
fn get_attr_str(buf: &[u8]) -> Option<(&str, &[u8])> {
585591
if buf.is_empty() {
586-
return ("", &[]);
592+
return Some(("", &[]));
587593
}
588594
let len = buf[0] as usize;
589-
let str = std::str::from_utf8(&buf[1..len + 1]).expect("attr should be ascii or utf-8");
590-
let remaining_buf = &buf[len + 1..];
591-
(str, remaining_buf)
595+
let str = std::str::from_utf8(&buf[1..len + 1]).ok()?;
596+
let remaining_buf = &buf.get(len + 1..)?;
597+
Some((str, remaining_buf))
592598
}
593599

594600
#[cfg(test)]

0 commit comments

Comments
 (0)