| विवरण | ### Description
We discovered a Denial of Service (DoS) vulnerability in Mapnik. The application crashes with a SIGFPE (Floating Point Exception) due to a Division by Zero error.
This crash is reproducible in RELEASE builds. The issue occurs when the expression evaluator processes a modulo operation (%) where the divisor evaluates to zero, causing an immediate hardware exception and process termination.
### Environment
- OS: Linux x86_64
- Complier: Clang/GCC with AddressSanitizer (-fsanitize=address)
- Build Configuration: Release Mode (-O3, -DNDEBUG),Static Plugins Linking
- Affected Version: `master branch`
### Vulnerability Details
- Target: Mapnik
- Vulnerability Type: Floating Point Exception (Integer Division/Modulo by Zero)
- Source File: src/value.cpp
- Function: mapnik::detail::mod<...>::operator()
- Line Number: 389
- Root Cause Analysis: The stack trace identifies the crash in mapnik::detail::mod...operator()<long>. Frame #-8 (evaluate_expression) and Frame #-6 (operator%) indicate that the parser is evaluating a mathematical expression defined in the Mapnik XML style (likely within a symbolizer property like stroke-width or similar, as seen in parse_stroke at Frame #-43). The FPE signal implies that the second operand of the modulo operation was 0. The code at src/value.cpp:389 likely performs a raw % operation on long integers without checking if the divisor is zero.
### Reproduce
1. Build Mapnik with Release optimization (-O3) and ASAN enabled. Input plugins should be linked statically.
2. Compile the Mapnik [harness](https://github.com/oneafter/1219/blob/main/harness.cpp) with AddressSanitizer enabled (-fsanitize=address -g)
3. Run with the crashing file [repro](https://github.com/oneafter/1219/blob/main/repro):
```
./harness repro
```
ASAN report
```
AddressSanitizer:DEADLYSIGNAL
=================================================================
==20072==ERROR: AddressSanitizer: FPE on unknown address 0x55aad44d2854 (pc 0x55aad44d2854 bp 0x7ffe603780d0 sp 0x7ffe603780c0 T0)
#0 0x55aad44d2854 in mapnik::value_adl_barrier::value mapnik::detail::mod<mapnik::value_adl_barrier::value>::operator()<long>(long, long) const /src/mapnik/src/value.cpp:389:20
#1 0x55aad44d2854 in mapnik::value_adl_barrier::value mapbox::util::detail::binary_dispatcher<mapnik::value_adl_barrier::value, long, double, icu_74::UnicodeString>::apply<mapnik::value_adl_barrier::value const&, mapnik::detail::mod<mapnik::value_adl_barrier::value>>(mapnik::value_adl_barrier::value const&, mapnik::value_adl_barrier::value const&, mapnik::detail::mod<mapnik::value_adl_barrier::value>&&) /src/mapnik/deps/mapbox/variant/include/mapbox/variant.hpp:432:24
#2 0x55aad44d20da in mapnik::value_adl_barrier::value mapbox::util::detail::binary_dispatcher<mapnik::value_adl_barrier::value, bool, long, double, icu_74::UnicodeString>::apply<mapnik::value_adl_barrier::value const&, mapnik::detail::mod<mapnik::value_adl_barrier::value>>(mapnik::value_adl_barrier::value const&, mapnik::value_adl_barrier::value const&, mapnik::detail::mod<mapnik::value_adl_barrier::value>&&) /src/mapnik/deps/mapbox/variant/include/mapbox/variant.hpp:448:16
#3 0x55aad44d20da in mapnik::value_adl_barrier::value mapbox::util::detail::binary_dispatcher<mapnik::value_adl_barrier::value, mapnik::value_null, bool, long, double, icu_74::UnicodeString>::apply<mapnik::value_adl_barrier::value const&, mapnik::detail::mod<mapnik::value_adl_barrier::value>>(mapnik::value_adl_barrier::value const&, mapnik::value_adl_barrier::value const&, mapnik::detail::mod<mapnik::value_adl_barrier::value>&&) /src/mapnik/deps/mapbox/variant/include/mapbox/variant.hpp:448:16
#4 0x55aad44c7992 in mapnik::value_adl_barrier::value mapbox::util::variant<mapnik::value_null, bool, long, double, icu_74::UnicodeString>::binary_visit<mapnik::detail::mod<mapnik::value_adl_barrier::value>, mapnik::value_adl_barrier::value const&, mapnik::value_null const&, mapnik::value_adl_barrier::value>(mapnik::value_adl_barrier::value const&, mapnik::value_adl_barrier::value const&, mapnik::detail::mod<mapnik::value_adl_barrier::value>&&) /src/mapnik/deps/mapbox/variant/include/mapbox/variant.hpp:846:16
#5 0x55aad44c7992 in decltype(fp0.binary_visit(std::forward<mapnik::value_adl_barrier::value const&>(fp0), std::forward<mapnik::value_adl_barrier::value const&>(fp1), std::forward<mapnik::detail::mod<mapnik::value_adl_barrier::value>>(fp))) mapnik::util::apply_visitor<mapnik::detail::mod<mapnik::value_adl_barrier::value>, mapnik::value_adl_barrier::value const&>(mapnik::detail::mod<mapnik::value_adl_barrier::value>&&, mapnik::value_adl_barrier::value const&, mapnik::value_adl_barrier::value const&) /src/mapnik/include/mapnik/util/variant.hpp:50:12
#6 0x55aad44c7992 in mapnik::value_adl_barrier::operator%(mapnik::value_adl_barrier::value const&, mapnik::value_adl_barrier::value const&) /src/mapnik/src/value.cpp:761:18
#7 0x55aad432f6c7 in std::modulus<mapnik::value_adl_barrier::value>::operator()(mapnik::value_adl_barrier::value const&, mapnik::value_adl_barrier::value const&) const /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/stl_function.h:230:20
#8 0x55aad432f6c7 in mapnik::value_adl_barrier::value mapnik::(anonymous namespace)::evaluate_expression<mapnik::value_adl_barrier::value, std::nullopt_t>::operator()<mapnik::tags::mod>(mapnik::binary_node<mapnik::tags::mod> const&) const /src/mapnik/include/mapnik/evaluate_global_attributes.hpp:169:16
#9 0x55aad432d761 in mapnik::value_adl_barrier::value mapbox::util::detail::dispatcher<mapnik::value_adl_barrier::value, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::plus>>, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::minus>>, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::mult>>,
...,
mapbox::util::recursive_wrapper<mapnik::binary_function_call>>> const&) /src/mapnik/include/mapnik/evaluate_global_attributes.hpp:268:32
#41 0x55aad43291af in mapnik::detail::set_symbolizer_property_impl<mapnik::symbolizer_base, double, false>::apply(mapnik::symbolizer_base&, mapnik::keys, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, mapnik::xml_node const&) /src/mapnik/include/mapnik/symbolizer_utils.hpp:398:31
#42 0x55aad42ee06e in void mapnik::set_symbolizer_property<mapnik::symbolizer_base, double>(mapnik::symbolizer_base&, mapnik::keys, mapnik::xml_node const&) /src/mapnik/include/mapnik/symbolizer_utils.hpp:525:9
#43 0x55aad42f34d5 in mapnik::map_parser::parse_stroke(mapnik::symbolizer_base&, mapnik::xml_node const&) /src/mapnik/src/load_map.cpp:1383:5
#44 0x55aad42e150c in mapnik::map_parser::parse_line_symbolizer(mapnik::rule&, mapnik::xml_node const&) /src/mapnik/src/load_map.cpp:1398:9
#45 0x55aad42d14ad in mapnik::map_parser::parse_symbolizers(mapnik::rule&, mapnik::xml_node const&) /src/mapnik/src/load_map.cpp:994:17
#46 0x55aad42cd567 in mapnik::map_parser::parse_rule(mapnik::feature_type_style&, mapnik::xml_node const&) /src/mapnik/src/load_map.cpp:953:9
#47 0x55aad42b9a69 in mapnik::map_parser::parse_style(mapnik::Map&, mapnik::xml_node const&) /src/mapnik/src/load_map.cpp:550:17
#48 0x55aad42b1a56 in mapnik::map_parser::parse_map_include(mapnik::Map&, mapnik::xml_node const&) /src/mapnik/src/load_map.cpp:425:17
#49 0x55aad42aabc2 in mapnik::map_parser::parse_map(mapnik::Map&, mapnik::xml_node const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&) /src/mapnik/src/load_map.cpp:398:9
#50 0x55aad42aead5 in mapnik::load_map_string(mapnik::Map&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, bool, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>) /src/mapnik/src/load_map.cpp:246:12
#51 0x55aad427ef4c in main /src/mapnik/harness_map_xml_simple.cpp:43:9
#52 0x7f8d2369e1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#53 0x7f8d2369e28a in __libc_start_main csu/../csu/libc-start.c:360:3
#54 0x55aad419afc4 in _start (/src/mapnik/harness_map_xml_simple+0xb5fc4) (BuildId: 461604e6f7bc5cc936fdce6b4f8515c956e7c014)
==20072==Register values:
rax = 0x00000000000022b8 rbx = 0x00007f8d1bb22220 rcx = 0x0000000000000000 rdx = 0x0000000000000000
rdi = 0x0000000000000001 rsi = 0x00007f8d1bb22428 rbp = 0x00007ffe603780d0 rsp = 0x00007ffe603780c0
r8 = 0x0000000000000001 r9 = 0x0000000000000001 r10 = 0x0000000000000001 r11 = 0x0000000000000001
r12 = 0x00000ff1a3764480 r13 = 0x00007f8d1bb22490 r14 = 0x000050d0000033b8 r15 = 0x00007f8d1bb22420
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: FPE /src/mapnik/src/value.cpp:389:20 in mapnik::value_adl_barrier::value mapnik::detail::mod<mapnik::value_adl_barrier::value>::operator()<long>(long, long) const
==20072==ABORTING
``` |
|---|