-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Prevent crash from negative array index for visibility_cache #75521
Prevent crash from negative array index for visibility_cache #75521
Conversation
Since you create a variable for the map, you might as well use it on the next line getting the level cache (and check if there are any other get_map calls that can be replaced). I don't see how you'd be able to convert these checks into compile time checks by using a pre checked type. It ought to result in it blowing up on assignment of the variable of said type when out of bounds instead (although I can't find the code for it in the template hell, and while it should still be better than seg faults, it's probably worse than your correction, where you reject the out of bounds parameters and treats it appropriately (by ignoring the out of bounds locations), rather than having a type conversion check blow up and probably crash the game with an at least some somewhat helpful error message). |
e0622ca
to
1bdca55
Compare
Thinking on it some more, you're probably right that it would need to be some runtime check anyway, like you say. My thinking was that at the moment, we allow reading these caches like
Thanks, have updated this now. No other usages in this method. |
I'm not opposed to a check resulting in a somewhat controlled failure, such as hiding the data behind a public operation that would perform a check and produce a report (preferably with a call chain) and then either crash after that by raising an exception, or return some garbage (such as the cache data for some legal entry, such as (0,0)). That would have saved a whole lot of effort trying to track this bugger down. However, none of that beats detecting and handling the issue in a suitable manner at a level where it can actually be done (like you did here). |
1bdca55
to
5260dcc
Compare
5260dcc
to
7d3e244
Compare
To reviewers: the above discussions are about a potential overall improvement, for a future change. I believe this change is ready to merge, since it fixes an actual crash. |
Prevents referencing `visibility_cache` using out-of-bounds array indexes such as negative values. Using out-of-bound indexes for this array previously caused crashes when compiled with `-D_GLIBCXX_ASSERTIONS`. The function `pixel_minimap::render_critters` is, for example, called with `center=(64,59,-5)`, which gives `start=(4,-1)` and then `p=(4,-1,-5)`, which previously crashed because `visibility_cache[p.x][p.y]` then gives a negative array index. Such values were seen when peeking using `X` at a submap boundary. Gdb backtrace of previous crash being fixed: ``` (gdb) bt #0 __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44 CleverRaven#1 0x00007ffff787840f in __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78 CleverRaven#2 0x00007ffff78294f2 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 CleverRaven#3 0x00007ffff78124ed in __GI_abort () at ./stdlib/abort.c:79 CleverRaven#4 0x00007ffff7ad30be in std::__glibcxx_assert_fail(char const*, int, char const*, char const*) () from /lib/x86_64-linux-gnu/libstdc++.so.6 CleverRaven#5 0x000055555668a04e in std::array<lit_level, 132ul>::operator[] (__n=18446744073709551615, this=0x555599f30348) at /usr/include/c++/13/array:211 CleverRaven#6 0x000055555668ab7a in std::array<lit_level, 132ul>::operator[] (__n=18446744073709551615, this=0x555599f30348) at /usr/include/c++/13/array:211 CleverRaven#7 pixel_minimap::render_critters (this=this@entry=0x555558108960, center=...) at src/pixel_minimap.cpp:521 CleverRaven#8 0x000055555668ada2 in pixel_minimap::render (this=0x555558108960, center=...) at src/pixel_minimap.cpp:447 CleverRaven#9 0x000055555668bb69 in pixel_minimap::draw (this=<optimized out>, screen_rect=..., center=...) at src/pixel_minimap.cpp:555 CleverRaven#10 0x0000555555b3fd5c in cata_tiles::draw_minimap (this=this@entry=0x555558093020, dest=..., center=..., width=width@entry=352, height=height@entry=352) at src/cata_tiles.cpp:1919 CleverRaven#11 0x00005555567f43d3 in cata_cursesport::curses_drawwindow (w=...) at src/sdltiles.cpp:1428 CleverRaven#12 0x000055555666f5e2 in std::function<void(draw_args const&)>::operator() (__args#0=..., this=<optimized out>) at /usr/include/c++/13/bits/std_function.h:591 CleverRaven#13 operator() (d=..., __closure=<optimized out>) at src/panels.cpp:54 CleverRaven#14 std::__invoke_impl<int, window_panel::window_panel(const std::function<void(const draw_args&)>&, const std::string&, const translation&, int, int, bool, const std::function<bool()>&, bool)::<lambda(const draw_args&)>&, const draw_args&> (__f=...) at /usr/include/c++/13/bits/invoke.h:61 CleverRaven#15 std::__invoke_r<int, window_panel::window_panel(const std::function<void(const draw_args&)>&, const std::string&, const translation&, int, int, bool, const std::function<bool()>&, bool)::<lambda(const draw_args&)>&, const draw_args&> (__fn=...) at /usr/include/c++/13/bits/invoke.h:114 CleverRaven#16 std::_Function_handler<int(const draw_args&), window_panel::window_panel(const std::function<void(const draw_args&)>&, const std::string&, const translation&, int, int, bool, const std::function<bool()>&, bool)::<lambda(const draw_args&)> >::_M_invoke(const std::_Any_data &, const draw_args &) (__functor=..., __args#0=...) at /usr/include/c++/13/bits/std_function.h:290 CleverRaven#17 0x0000555555e7c9ec in std::function<int(draw_args const&)>::operator() (__args#0=..., this=0x55559461d638) at /usr/include/c++/13/bits/std_function.h:591 CleverRaven#18 game::draw_panels (this=this@entry=0x555558276c40, force_draw=force_draw@entry=true) at src/game.cpp:4006 CleverRaven#19 0x0000555555e984f8 in game::draw (this=0x555558276c40, ui=...) at src/game.cpp:3960 CleverRaven#20 0x000055555695df35 in ui_adaptor::redraw_invalidated () at src/ui_manager.cpp:440 CleverRaven#21 0x000055555695e039 in ui_adaptor::redraw () at src/ui_manager.cpp:345 CleverRaven#22 0x000055555695e060 in ui_manager::redraw () at src/ui_manager.cpp:506 CleverRaven#23 0x0000555555ea95cf in game::look_around (this=this@entry=0x555558276c40, show_window=show_window@entry=true, center=..., start_point=..., has_first_point=has_first_point@entry=false, select_zone=false, peeking=true, is_moving_zone=<optimized out>, end_point=..., change_lv=true) at src/game.cpp:7529 CleverRaven#24 0x0000555555eadd32 in game::look_around (this=this@entry=0x555558276c40, looka_params=...) at src/game.cpp:7697 CleverRaven#25 0x0000555555eadecb in game::peek (this=this@entry=0x555558276c40, p=...) at src/game.cpp:6071 CleverRaven#26 0x0000555555ec441a in game::peek (this=this@entry=0x555558276c40) at src/game.cpp:6050 CleverRaven#27 0x0000555555f124ec in game::do_regular_action (this=this@entry=0x555558276c40, act=@0x7fffffffd104: ACTION_PEEK, player_character=..., mouse_target=std::optional [no contained value]) at src/handle_action.cpp:2432 CleverRaven#28 0x0000555555f15b09 in game::handle_action (this=0x555558276c40) at src/handle_action.cpp:3174 CleverRaven#29 0x0000555555d8a108 in do_turn () at /usr/include/c++/13/bits/unique_ptr.h:199 CleverRaven#30 0x0000555555781b4e in main (argc=<optimized out>, argv=<optimized out>) at src/main.cpp:873 (gdb) frame 7 (gdb) print p $1 = {static dimension = 3, x = 4, y = -1, z = -5} (gdb) print center $2 = (const tripoint &) @0x7fffffffbda8: {static dimension = 3, x = 64, y = 59, z = -5} ```
7d3e244
to
f876f90
Compare
Summary
Bugfixes "Prevent crash from negative array index for visibility_cache"
Purpose of change
Prevents referencing
visibility_cache
using out-of-bounds array indexes such as negative values. Using out-of-bound indexes for this array previously caused crashes when compiled with-D_GLIBCXX_ASSERTIONS
.Describe the solution
The function
pixel_minimap::render_critters
is, for example, called withcenter=(64,59,-5)
, which givesstart=(4,-1)
and thenp=(4,-1,-5)
, which previously crashed becausevisibility_cache[p.x][p.y]
then gives a negative array index. Such values were seen when peeking usingX
at a submap boundary.Gdb backtrace of previous crash being fixed:
Describe alternatives you've considered
_ib
), then problems such as these could be a compile-time error instead of silent out-of-bounds reading.Testing
Additional context