paavohtl Claude Opus 4.6 (1M context) commited on
Commit
ed4e24d
·
1 Parent(s): ae56671

fix: use *mut u8 in TeamArenaRef, add team_header_mut

Browse files

TeamArenaRef.base was *const u8 but team_header_mut() cast it to
*mut, which is unsound. Change base to *mut u8 so all mutable
access goes through legitimate mutable pointers.

blocks() now returns *mut TeamBlock. team_header_mut() no longer
needs a const-to-mut cast.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

crates/openwa-core/src/engine/ddgame.rs CHANGED
@@ -1898,7 +1898,7 @@ impl TeamArenaState {
1898
  #[repr(transparent)]
1899
  #[derive(Clone, Copy)]
1900
  pub struct TeamArenaRef {
1901
- base: *const u8,
1902
  }
1903
 
1904
  impl TeamArenaRef {
@@ -1909,7 +1909,7 @@ impl TeamArenaRef {
1909
  #[inline]
1910
  pub unsafe fn from_raw(base: u32) -> Self {
1911
  Self {
1912
- base: base as *const u8,
1913
  }
1914
  }
1915
 
@@ -1927,8 +1927,8 @@ impl TeamArenaRef {
1927
 
1928
  /// Get pointer to the TeamBlock array base.
1929
  #[inline]
1930
- pub unsafe fn blocks(&self) -> *const TeamBlock {
1931
- self.base.sub(offsets::ARENA_TO_BLOCKS) as *const TeamBlock
1932
  }
1933
 
1934
  /// Get the team header (metadata) for a team.
@@ -1940,6 +1940,12 @@ impl TeamArenaRef {
1940
  &(*self.blocks().add(team_idx + 1)).header.team
1941
  }
1942
 
 
 
 
 
 
 
1943
  /// Get a playable worm entry by 1-indexed worm number (1..=8).
1944
  ///
1945
  /// Uses raw pointer arithmetic matching the original WA code:
 
1898
  #[repr(transparent)]
1899
  #[derive(Clone, Copy)]
1900
  pub struct TeamArenaRef {
1901
+ base: *mut u8,
1902
  }
1903
 
1904
  impl TeamArenaRef {
 
1909
  #[inline]
1910
  pub unsafe fn from_raw(base: u32) -> Self {
1911
  Self {
1912
+ base: base as *mut u8,
1913
  }
1914
  }
1915
 
 
1927
 
1928
  /// Get pointer to the TeamBlock array base.
1929
  #[inline]
1930
+ pub unsafe fn blocks(&self) -> *mut TeamBlock {
1931
+ self.base.sub(offsets::ARENA_TO_BLOCKS) as *mut TeamBlock
1932
  }
1933
 
1934
  /// Get the team header (metadata) for a team.
 
1940
  &(*self.blocks().add(team_idx + 1)).header.team
1941
  }
1942
 
1943
+ /// Get a mutable team header for a team.
1944
+ #[inline]
1945
+ pub unsafe fn team_header_mut(&self, team_idx: usize) -> &mut TeamHeader {
1946
+ &mut (*self.blocks().add(team_idx + 1)).header.team
1947
+ }
1948
+
1949
  /// Get a playable worm entry by 1-indexed worm number (1..=8).
1950
  ///
1951
  /// Uses raw pointer arithmetic matching the original WA code:
crates/openwa-wormkit/src/replacements/weapon.rs CHANGED
@@ -400,7 +400,6 @@ unsafe fn fire_weapon_special(
400
  /// In game_version > 0x1C: toggles (set/clear). Otherwise: always sets.
401
  unsafe fn fire_skip_go(worm: *const CTaskWorm, entry: *const WeaponEntry) {
402
  use openwa_core::engine::ddgame::TeamArenaRef;
403
- use openwa_core::engine::ddgame::TeamHeader;
404
  use openwa_core::engine::DDGame;
405
 
406
  let ddgame = (*worm).base.base.ddgame as *mut DDGame;
@@ -412,13 +411,13 @@ unsafe fn fire_skip_go(worm: *const CTaskWorm, entry: *const WeaponEntry) {
412
 
413
  let arena_ptr = &raw mut (*ddgame).team_arena as u32;
414
  let arena = TeamArenaRef::from_raw(arena_ptr);
415
- let header = arena.team_header(team_index) as *const TeamHeader as *mut TeamHeader;
416
- let flags = (*header).turn_action_flags;
417
 
418
  if game_version > 0x1C && (flags & bit) != 0 {
419
- (*header).turn_action_flags = flags & !bit;
420
  } else {
421
- (*header).turn_action_flags = flags | bit;
422
  }
423
  }
424
 
 
400
  /// In game_version > 0x1C: toggles (set/clear). Otherwise: always sets.
401
  unsafe fn fire_skip_go(worm: *const CTaskWorm, entry: *const WeaponEntry) {
402
  use openwa_core::engine::ddgame::TeamArenaRef;
 
403
  use openwa_core::engine::DDGame;
404
 
405
  let ddgame = (*worm).base.base.ddgame as *mut DDGame;
 
411
 
412
  let arena_ptr = &raw mut (*ddgame).team_arena as u32;
413
  let arena = TeamArenaRef::from_raw(arena_ptr);
414
+ let header = arena.team_header_mut(team_index);
415
+ let flags = header.turn_action_flags;
416
 
417
  if game_version > 0x1C && (flags & bit) != 0 {
418
+ header.turn_action_flags = flags & !bit;
419
  } else {
420
+ header.turn_action_flags = flags | bit;
421
  }
422
  }
423