source: ntrip/trunk/BNC/tests/tools/ssr_harness.cpp

Last change on this file was 11130, checked in by stuerze, 9 days ago

Some fixes from security point of view

File size: 7.0 KB
Line 
1// SSR decoder harness for AddressSanitizer/UBSan runs (see ssr_harness.sh).
2//
3// Decodes every CRC-valid RTCM3 frame of a file with each of the three SSR
4// format classes (SsrCorrIgs, SsrCorrRtcm, SsrCorrRtcmNew). Unlike in BNC,
5// where all target structs are members of one RTCM3coDecoder object, every
6// struct is a separate heap block here, so a write beyond a struct is
7// reported by AddressSanitizer instead of silently corrupting the next member.
8//
9// Every decoded VTEC (all formats), metadata and satellite antenna message
10// (new RTCM-SSR) is encoded again with the Make* function of the same class
11// and decoded once more; the result must be identical, for the antenna
12// messages also the bytes of the frame (exit code 1 otherwise).
13//
14// Usage: ssr_harness <file> (BNC raw file or plain RTCM3 byte stream)
15
16#include <cstdio>
17#include <vector>
18
19#include "clock_orbit_igs.h"
20#include "clock_orbit_rtcm.h"
21#include "clock_orbit_rtcm_new.h"
22
23using namespace std;
24
25// from bncutils.cpp, which would pull in most of BNC
26unsigned long CRC24(long size, const unsigned char *buf) {
27 unsigned long crc = 0;
28 while (size--) {
29 crc ^= (*buf++) << (16);
30 for (int ii = 0; ii < 8; ii++) {
31 crc <<= 1;
32 if (crc & 0x1000000) {
33 crc ^= 0x01864cfb;
34 }
35 }
36 }
37 return crc;
38}
39
40struct t_target {
41 t_target() : co(new SsrCorr::ClockOrbit()), cb(new SsrCorr::CodeBias()),
42 v(new SsrCorr::VTEC()), pb(new SsrCorr::PhaseBias()),
43 md(new SsrCorr::MetaData()), a(new SsrCorr::Antenna()) {}
44 ~t_target() {delete co; delete cb; delete v; delete pb; delete md; delete a;}
45 int decode(SsrCorr* ssr, const unsigned char* frame, size_t size) {
46 int bytesused = 0;
47 return ssr->GetSSR(co, cb, v, pb, md, a, (const char*)frame, size, &bytesused);
48 }
49 SsrCorr::ClockOrbit* co;
50 SsrCorr::CodeBias* cb;
51 SsrCorr::VTEC* v;
52 SsrCorr::PhaseBias* pb;
53 SsrCorr::MetaData* md;
54 SsrCorr::Antenna* a;
55};
56
57static bool sameVTEC(const SsrCorr::VTEC* v1, const SsrCorr::VTEC* v2) {
58 if (v1->EpochTime != v2->EpochTime || v1->NumLayers != v2->NumLayers ||
59 v1->Quality != v2->Quality) {
60 return false;
61 }
62 for (unsigned l = 0; l < v1->NumLayers; l++) {
63 const SsrCorr::VTEC::IonoLayers& l1 = v1->Layers[l];
64 const SsrCorr::VTEC::IonoLayers& l2 = v2->Layers[l];
65 if (l1.Height != l2.Height || l1.Degree != l2.Degree || l1.Order != l2.Order) {
66 return false;
67 }
68 for (unsigned d = 0; d <= l1.Degree; d++) {
69 for (unsigned o = 0; o <= l1.Order; o++) {
70 if (l1.Cosinus[d][o] != l2.Cosinus[d][o] || l1.Sinus[d][o] != l2.Sinus[d][o]) {
71 return false;
72 }
73 }
74 }
75 }
76 return true;
77}
78
79static bool sameMetaData(const SsrCorr::MetaData* m1, const SsrCorr::MetaData* m2) {
80 if (m1->SSRIOD != m2->SSRIOD || m1->SSRProviderID != m2->SSRProviderID ||
81 m1->SSRSolutionID != m2->SSRSolutionID || m1->NumEntries != m2->NumEntries) {
82 return false;
83 }
84 for (unsigned i = 0; i < m1->NumEntries; i++) {
85 if (memcmp(&m1->Entries[i], &m2->Entries[i], sizeof(m1->Entries[i])) != 0) {
86 return false;
87 }
88 }
89 return true;
90}
91
92static int nFailed = 0;
93
94// Decode, print a summary, encode the result again and compare
95static void decode(const char* name, SsrCorr* ssr, const unsigned char* frame, size_t size) {
96 t_target t1;
97 int irc = t1.decode(ssr, frame, size);
98 printf(" %-8s irc %3d", name, irc);
99 SsrCorrRtcmNew* rtcmNew = dynamic_cast<SsrCorrRtcmNew*>(ssr);
100 if (irc >= 0 && t1.v->NumLayers) {
101 double sum = 0.0;
102 printf(" VTEC");
103 for (unsigned l = 0; l < t1.v->NumLayers; l++) {
104 const SsrCorr::VTEC::IonoLayers& layer = t1.v->Layers[l];
105 printf(" %u/%u", layer.Degree, layer.Order);
106 for (unsigned d = 0; d <= layer.Degree; d++) {
107 for (unsigned o = 0; o <= layer.Order; o++) {
108 sum += layer.Cosinus[d][o] - layer.Sinus[d][o];
109 }
110 }
111 }
112 printf(" sum(C-S) %.3f", sum);
113
114 char buffer[CLOCKORBIT_BUFFERSIZE];
115 size_t len = ssr->MakeVTEC(t1.v, 0, buffer, sizeof(buffer));
116 t_target t2;
117 bool ok = len > 0 && t2.decode(ssr, (const unsigned char*)buffer, len) >= 0 && sameVTEC(t1.v, t2.v);
118 printf(" re-encoded: %s", ok ? "identical" : "DIFFERENT");
119 nFailed += !ok;
120 }
121 if (irc >= 0 && t1.md->NumEntries) {
122 printf(" META %u entries, additional data", t1.md->NumEntries);
123 for (unsigned i = 0; i < t1.md->NumEntries; i++) {
124 if (t1.md->Entries[i].additionalParameterIndicator) {
125 printf(" %u:0x%x", t1.md->Entries[i].additionalParameterNumBits,
126 t1.md->Entries[i].additionalParameterData);
127 }
128 }
129 if (rtcmNew) {
130 char buffer[CLOCKORBIT_BUFFERSIZE];
131 size_t len = rtcmNew->MakeMetaData(t1.md, buffer, sizeof(buffer));
132 t_target t2;
133 bool ok = len > 0 && t2.decode(ssr, (const unsigned char*)buffer, len) >= 0 && sameMetaData(t1.md, t2.md);
134 printf(" re-encoded: %s", ok ? "identical" : "DIFFERENT");
135 nFailed += !ok;
136 }
137 }
138 for (unsigned s = 0; rtcmNew && irc >= 0 && s < CLOCKORBIT_SATNUM; s++) {
139 if (!t1.a->SatelliteMask[s]) {
140 continue;
141 }
142 printf(" ANT type %u mask %016llx", t1.a->messageType[s],
143 (unsigned long long)t1.a->SatelliteMask[s]);
144 char buffer[CLOCKORBIT_BUFFERSIZE];
145 size_t len = rtcmNew->MakeAntenna(t1.a, t1.a->messageType[s], buffer, sizeof(buffer));
146 t_target t2;
147 bool sameBytes = len == size && memcmp(buffer, frame, size) == 0;
148 bool ok = len > 0 && t2.decode(ssr, (const unsigned char*)buffer, len) >= 0 &&
149 memcmp(t1.a, t2.a, sizeof(*t1.a)) == 0;
150 printf(" re-encoded: %s, %s", ok ? "identical" : "DIFFERENT",
151 sameBytes ? "same bytes" : "OTHER BYTES");
152 nFailed += !ok || !sameBytes;
153 }
154 printf("\n");
155}
156
157int main(int argc, char* argv[]) {
158 if (argc != 2) {
159 fprintf(stderr, "usage: %s <file>\n", argv[0]);
160 return 2;
161 }
162 FILE* inp = fopen(argv[1], "rb");
163 if (!inp) {
164 perror(argv[1]);
165 return 2;
166 }
167 vector<unsigned char> buf;
168 int c;
169 while ((c = fgetc(inp)) != EOF) {
170 buf.push_back((unsigned char)c);
171 }
172 fclose(inp);
173
174 SsrCorrIgs igs;
175 SsrCorrRtcm rtcm;
176 SsrCorrRtcmNew rtcmNew;
177
178 size_t ii = 0;
179 while (ii + 6 <= buf.size()) {
180 size_t len = ((buf[ii + 1] & 0x03) << 8) | buf[ii + 2];
181 if (buf[ii] != 0xD3 || ii + len + 6 > buf.size() ||
182 CRC24(len + 3, &buf[ii]) != (unsigned long)((buf[ii + len + 3] << 16) |
183 (buf[ii + len + 4] << 8) | buf[ii + len + 5])) {
184 ii++;
185 continue;
186 }
187 // exact-size copy, so reading beyond the frame is caught as well
188 vector<unsigned char> frame(buf.begin() + ii, buf.begin() + ii + len + 6);
189 int type = (frame[3] << 4) | (frame[4] >> 4);
190 printf("frame at %zu: type %d, %zu bytes\n", ii, type, len);
191 decode("IGS", &igs, frame.data(), frame.size());
192 decode("RTCM", &rtcm, frame.data(), frame.size());
193 decode("RTCMnew", &rtcmNew, frame.data(), frame.size());
194 ii += len + 6;
195 }
196 if (nFailed) {
197 printf("%d decoded messages differ after re-encoding\n", nFailed);
198 return 1;
199 }
200 return 0;
201}
Note: See TracBrowser for help on using the repository browser.