-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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 div by zero crash in mana widget #75642
Prevent div by zero crash in mana widget #75642
Conversation
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 ```
I think this may resolve #72474 as well, though my past comments note that may have been due to power storage and not mana. |
Oh that's great. Yes, you're right! I can reliably reproduce that issue on Thanks for having such good memory @RenechCDDA ! I'll update the description with |
Backport #75642 Prevent div by zero crash in mana widget
Summary
Bugfixes "Prevent div by zero crash in mana widget"
Purpose of change
Prevents division by zero crash when displaying widgets with defined break levels.
Fixes #75566 . Fixes #72474 .
Describe the solution
Example of where previous crash from div-by-zero happened:
zenfs_thick_sidebar
, which includes widgetzenfs_mana_bar_14_no_label
that defines break levels.v=201
withmin=0
max=201
.known_magic::max_mana
where internal values arebionic_penalty=999
mana_base=1000
int_bonus=200
.known_magic::max_mana
will return0
becauseint_bonus=-100
._var_max=0
inwidget::value_color
and thusvar_range=0
which causes the div by zero.Backtrace of previous crash being fixed:
Describe alternatives you've considered
Testing
Additional context
Other conditionals in this method are already checking
var_range > 0
.