Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix dangling reference in Character::gen_aim_mods_cache() #69589

Merged
merged 2 commits into from
Nov 21, 2023

Conversation

BrettDong
Copy link
Member

Summary

None

Purpose of change

aim_mods_cache Character::gen_aim_mods_cache( const item &gun )const
{
parallax_cache parallaxes{ get_character_parallax( true ), get_character_parallax( false ) };
auto parallaxes_opt = std::make_optional( std::ref( parallaxes ) );
aim_mods_cache aim_cache = { get_modifier( character_modifier_aim_speed_skill_mod, gun.gun_skill() ), get_modifier( character_modifier_aim_speed_dex_mod ), get_modifier( character_modifier_aim_speed_mod ), most_accurate_aiming_method_limit( gun ), aim_factor_from_volume( gun ), aim_factor_from_length( gun ), parallaxes_opt };
return aim_cache;
}

Character::gen_aim_mods_cache() stores a reference to the local variable parallaxes, causes a use-after-scope in subsequent aim speed calculations.

[brett] ~/Developer/Cataclysm-DDA [master]  % ./tests/cata_test unskilled_shooter_accuracy

22:34:33.469 INFO : SDL render devices: software, metal, opengl, opengles2
22:34:33.469 INFO : [options] C locale set to C
22:34:33.469 INFO : [options] C++ locale set to C
22:34:39.133 INFO : src/mod_tracker.h:68: Tried check if 'FakeSpecial_s_gas' had a duplicate, but type 'overmap_special' does not track object sources
22:35:01.319 INFO : Game data loaded, running Catch2 session:
Filters: unskilled_shooter_accuracy
=================================================================
==45065==ERROR: AddressSanitizer: stack-use-after-scope on address 0x00016fb189e4 at pc 0x000102812ab8 bp 0x00016fb18790 sp 0x00016fb18788
READ of size 4 at 0x00016fb189e4 thread T0
    #0 0x102812ab4 in Character::fastest_aiming_method_speed(item const&, double, Target_attributes, std::__1::optional<std::__1::reference_wrapper<parallax_cache>>) const character.cpp:988
    #1 0x102812f3c in Character::aim_per_move(item const&, double, Target_attributes, std::__1::optional<std::__1::reference_wrapper<aim_mods_cache const>>) const character.cpp:1100
    #2 0x104eb41ec in npc::aim(Target_attributes const&) npcmove.cpp:2300
    #3 0x101782168 in get_dispersion(npc&, int, int) ranged_balance_test.cpp:132
    #4 0x10177b3c0 in test_shooting_scenario(npc&, int, int, int) ranged_balance_test.cpp:163
    #5 0x101740b4c in ____C_A_T_C_H____T_E_S_T____37() ranged_balance_test.cpp:251
    #6 0x101bc01ec in Catch::RunContext::invokeActiveTestCase() catch.hpp:12997
    #7 0x101bbb528 in Catch::RunContext::runCurrentTest(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>&) catch.hpp:12970
    #8 0x101bb970c in Catch::RunContext::runTest(Catch::TestCase const&) catch.hpp:12731
    #9 0x101bc727c in Catch::Session::runInternal() catch.hpp:13530
    #10 0x101bc5bd8 in Catch::Session::run() catch.hpp:13486
    #11 0x101c0b424 in main test_main.cpp:405
    #12 0x18ecc10dc  (<unknown module>)

Address 0x00016fb189e4 is located in stack of thread T0 at offset 100 in frame
    #0 0x102812e04 in Character::aim_per_move(item const&, double, Target_attributes, std::__1::optional<std::__1::reference_wrapper<aim_mods_cache const>>) const character.cpp:1095

  This frame has 2 object(s):
    [32, 64) 'agg.tmp'
    [96, 112) 'gun_skill' (line 1115) <== Memory access at offset 100 is inside this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope character.cpp:988 in Character::fastest_aiming_method_speed(item const&, double, Target_attributes, std::__1::optional<std::__1::reference_wrapper<parallax_cache>>) const
Shadow bytes around the buggy address:
  0x00016fb18700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x00016fb18780: 00 00 00 00 f1 f1 f1 f1 00 00 f2 f2 00 00 00 f2
  0x00016fb18800: f2 f2 f2 f2 f8 f8 f8 f3 f3 f3 f3 f3 00 00 00 00
  0x00016fb18880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x00016fb18900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x00016fb18980: f1 f1 f1 f1 00 00 00 00 f2 f2 f2 f2[f8]f8 f3 f3
  0x00016fb18a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x00016fb18a80: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 f2 f2
  0x00016fb18b00: 00 00 00 00 f2 f2 f2 f2 00 00 00 00 00 00 f2 f2
  0x00016fb18b80: f2 f2 f8 f2 f2 f2 00 00 00 00 f3 f3 f3 f3 f3 f3
  0x00016fb18c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==45065==ABORTING
Stack trace at fatal error:


    Attempting to repeat stack trace using debug symbols…

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cata_test is a Catch v2.13.7 host application.
Run with -? for options

-------------------------------------------------------------------------------
unskilled_shooter_accuracy
  an unskilled shooter with a common pistol
-------------------------------------------------------------------------------
../tests/ranged_balance_test.cpp:249
...............................................................................

../tests/ranged_balance_test.cpp:160: FAILED:
  {Unknown expression after the reported line}
due to a fatal error condition:
  SIGABRT - Abort (abnormal termination) signal

===============================================================================
test cases:  1 |  0 passed | 1 failed
assertions: 18 | 17 passed | 1 failed

zsh: abort      ./tests/cata_test unskilled_shooter_accuracy

Describe the solution

Make minimal code changes to avoid creating dangling references.

Describe alternatives you've considered

I am not sure if using std::optional<std::reference_wrapper<T> is really appropriate here, and this part of code might worth revisiting for a refactor in the future.

Testing

AddressSanitizer does not report error after this patch.

Additional context

@github-actions github-actions bot added NPC / Factions NPCs, AI, Speech, Factions, Ownership [C++] Changes (can be) made in C++. Previously named `Code` json-styled JSON lint passed, label assigned by github actions astyled astyled PR, label is assigned by github actions BasicBuildPassed This PR builds correctly, label assigned by github actions labels Nov 20, 2023
@Maleclypse Maleclypse merged commit d40bba2 into CleverRaven:master Nov 21, 2023
@BrettDong BrettDong deleted the dangling-ref branch November 23, 2023 07:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
astyled astyled PR, label is assigned by github actions BasicBuildPassed This PR builds correctly, label assigned by github actions [C++] Changes (can be) made in C++. Previously named `Code` json-styled JSON lint passed, label assigned by github actions NPC / Factions NPCs, AI, Speech, Factions, Ownership
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants