Returns false only if must_be_clean is true. */
| 813 | |
| 814 | /* Returns false only if must_be_clean is true. */ |
| 815 | static bool map_catchup(struct gossmap *map, |
| 816 | void (*dyingcb)(struct short_channel_id scid, |
| 817 | u32 blockheight, |
| 818 | u64 offset, |
| 819 | void *cb_arg), |
| 820 | void *cb_arg, |
| 821 | bool must_be_clean, |
| 822 | bool *changed) |
| 823 | { |
| 824 | size_t reclen, num_bad_cupdates = 0; |
| 825 | |
| 826 | *changed = false; |
| 827 | |
| 828 | for (; map->map_end + sizeof(struct gossip_hdr) < map->map_size; |
| 829 | map->map_end += reclen) { |
| 830 | struct gossip_hdr ghdr; |
| 831 | u64 off; |
| 832 | u16 msglen, type, flags; |
| 833 | |
| 834 | map_copy(map, map->map_end, &ghdr, sizeof(ghdr)); |
| 835 | msglen = be16_to_cpu(ghdr.len); |
| 836 | reclen = msglen + sizeof(ghdr); |
| 837 | |
| 838 | flags = be16_to_cpu(ghdr.flags); |
| 839 | |
| 840 | /* Not finished, this can happen. */ |
| 841 | if (!(flags & GOSSIP_STORE_COMPLETED_BIT)) |
| 842 | break; |
| 843 | |
| 844 | if (flags & GOSSIP_STORE_DELETED_BIT) { |
| 845 | map->num_dead++; |
| 846 | continue; |
| 847 | } |
| 848 | |
| 849 | /* Partial write, should not happen with completed records. */ |
| 850 | if (map->map_end + reclen > map->map_size) |
| 851 | break; |
| 852 | |
| 853 | /* FIXME: In corruption, we can see zeroes here: don't crash. */ |
| 854 | if (msglen < sizeof(be16)) { |
| 855 | map->logcb(map->cbarg, |
| 856 | LOG_BROKEN, |
| 857 | "Truncated gossmap record @%"PRIu64 |
| 858 | "/%"PRIu64" (len %zu): waiting%s", |
| 859 | map->map_end, map->map_size, msglen, |
| 860 | gossmap_has_mmap(map) ? " and disabling mmap" : ""); |
| 861 | gossmap_disable_mmap(map); |
| 862 | if (must_be_clean) |
| 863 | return false; |
| 864 | break; |
| 865 | } |
| 866 | |
| 867 | off = map->map_end + sizeof(ghdr); |
| 868 | type = map_be16(map, off); |
| 869 | |
| 870 | if (!csum_matches(map, off, |
| 871 | be32_to_cpu(ghdr.timestamp), |
| 872 | msglen, |
no test coverage detected