@@ -63,6 +63,11 @@ namespace libtorrent {
63
63
64
64
using namespace aux ;
65
65
66
+ // due to the recursive nature of update_map, it's necessary to
67
+ // limit the internal list of global mappings to a small size
68
+ // this can be changed once the entire UPnP code is refactored
69
+ constexpr std::size_t max_global_mappings = 50 ;
70
+
66
71
namespace upnp_errors
67
72
{
68
73
boost::system::error_code make_error_code (error_code_enum e)
@@ -227,6 +232,14 @@ port_mapping_t upnp::add_mapping(portmap_protocol const p, int const external_po
227
232
228
233
if (mapping_it == m_mappings.end ())
229
234
{
235
+ TORRENT_ASSERT (m_mappings.size () <= max_global_mappings);
236
+ if (m_mappings.size () >= max_global_mappings)
237
+ {
238
+ #ifndef TORRENT_DISABLE_LOGGING
239
+ log (" too many mappings registered" );
240
+ #endif
241
+ return port_mapping_t {-1 };
242
+ }
230
243
m_mappings.push_back (global_mapping_t ());
231
244
mapping_it = m_mappings.end () - 1 ;
232
245
}
@@ -1560,6 +1573,14 @@ void upnp::on_upnp_unmap_response(error_code const& e
1560
1573
1561
1574
d.mapping [mapping].protocol = portmap_protocol::none;
1562
1575
1576
+ // free the slot in global mappings
1577
+ auto pred = [mapping](rootdevice const & rd)
1578
+ { return rd.mapping [mapping].protocol == portmap_protocol::none; };
1579
+ if (std::all_of (m_devices.begin (), m_devices.end (), pred))
1580
+ {
1581
+ m_mappings[mapping].protocol = portmap_protocol::none;
1582
+ }
1583
+
1563
1584
next (d, mapping);
1564
1585
}
1565
1586
0 commit comments