Opened 5 years ago

#13210 new Bugs

Signed integer overflow in successive_shortest_path_nonnegative_weights()

Reported by: grievejia@… 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.

Change History (0)

Note: See TracTickets for help on using tickets.