Opened 5 years ago
#13210 new Bugs
Signed integer overflow in successive_shortest_path_nonnegative_weights()
| Reported by: | Owned by: | Jeremiah Willcock | |
|---|---|---|---|
| Milestone: | To Be Determined | Component: | graph | 
| Version: | Boost Development Trunk | Severity: | Problem | 
| Keywords: | Cc: | 
Description
Buiding and running the following program with UndefinedBehaviorSanitizer will generate a report on signed integer overflow error:
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/read_dimacs.hpp>
#include <boost/graph/successive_shortest_path_nonnegative_weights.hpp>
#include <iostream>
using namespace boost;
using Traits = adjacency_list_traits<vecS, vecS, directedS>;
using Graph = adjacency_list<
    vecS, vecS, directedS, no_property,
    property<edge_capacity_t, int,
             property<edge_residual_capacity_t, int,
                      property<edge_reverse_t, Traits::edge_descriptor,
                               property<edge_weight_t, int>>>>>;
template <typename Map, typename Edge>
void fill_capacity(Map &m, Edge e, Edge er, int c) {
  put(m, e, c);
  put(m, er, 0);
}
template <typename Map, typename Edge> void fill_rev(Map &m, Edge e, Edge er) {
  put(m, e, er);
  put(m, er, e);
}
template <typename Map, typename Edge>
void fill_weight(Map &m, Edge e, Edge er, int w) {
  put(m, e, w);
  put(m, er, -w);
}
int main() {
  Graph g(4);
  auto capacity = get(edge_capacity, g);
  auto rev = get(edge_reverse, g);
  auto weight = get(edge_weight, g);
  auto e0 = add_edge(0, 1, g).first;
  auto e0r = add_edge(1, 0, g).first;
  auto e1 = add_edge(0, 2, g).first;
  auto e1r = add_edge(2, 0, g).first;
  auto e2 = add_edge(1, 2, g).first;
  auto e2r = add_edge(2, 1, g).first;
  // What the weights and capacities are don't really matter as long as they are all positive
  fill_capacity(capacity, e0, e0r, 1);
  fill_capacity(capacity, e1, e1r, 1);
  fill_capacity(capacity, e2, e2r, 1);
  fill_rev(rev, e0, e0r);
  fill_rev(rev, e1, e1r);
  fill_rev(rev, e2, e2r);
  fill_weight(weight, e0, e0r, 1);
  fill_weight(weight, e1, e1r, 1);
  fill_weight(weight, e2, e2r, 1);
  successive_shortest_path_nonnegative_weights(g, 0, 2);
}
Here's the stacktrace collected by UBSan (simplified for readability):
/usr/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp:104:57: runtime error: signed integer overflow: 2147483647 + 2147483647 cannot be represented in type 'int'
    #0 0x43fccd in void boost::successive_shortest_path_nonnegative_weights<...>(...) /usr/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp:104:57
    #1 0x43d7dc in void boost::detail::successive_shortest_path_nonnegative_weights_dispatch3<...>(...) /usr/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp:148:5
    #2 0x43bf40 in void boost::detail::successive_shortest_path_nonnegative_weights_dispatch2<...>(...) /usr/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp:186:5
    #3 0x43b2ba in void boost::detail::successive_shortest_path_nonnegative_weights_dispatch1<...>(...) /usr/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp:223:5
    #4 0x43b018 in void boost::successive_shortest_path_nonnegative_weights<boost::adjacency_list<...>, int, boost::buffer_param_t, boost::no_property>(...) /usr/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp:238:12
    #5 0x42b046 in void boost::successive_shortest_path_nonnegative_weights<...>(boost::adjacency_list<...>&, boost::graph_traits<...>::vertex_descriptor, boost::graph_traits<...>::vertex_descriptor) /usr/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp:255:5
    #6 0x42a520 in main /home/grieve/Research/Testing/boost/reduced.cpp:56:3
    #7 0x7f7cb22e3f69 in __libc_start_main (/usr/lib/libc.so.6+0x20f69)
    #8 0x4039b9 in _start (/home/grieve/Research/Testing/boost/reduced+0x4039b9)
The problem here is that function successive_shortest_path_nonnegative_weights() does not take into account the fact that its input graph might be disconnected and therefore it is possible for some shortest path distances to be infinity.
  Note:
 See   TracTickets
 for help on using tickets.
    