From 363db1c56ad351cad05805938445421eb63e7c76 Mon Sep 17 00:00:00 2001
From: Wizzard <rich@bandaholics.cash>
Date: Mon, 10 Mar 2025 21:08:42 -0400
Subject: [PATCH] Fix memory leak + crash

---
 src/dma/context/mod.rs    |   5 +-
 src/dma/mod.rs            | 103 +++++++++++++++++++++++---------------
 src/dma/threaddata/mod.rs |  10 ++--
 3 files changed, 71 insertions(+), 47 deletions(-)

diff --git a/src/dma/context/mod.rs b/src/dma/context/mod.rs
index 7a58ff7..27b1d11 100755
--- a/src/dma/context/mod.rs
+++ b/src/dma/context/mod.rs
@@ -196,7 +196,8 @@ impl DmaCtx {
         let mut data_vec: Vec<(Address, u64, Vec<(u64, i32)>)> = data_vec
             .into_iter()
             .map(|(pawn, _, wep_count, wep_base)| {
-                let weps = (0..wep_count).into_iter().map(|idx| (0u64, idx)).collect();
+                let safe_count = if wep_count < 0 || wep_count > 32 { 0 } else { wep_count };
+                let weps = (0..safe_count).into_iter().map(|idx| (0u64, idx)).collect();
                 (pawn, wep_base, weps)
             })
             .collect();
@@ -206,7 +207,7 @@ impl DmaCtx {
         data_vec.iter_mut().for_each(|(_, wep_base, wep_data_vec)| {
             wep_data_vec.iter_mut().for_each(|(_, idx)| {
                 let b: Address = (*wep_base).into();
-                batcher.read_into(b + * idx * 0x4, idx);
+                batcher.read_into(b + u64::saturating_mul(*idx as u64, 0x4), idx);
             });
         });
         drop(batcher);
diff --git a/src/dma/mod.rs b/src/dma/mod.rs
index 1dc91bd..c23e670 100755
--- a/src/dma/mod.rs
+++ b/src/dma/mod.rs
@@ -76,10 +76,18 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_
                 .into_iter()
                 .map(|(_, pawn)| pawn)
                 .collect();
-
-            pawns.push(data.local_pawn.into());
         
+            pawns.push(data.local_pawn.into());
+
+            let prev_holder = data.bomb_holder;
+
             data.bomb_holder = ctx.get_c4_holder(pawns, data.entity_list.into(), &data);
+
+            if data.bomb_holder.is_some() && prev_holder.is_none() {
+                log::debug!("Bomb picked up by player");
+                data.bomb_dropped = false;
+            }
+
             data.recheck_bomb_holder = false;
         }
 
@@ -138,18 +146,25 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_
 
             // Bomb
             if data.bomb_dropped || data.bomb_planted {
-                let node = ctx.process.read_addr64(
+                if let Ok(node) = ctx.process.read_addr64(
                     data.bomb + cs2dumper::client::C_BaseEntity::m_pGameSceneNode as u64
-                ).unwrap();
-                let pos = ctx.process.read(node + cs2dumper::client::CGameSceneNode::m_vecAbsOrigin).unwrap();
-    
-                entity_data.push(EntityData::Bomb(BombData::new(pos, data.bomb_planted)));
+                ) {
+                    if let Ok(pos) = ctx.process.read(node + cs2dumper::client::CGameSceneNode::m_vecAbsOrigin) {
+                        entity_data.push(EntityData::Bomb(BombData::new(pos, data.bomb_planted)));
+                    }
+                }
             }
 
             // Local player
-            let local_data = ctx.batched_player_read(
+            let local_data = match ctx.batched_player_read(
                 data.local.into(), data.local_pawn.into()
-            ).unwrap();
+            ) {
+                Ok(data) => data,
+                Err(e) => {
+                    log::warn!("Failed to read local player data: {}", e);
+                    continue;
+                }
+            };
 
             if local_data.health > 0 {
                 let has_bomb = match data.bomb_holder {
@@ -160,7 +175,7 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_
                 entity_data.push(
                     EntityData::Player(
                         PlayerData::new(
-                            local_data.pos, 
+                            local_data.pos,
                             local_data.yaw,
                             PlayerType::Local,
                             has_bomb,
@@ -175,41 +190,47 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_
 
             // Other players
             for (controller, pawn) in &data.players {
-                let player_data = ctx.batched_player_read(*controller, *pawn).unwrap();
+                match ctx.batched_player_read(*controller, *pawn) {
+                    Ok(player_data) => {
+                        if player_data.health < 1 {
+                            continue;
+                        }
 
-                if player_data.health < 1 {
-                    continue;
-                }
+                        let has_bomb = match data.bomb_holder {
+                            Some(bh) => *pawn == bh,
+                            None => false,
+                        };
 
-                let has_bomb = match data.bomb_holder {
-                    Some(bh) => *pawn == bh,
-                    None => false,
-                };
+                        let player_type = {
+                            if local_data.team != player_data.team {
+                                PlayerType::Enemy
+                            } else if local_data.team == player_data.team {
+                                PlayerType::Team
+                            } else {
+                                PlayerType::Unknown
+                            }
+                        };
 
-                let player_type = {
-                    if local_data.team != player_data.team {
-                        PlayerType::Enemy
-                    } else if local_data.team == player_data.team {
-                        PlayerType::Team
-                    } else {
-                        PlayerType::Unknown
+                        entity_data.push(
+                            EntityData::Player(
+                                PlayerData::new(
+                                    player_data.pos,
+                                    player_data.yaw,
+                                    player_type,
+                                    has_bomb,
+                                    player_data.has_awp,
+                                    player_data.is_scoped,
+                                    player_data.player_name,
+                                    player_data.weapon_id
+                                )
+                            )
+                        );
+                    },
+                    Err(e) => {
+                        log::warn!("Failed to read player data: {}", e);
+                        continue;
                     }
-                };
-
-                entity_data.push(
-                    EntityData::Player(
-                        PlayerData::new(
-                            player_data.pos, 
-                            player_data.yaw,
-                            player_type,
-                            has_bomb,
-                            player_data.has_awp,
-                            player_data.is_scoped,
-                            player_data.player_name,
-                            player_data.weapon_id
-                        )
-                    )
-                );
+                }
             }
 
             let mut radar = radar_data.write().await;
diff --git a/src/dma/threaddata/mod.rs b/src/dma/threaddata/mod.rs
index 1ba32bd..f214d18 100755
--- a/src/dma/threaddata/mod.rs
+++ b/src/dma/threaddata/mod.rs
@@ -104,10 +104,12 @@ impl CsData {
                 }
             }
         } else if self.bomb_planted {
-            let bomb = ctx.get_plantedc4()
-                .expect("Failed to get planted bomb");
-
-            self.bomb = bomb;
+            match ctx.get_plantedc4() {
+                Ok(bomb) => self.bomb = bomb,
+                Err(e) => {
+                    log::warn!("Failed to get planted bomb: {}", e);
+                }
+            }
         }
     }