Skip to content

Commit

Permalink
Prevent div by zero crash in mana widget
Browse files Browse the repository at this point in the history
Prevents division by zero crash when displaying widgets with defined
break levels.

Example of where previous crash from div-by-zero happened:
* Provided save used the `zenfs_thick_sidebar`, which includes widget
  `zenfs_mana_bar_14_no_label` that defines break levels.
* When running the provided save, mana value is usually at `v=201` with
  `min=0` `max=201`.
* Those values are computed by `known_magic::max_mana` where internal
  values are `bionic_penalty=999` `mana_base=1000` `int_bonus=200`.
* But when int falls (because of tiredness), then
  `known_magic::max_mana` will return `0` because `int_bonus=-100`.
* This leads to `_var_max=0` in `widget::value_color` and thus
  `var_range=0` which causes the div by zero.

Backtrace of previous crash beng fixed:
```
Thread 1 "cataclysm-tiles" received signal SIGFPE, Arithmetic exception.
0x0000555556a9c54e in widget::value_color (this=this@entry=0x7fffffffb8d8, value=value@entry=201) at src/widget.cpp:1310
1310            const int value_offset = ( 100 * ( value - _var_min ) ) / var_range;

(gdb) bt
 #0  0x0000555556a9c54e in widget::value_color (this=this@entry=0x7fffffffb8d8, value=value@entry=201) at src/widget.cpp:1310
 CleverRaven#1  0x0000555556aa37dc in widget::color_value_string[abi:cxx11](int, int) (this=this@entry=0x7fffffffb8d8, value=201, width_max=width_max@entry=14) at src/widget.cpp:1262
 CleverRaven#2  0x0000555556aa38ca in widget::show[abi:cxx11](avatar const&, unsigned int) (this=this@entry=0x7fffffffb8d8, ava=..., max_width=max_width@entry=14) at src/widget.cpp:890
 CleverRaven#3  0x0000555556aa497f in widget::layout[abi:cxx11](avatar const&, unsigned int, int, bool) (this=this@entry=0x7fffffffb8d8, ava=..., max_width=<optimized out>, label_width=label_width@entry=0, skip_pad=false) at src/widget.cpp:1834
 CleverRaven#4  0x0000555556aa42c2 in widget::layout[abi:cxx11](avatar const&, unsigned int, int, bool) (this=this@entry=0x7fffffffbe88, ava=..., max_width=<optimized out>, label_width=label_width@entry=9, skip_pad=false) at src/widget.cpp:1794
 CleverRaven#5  0x0000555556aa3cfa in widget::layout[abi:cxx11](avatar const&, unsigned int, int, bool) (this=this@entry=0x7fffffffc438, ava=..., max_width=<optimized out>, label_width=label_width@entry=0, skip_pad=false) at src/widget.cpp:1724
 CleverRaven#6  0x0000555556aa42c2 in widget::layout[abi:cxx11](avatar const&, unsigned int, int, bool) (this=this@entry=0x7fffffffc9e8, ava=..., max_width=<optimized out>, label_width=label_width@entry=0, skip_pad=false) at src/widget.cpp:1794
 CleverRaven#7  0x0000555556aa42c2 in widget::layout[abi:cxx11](avatar const&, unsigned int, int, bool) (this=this@entry=0x555562c47160, ava=..., max_width=<optimized out>, max_width@entry=64, label_width=<optimized out>, skip_pad=skip_pad@entry=false) at src/widget.cpp:1794
 CleverRaven#8  0x0000555556aa5222 in custom_draw_func (args=...) at src/widget.cpp:970
 CleverRaven#9  0x0000555555ec4360 in std::function<int(draw_args const&)>::operator() (this=0x555597eb1780, __args#0=...) at /usr/include/c++/14/bits/std_function.h:591
 CleverRaven#10 game::draw_panels (this=this@entry=0x55555827ef50, force_draw=force_draw@entry=true) at src/game.cpp:4007
 CleverRaven#11 0x0000555555eed1ac in game::draw (this=0x55555827ef50, ui=...) at src/game.cpp:3961
 CleverRaven#12 0x00005555569a962c in ui_adaptor::redraw_invalidated () at src/ui_manager.cpp:440
 CleverRaven#13 0x00005555569a96e9 in ui_adaptor::redraw () at src/ui_manager.cpp:345
 CleverRaven#14 0x00005555569a9710 in ui_manager::redraw () at src/ui_manager.cpp:506
 CleverRaven#15 0x0000555555dd0850 in do_turn () at src/do_turn.cpp:712
 CleverRaven#16 0x00005555557a138d in main (argc=<optimized out>, argv=<optimized out>) at src/main.cpp:873

(gdb) print var_range
$1 = 0
(gdb) print value
$2 = 201
(gdb) print _var_min
$3 = 0
(gdb) print _var_max
$4 = 0
```
  • Loading branch information
inogenous committed Aug 13, 2024
1 parent b8dba37 commit 6b09c6d
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion src/widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1306,7 +1306,7 @@ nc_color widget::value_color( int value )
// Get range of values from min to max
const int var_range = _var_max - _var_min;

if( ! _breaks.empty() ) {
if( var_range > 0 && ! _breaks.empty() ) {
const int value_offset = ( 100 * ( value - _var_min ) ) / var_range;
for( int i = 0; i < color_max; i++ ) {
if( value_offset < _breaks[i] ) {
Expand Down

0 comments on commit 6b09c6d

Please sign in to comment.