Skip to content

Commit

Permalink
Merge pull request TaggrNetwork#44 from TaggrNetwork/corruption_fix
Browse files Browse the repository at this point in the history
fix: prevent usage of uninitialized allocator
  • Loading branch information
taggrx authored Apr 8, 2024
2 parents 5432e32 + d34757d commit 481f151
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 5 deletions.
33 changes: 30 additions & 3 deletions src/backend/env/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ impl Memory {

fn unpack(&mut self) {
self.api_ref = Rc::new(RefCell::new(self.api.clone()));
self.posts.api = Rc::clone(&self.api_ref);
self.features.api = Rc::clone(&self.api_ref);
self.posts.init(Rc::clone(&self.api_ref));
self.features.init(Rc::clone(&self.api_ref));
}

#[allow(clippy::type_complexity)]
Expand All @@ -114,7 +114,13 @@ impl Memory {
read_bytes: Some(read_bytes),
};
self.api_ref = Rc::new(RefCell::new(test_api));
self.posts.api = Rc::clone(&self.api_ref);
self.posts.init(Rc::clone(&self.api_ref));
self.features.init(Rc::clone(&self.api_ref));
}

#[cfg(test)]
pub fn unpack_for_testing(&mut self) {
self.unpack();
}
}

Expand Down Expand Up @@ -313,6 +319,8 @@ impl Allocator {
pub struct ObjectManager<K: Ord + Eq, T: Serialize + DeserializeOwned> {
index: BTreeMap<K, (u64, u64)>,
#[serde(skip)]
initialized: bool,
#[serde(skip)]
api: Rc<RefCell<Api>>,
#[serde(skip)]
phantom: std::marker::PhantomData<T>,
Expand All @@ -323,7 +331,20 @@ impl<K: Eq + Ord + Clone + Copy + Display, T: Serialize + DeserializeOwned> Obje
self.index.len()
}

// TODO: delete after restoring data
pub fn reset(&mut self) {
self.index.clear()
}

// TODO: delete after restoring data
pub fn reinsert(&mut self, id: K, value: T) {
assert!(self.initialized, "allocator uninitialized");
self.index
.insert(id, self.api.borrow_mut().write(&value).unwrap());
}

pub fn insert(&mut self, id: K, value: T) -> Result<(), String> {
assert!(self.initialized, "allocator uninitialized");
if self.index.contains_key(&id) {
self.remove(&id)?;
}
Expand All @@ -349,11 +370,17 @@ impl<K: Eq + Ord + Clone + Copy + Display, T: Serialize + DeserializeOwned> Obje
}

pub fn remove(&mut self, id: &K) -> Result<T, String> {
assert!(self.initialized, "allocator uninitialized");
let (offset, len) = self.index.remove(id).ok_or("not found")?;
let value = self.api.borrow().read(offset, len);
self.api.borrow_mut().remove(offset, len)?;
Ok(value)
}

pub fn init(&mut self, api: Rc<RefCell<Api>>) {
self.initialized = true;
self.api = api;
}
}

#[cfg(test)]
Expand Down
1 change: 1 addition & 0 deletions src/backend/env/proposals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ pub mod tests {
#[should_panic(expected = "couldn't take post 2: not found")]
fn test_wrong_post_id_in_proposal() {
mutate(|state| {
state.memory.unpack_for_testing();
create_user(state, pr(1));
state.principal_to_user_mut(pr(1)).unwrap().stalwart = true;
create_proposal(state, pr(1), 2, Payload::Noop, 0).unwrap();
Expand Down
43 changes: 41 additions & 2 deletions src/backend/updates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,51 @@ fn post_upgrade() {

#[allow(clippy::all)]
fn sync_post_upgrade_fixtures() {
mutate(|state| {
// Compensate for the executed by failed proposal #/post/1159871
// Restore features and corrupted posts
#[cfg(not(any(feature = "dev", feature = "staging")))]
{
mutate(|state| {
// Restore corrupted posts 2 & 3
use serde_json::json;
let post_2 = json!({"id":2,"body":"#hello everyone! I'm [X](#/user/0) the anonymous creator of #Taggr. I wanted to build Taggr for at least 15 years but there was no point to build it on #Web2 to compete with established social platforms. After I've learned about #SNS and #InternetComputer I realized that this is exactly the right moment and the right platform: a public #blockchain on a \"sovereign physical layer\". My main goal is to make #Taggr truly decentralized and make it operate fully autonomously. Then, as a community (if there will be one) we can figure out a sustainable development path for #Taggr.","user":0,"timestamp":1640952386200311995_u64,"children":[151],"parent":null,"watchers":[],"tags":["InternetComputer","SNS","Taggr","Web2","blockchain","hello"],"reactions":{"10":[18446744073709551614_u64,18446744073709551615_u64],"100":[18446744073709551615_u64]},"patches":[],"files":{},"tree_size":1,"tree_update":0,"report":null,"tips":[],"extension":null,"realm":null,"hashes":[],"reposts":[],"heat":0});
let post_3 = json!({"id":3,"body":"","user":0,"timestamp":1640954615975657983_i64,"children":[],"parent":null,"watchers":[],"tags":["HappyNewYear","story"],"reactions":{"10":[18446744073709551614_u64,18446744073709551615_u64]},"patches":[],"files":{},"tree_size":0,"tree_update":0,"report":null,"tips":[],"extension":null,"realm":null,"hashes":["c6687c165aaae7c71b08486bbb1e39fd41db0a2605783ebb10dc20d58094f03d"],"reposts":[],"heat":0});
state
.memory
.posts
.reinsert(2, serde_json::from_value(post_2).unwrap());
state
.memory
.posts
.reinsert(3, serde_json::from_value(post_3).unwrap());
});

// Restore features
mutate(|state| state.memory.features.reset());
let mut features = Vec::new();
read(|state| {
for post_id in 1136641..state.next_post_id {
if let Some(post) = Post::get(&state, &post_id) {
if !matches!(post.extension, Some(Extension::Feature)) {
continue;
}
let author = state.user(post.user.to_string().as_str()).unwrap();
features.push((author.principal, post_id));
}
}
});

features
.into_iter()
.for_each(|(author, post_id)| features::create_feature(author, post_id).unwrap());
}

// Compensate for the executed by failed proposal #/post/1159871
mutate(|state| {
if let Some(realm) = state.realms.get_mut("RUGANG") {
realm.controllers.insert(1277);
}
})

}

#[allow(clippy::all)]
Expand Down

0 comments on commit 481f151

Please sign in to comment.