Fix multiply-with-overflow panic in router
authorMatt Corallo <git@bluematt.me>
Tue, 14 Aug 2018 14:34:20 +0000 (10:34 -0400)
committerMatt Corallo <git@bluematt.me>
Fri, 17 Aug 2018 00:51:50 +0000 (20:51 -0400)
Found by fuzzer

src/ln/router.rs

index 229682bd03a837479e0e38bff61fc39eb3ec04d7..22eba189d9e6bd4f3cbefaee4f2dae5c127db664 100644 (file)
@@ -440,8 +440,8 @@ impl Router {
                                                let old_entry = hm_entry.or_insert_with(|| {
                                                        let node = network.nodes.get(&$directional_info.src_node_id).unwrap();
                                                        (u64::max_value(),
-                                                               node.lowest_inbound_channel_fee_base_msat as u64,
-                                                               node.lowest_inbound_channel_fee_proportional_millionths as u64,
+                                                               node.lowest_inbound_channel_fee_base_msat,
+                                                               node.lowest_inbound_channel_fee_proportional_millionths,
                                                                RouteHop {
                                                                        pubkey: PublicKey::new(),
                                                                        short_channel_id: 0,
@@ -453,7 +453,12 @@ impl Router {
                                                        // Ignore new_fee for channel-from-us as we assume all channels-from-us
                                                        // will have the same effective-fee
                                                        total_fee += new_fee;
-                                                       total_fee += old_entry.2 * (final_value_msat + total_fee) / 1000000 + old_entry.1;
+                                                       if let Some(fee_inc) = final_value_msat.checked_add(total_fee).and_then(|inc| { (old_entry.2 as u64).checked_mul(inc) }) {
+                                                               total_fee += fee_inc / 1000000 + (old_entry.1 as u64);
+                                                       } else {
+                                                               // max_value means we'll always fail the old_entry.0 > total_fee check
+                                                               total_fee = u64::max_value();
+                                                       }
                                                }
                                                let new_graph_node = RouteGraphNode {
                                                        pubkey: $directional_info.src_node_id,