• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ska-sa / spead2 / 5736993912

pending completion
5736993912

push

github

bmerry
Manually eliminate some calls to str.format

5405 of 7212 relevant lines covered (74.94%)

53446.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.15
/src/recv_packet.cpp
1
/* Copyright 2015 National Research Foundation (SARAO)
2
 *
3
 * This program is free software: you can redistribute it and/or modify it under
4
 * the terms of the GNU Lesser General Public License as published by the Free
5
 * Software Foundation, either version 3 of the License, or (at your option) any
6
 * later version.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
11
 * details.
12
 *
13
 * You should have received a copy of the GNU Lesser General Public License
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 */
16

17
/**
18
 * @file
19
 */
20

21
#include <cassert>
22
#include <cstring>
23
#include <spead2/recv_packet.h>
24
#include <spead2/recv_utils.h>
25
#include <spead2/common_defines.h>
26
#include <spead2/common_logging.h>
27
#include <spead2/common_endian.h>
28

29
namespace spead2
30
{
31
namespace recv
32
{
33

34
/**
35
 * Retrieve bits [first, first+cnt) from a field.
36
 *
37
 * @pre 0 &lt;= @a first &lt; @a first + @a cnt &lt;= @a n and @a cnt &lt; @a n,
38
 * where @a n is the number of bits in T.
39
 */
40
template<typename T>
41
static inline T extract_bits(T value, int first, int cnt)
99,980✔
42
{
43
    assert(0 <= first && first + cnt <= 8 * sizeof(T));
284✔
44
    assert(cnt > 0 && cnt < 8 * sizeof(T));
284✔
45
    return (value >> first) & ((T(1) << cnt) - 1);
99,980✔
46
}
47

48
static bool decode_header(const uint8_t *data, int &heap_address_bits, int &n_items)
25,008✔
49
{
50
    std::uint64_t header = load_be<std::uint64_t>(data);
25,008✔
51
    if (extract_bits(header, 48, 16) != magic_version)
25,006✔
52
    {
53
        log_info("packet rejected because magic or version did not match");
1✔
54
        return false;
1✔
55
    }
56
    int item_id_bits = extract_bits(header, 40, 8) * 8;
24,998✔
57
    heap_address_bits = extract_bits(header, 32, 8) * 8;
24,995✔
58
    if (item_id_bits == 0 || heap_address_bits == 0)
24,997✔
59
    {
60
        log_info("packet rejected because flavour is invalid");
×
61
        return false;
×
62
    }
63
    if (item_id_bits + heap_address_bits != 8 * sizeof(item_pointer_t))
24,997✔
64
    {
65
        log_info("packet rejected because flavour is not SPEAD-64-*");
×
66
        return false;
×
67
    }
68

69
    n_items = extract_bits(header, 0, 16);
24,997✔
70
    return true;
24,991✔
71
}
72

73
s_item_pointer_t get_packet_size(const uint8_t *data, std::size_t length)
702✔
74
{
75
    if (length < 8)
702✔
76
        return 0;
1✔
77
    int heap_address_bits, n_items;
78
    if (!decode_header(data, heap_address_bits, n_items))
701✔
79
        return -1;
1✔
80
    if (std::size_t(n_items) * sizeof(item_pointer_t) + 8 > length)
700✔
81
        return 0;
1✔
82

83
    pointer_decoder decoder(heap_address_bits);
699✔
84
    s_item_pointer_t payload_length = -1;
699✔
85
    for (int i = 0; i < n_items; i++)
2,792✔
86
    {
87
        item_pointer_t pointer = load_be<item_pointer_t>(data + 8 + i * sizeof(item_pointer_t));
2,792✔
88
        if (decoder.is_immediate(pointer) && decoder.get_id(pointer) == PAYLOAD_LENGTH_ID)
2,792✔
89
        {
90
            payload_length = decoder.get_immediate(pointer);
699✔
91
            break;
699✔
92
        }
93
    }
94
    if (payload_length == -1)
699✔
95
        return -1;
×
96
    return payload_length + n_items * sizeof(item_pointer_t) + 8;
699✔
97
}
98

99
std::size_t decode_packet(packet_header &out, const uint8_t *data, std::size_t max_size)
24,318✔
100
{
101
    if (max_size < 8)
24,318✔
102
    {
103
        log_info("packet rejected because too small (%d bytes)", max_size);
×
104
        return 0;
×
105
    }
106
    if (!decode_header(data, out.heap_address_bits, out.n_items))
24,318✔
107
        return 0;
×
108
    if (std::size_t(out.n_items) * sizeof(item_pointer_t) + 8 > max_size)
24,291✔
109
    {
110
        log_info("packet rejected because the items overflow the packet");
×
111
        return 0;
×
112
    }
113

114
    // Mark specials as not found
115
    out.heap_cnt = -1;
24,291✔
116
    out.heap_length = -1;
24,291✔
117
    out.payload_offset = -1;
24,291✔
118
    out.payload_length = -1;
24,291✔
119
    // Look for special items
120
    pointer_decoder decoder(out.heap_address_bits);
24,291✔
121
    int first_regular = out.n_items;
24,291✔
122
    for (int i = 0; i < out.n_items; i++)
137,833✔
123
    {
124
        item_pointer_t pointer = load_be<item_pointer_t>(data + 8 + i * sizeof(item_pointer_t));
113,475✔
125
        bool special;
126
        if (decoder.is_immediate(pointer))
113,484✔
127
        {
128
            special = true;
103,155✔
129
            switch (decoder.get_id(pointer))
103,155✔
130
            {
131
            case HEAP_CNT_ID:
24,296✔
132
                out.heap_cnt = decoder.get_immediate(pointer);
24,296✔
133
                break;
24,295✔
134
            case HEAP_LENGTH_ID:
24,292✔
135
                out.heap_length = decoder.get_immediate(pointer);
24,292✔
136
                break;
24,291✔
137
            case PAYLOAD_OFFSET_ID:
24,295✔
138
                out.payload_offset = decoder.get_immediate(pointer);
24,295✔
139
                break;
24,294✔
140
            case PAYLOAD_LENGTH_ID:
24,229✔
141
                out.payload_length = decoder.get_immediate(pointer);
24,229✔
142
                break;
24,294✔
143
            default:
6,045✔
144
                special = false;
6,045✔
145
                break;
6,045✔
146
            }
147
        }
148
        else
149
            special = false;
10,323✔
150
        if (!special)
113,542✔
151
            first_regular = std::min(first_regular, i);
16,368✔
152
    }
153
    if (out.heap_cnt == -1 || out.payload_offset == -1 || out.payload_length == -1)
24,358✔
154
    {
155
        log_info("packet rejected because it does not have required items");
63✔
156
        return 0;
×
157
    }
158
    std::size_t size = out.payload_length + out.n_items * sizeof(item_pointer_t) + 8;
24,295✔
159
    if (size > max_size)
24,295✔
160
    {
161
        log_info("packet rejected because payload length overflows packet size (%d > %d)",
×
162
                  size, max_size);
163
        return 0;
×
164
    }
165
    if (out.heap_length >= 0 && out.payload_offset + out.payload_length > out.heap_length)
24,295✔
166
    {
167
        log_info("packet rejected because payload would overflow given heap length");
×
168
        return 0;
×
169
    }
170

171
    // Adjust the pointers to skip the specials, since live_heap::add_packet does not
172
    // need them
173
    out.pointers = data + 8 + first_regular * sizeof(item_pointer_t);
24,295✔
174
    out.n_items -= first_regular;
24,295✔
175
    out.payload = out.pointers + out.n_items * sizeof(item_pointer_t);
24,295✔
176
    out.packet = data;
24,295✔
177
    return size;
24,295✔
178
}
179

180
} // namespace recv
181
} // namespace spead2
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc