1 /*
2 * Copyright (c) 2017, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /**
29 * @file
30 * This file implements a spinel decoder.
31 */
32
33 #include "spinel_decoder.hpp"
34
35 #include "common/code_utils.hpp"
36 #include "common/string.hpp"
37
38 namespace ot {
39 namespace Spinel {
40
Decoder(void)41 Decoder::Decoder(void)
42 : mFrame(nullptr)
43 , mLength(0)
44 , mIndex(0)
45 , mEnd(0)
46 , mNumOpenStructs(0)
47 , mSavedNumOpenStructs(0)
48 , mSavedIndex(0)
49 , mSavedEnd(0)
50 {
51 }
52
Init(const uint8_t * aFrame,uint16_t aLength)53 void Decoder::Init(const uint8_t *aFrame, uint16_t aLength)
54 {
55 mFrame = aFrame;
56 mLength = (mFrame != nullptr) ? aLength : 0;
57
58 Reset();
59 ClearSavedPosition();
60 }
61
Reset(void)62 void Decoder::Reset(void)
63 {
64 mIndex = 0;
65 mEnd = mLength;
66 mNumOpenStructs = 0;
67 ClearSavedPosition();
68 }
69
ReadBool(bool & aBool)70 otError Decoder::ReadBool(bool &aBool)
71 {
72 otError error = OT_ERROR_NONE;
73 uint8_t byte;
74
75 SuccessOrExit(error = ReadUint8(byte));
76
77 // Boolean value are encoded in 8-bits as either 0x00 or 0x01. All other values are illegal.
78 if (byte == 0x00)
79 {
80 aBool = false;
81 }
82 else if (byte == 0x01)
83 {
84 aBool = true;
85 }
86 else
87 {
88 error = OT_ERROR_PARSE;
89 }
90
91 exit:
92 return error;
93 }
94
ReadUint8(uint8_t & aUint8)95 otError Decoder::ReadUint8(uint8_t &aUint8)
96 {
97 otError error = OT_ERROR_NONE;
98
99 VerifyOrExit(mIndex + sizeof(uint8_t) <= mEnd, error = OT_ERROR_PARSE);
100 aUint8 = mFrame[mIndex];
101 mIndex += sizeof(uint8_t);
102
103 exit:
104 return error;
105 }
106
ReadInt8(int8_t & aInt8)107 otError Decoder::ReadInt8(int8_t &aInt8)
108 {
109 otError error = OT_ERROR_NONE;
110 uint8_t byte;
111
112 SuccessOrExit(error = ReadUint8(byte));
113 aInt8 = static_cast<int8_t>(byte);
114
115 exit:
116 return error;
117 }
118
ReadUint16(uint16_t & aUint16)119 otError Decoder::ReadUint16(uint16_t &aUint16)
120 {
121 otError error = OT_ERROR_NONE;
122
123 VerifyOrExit(mIndex + sizeof(uint16_t) <= mEnd, error = OT_ERROR_PARSE);
124
125 aUint16 = static_cast<uint16_t>(mFrame[mIndex] | (mFrame[mIndex + 1] << 8));
126
127 mIndex += sizeof(uint16_t);
128
129 exit:
130 return error;
131 }
132
ReadInt16(int16_t & aInt16)133 otError Decoder::ReadInt16(int16_t &aInt16)
134 {
135 otError error = OT_ERROR_NONE;
136 uint16_t u16;
137
138 SuccessOrExit(error = ReadUint16(u16));
139 aInt16 = static_cast<int16_t>(u16);
140
141 exit:
142 return error;
143 }
144
ReadUint32(uint32_t & aUint32)145 otError Decoder::ReadUint32(uint32_t &aUint32)
146 {
147 otError error = OT_ERROR_NONE;
148
149 VerifyOrExit(mIndex + sizeof(uint32_t) <= mEnd, error = OT_ERROR_PARSE);
150
151 aUint32 = ((static_cast<uint32_t>(mFrame[mIndex + 0]) << 0) | (static_cast<uint32_t>(mFrame[mIndex + 1]) << 8) |
152 (static_cast<uint32_t>(mFrame[mIndex + 2]) << 16) | (static_cast<uint32_t>(mFrame[mIndex + 3]) << 24));
153
154 mIndex += sizeof(uint32_t);
155
156 exit:
157 return error;
158 }
159
ReadInt32(int32_t & aInt32)160 otError Decoder::ReadInt32(int32_t &aInt32)
161 {
162 otError error = OT_ERROR_NONE;
163 uint32_t u32;
164
165 SuccessOrExit(error = ReadUint32(u32));
166 aInt32 = static_cast<int32_t>(u32);
167
168 exit:
169 return error;
170 }
171
ReadUint64(uint64_t & aUint64)172 otError Decoder::ReadUint64(uint64_t &aUint64)
173 {
174 otError error = OT_ERROR_NONE;
175
176 VerifyOrExit(mIndex + sizeof(uint64_t) <= mEnd, error = OT_ERROR_PARSE);
177
178 aUint64 = ((static_cast<uint64_t>(mFrame[mIndex + 0]) << 0) | (static_cast<uint64_t>(mFrame[mIndex + 1]) << 8) |
179 (static_cast<uint64_t>(mFrame[mIndex + 2]) << 16) | (static_cast<uint64_t>(mFrame[mIndex + 3]) << 24) |
180 (static_cast<uint64_t>(mFrame[mIndex + 4]) << 32) | (static_cast<uint64_t>(mFrame[mIndex + 5]) << 40) |
181 (static_cast<uint64_t>(mFrame[mIndex + 6]) << 48) | (static_cast<uint64_t>(mFrame[mIndex + 7]) << 56));
182
183 mIndex += sizeof(uint64_t);
184
185 exit:
186 return error;
187 }
188
ReadInt64(int64_t & aInt64)189 otError Decoder::ReadInt64(int64_t &aInt64)
190 {
191 otError error = OT_ERROR_NONE;
192 uint64_t u64;
193
194 SuccessOrExit(error = ReadUint64(u64));
195 aInt64 = static_cast<int64_t>(u64);
196
197 exit:
198 return error;
199 }
200
ReadUintPacked(unsigned int & aUint)201 otError Decoder::ReadUintPacked(unsigned int &aUint)
202 {
203 otError error = OT_ERROR_NONE;
204 spinel_ssize_t parsedLen;
205 unsigned int uint;
206
207 parsedLen = spinel_packed_uint_decode(&mFrame[mIndex], mEnd - mIndex, &uint);
208 VerifyOrExit(parsedLen > 0, error = OT_ERROR_PARSE);
209
210 mIndex += parsedLen;
211 aUint = uint;
212
213 exit:
214 return error;
215 }
216
217 // Reads an item of given size and updates the pointer `aPtr`.
ReadItem(const uint8_t ** aPtr,uint16_t aSize)218 otError Decoder::ReadItem(const uint8_t **aPtr, uint16_t aSize)
219 {
220 otError error = OT_ERROR_NONE;
221
222 VerifyOrExit(mIndex + aSize <= mEnd, error = OT_ERROR_PARSE);
223
224 *aPtr = &mFrame[mIndex];
225
226 mIndex += aSize;
227
228 exit:
229 return error;
230 }
231
ReadIp6Address(spinel_ipv6addr_t & aIp6Addr)232 otError Decoder::ReadIp6Address(spinel_ipv6addr_t &aIp6Addr)
233 {
234 otError error = OT_ERROR_NONE;
235 const spinel_ipv6addr_t *ipv6AddrPtr = nullptr;
236
237 SuccessOrExit(error = ReadIp6Address(ipv6AddrPtr));
238 VerifyOrExit(ipv6AddrPtr != nullptr, error = OT_ERROR_PARSE);
239 aIp6Addr = *ipv6AddrPtr;
240
241 exit:
242 return error;
243 }
244
ReadIp6Address(otIp6Address & aIp6Addr)245 otError Decoder::ReadIp6Address(otIp6Address &aIp6Addr)
246 {
247 otError error = OT_ERROR_NONE;
248 const otIp6Address *ipv6AddrPtr = nullptr;
249
250 SuccessOrExit(error = ReadIp6Address(ipv6AddrPtr));
251 VerifyOrExit(ipv6AddrPtr != nullptr, error = OT_ERROR_PARSE);
252 aIp6Addr = *ipv6AddrPtr;
253
254 exit:
255 return error;
256 }
257
ReadEui64(spinel_eui64_t & aEui64)258 otError Decoder::ReadEui64(spinel_eui64_t &aEui64)
259 {
260 otError error = OT_ERROR_NONE;
261 const spinel_eui64_t *eui64Ptr = nullptr;
262
263 SuccessOrExit(error = ReadEui64(eui64Ptr));
264 VerifyOrExit(eui64Ptr != nullptr, error = OT_ERROR_PARSE);
265 aEui64 = *eui64Ptr;
266
267 exit:
268 return error;
269 }
270
ReadEui64(otExtAddress & aEui64)271 otError Decoder::ReadEui64(otExtAddress &aEui64)
272 {
273 otError error = OT_ERROR_NONE;
274 const otExtAddress *eui64Ptr = nullptr;
275
276 SuccessOrExit(error = ReadEui64(eui64Ptr));
277 VerifyOrExit(eui64Ptr != nullptr, error = OT_ERROR_PARSE);
278 aEui64 = *eui64Ptr;
279
280 exit:
281 return error;
282 }
283
ReadEui48(spinel_eui48_t & aEui48)284 otError Decoder::ReadEui48(spinel_eui48_t &aEui48)
285 {
286 otError error = OT_ERROR_NONE;
287 const spinel_eui48_t *eui48Ptr = nullptr;
288
289 SuccessOrExit(error = ReadEui48(eui48Ptr));
290 VerifyOrExit(eui48Ptr != nullptr, error = OT_ERROR_PARSE);
291 aEui48 = *eui48Ptr;
292
293 exit:
294 return error;
295 }
296
ReadUtf8(const char * & aUtf8)297 otError Decoder::ReadUtf8(const char *&aUtf8)
298 {
299 otError error = OT_ERROR_NONE;
300 size_t len;
301
302 // Ensure there is at least one byte (for null character).
303 VerifyOrExit(mIndex + sizeof(uint8_t) <= mEnd, error = OT_ERROR_PARSE);
304
305 len = StringLength(reinterpret_cast<const char *>(&mFrame[mIndex]), mEnd - mIndex);
306 VerifyOrExit(len < static_cast<uint16_t>(mEnd - mIndex), error = OT_ERROR_PARSE);
307
308 aUtf8 = reinterpret_cast<const char *>(&mFrame[mIndex]);
309
310 // `sizeof(uint8_t)` is added for the terminating null character.
311 mIndex += static_cast<uint16_t>(len + sizeof(uint8_t));
312
313 exit:
314 return error;
315 }
316
ReadData(const uint8_t * & aData,uint16_t & aDataLen)317 otError Decoder::ReadData(const uint8_t *&aData, uint16_t &aDataLen)
318 {
319 aDataLen = mEnd - mIndex;
320
321 return ReadItem(&aData, aDataLen);
322 }
323
ReadDataWithLen(const uint8_t * & aData,uint16_t & aDataLen)324 otError Decoder::ReadDataWithLen(const uint8_t *&aData, uint16_t &aDataLen)
325 {
326 otError error = OT_ERROR_NONE;
327 uint16_t len;
328
329 SuccessOrExit(error = ReadUint16(len));
330 SuccessOrExit(error = ReadItem(&aData, len));
331 aDataLen = len;
332
333 exit:
334 return error;
335 }
336
OpenStruct(void)337 otError Decoder::OpenStruct(void)
338 {
339 otError error = OT_ERROR_NONE;
340 uint16_t structLen;
341
342 VerifyOrExit(mNumOpenStructs < kMaxNestedStructs, error = OT_ERROR_INVALID_STATE);
343
344 SuccessOrExit(error = ReadUint16(structLen));
345 VerifyOrExit(structLen <= mEnd - mIndex, error = OT_ERROR_PARSE);
346
347 mPrevEnd[mNumOpenStructs] = mEnd;
348 mEnd = (mIndex + structLen);
349 mNumOpenStructs++;
350
351 exit:
352 return error;
353 }
354
CloseStruct(void)355 otError Decoder::CloseStruct(void)
356 {
357 otError error = OT_ERROR_NONE;
358
359 VerifyOrExit(mNumOpenStructs > 0, error = OT_ERROR_INVALID_STATE);
360
361 // If there is a saved position and it is contained
362 // within the current struct being closed, the saved
363 // position is cleared to ensure user cannot go back
364 // to middle of an already closed struct.
365
366 if (IsSavedPositionValid() && (mNumOpenStructs == mSavedNumOpenStructs))
367 {
368 ClearSavedPosition();
369 }
370
371 mNumOpenStructs--;
372 mIndex = mEnd;
373 mEnd = mPrevEnd[mNumOpenStructs];
374
375 exit:
376 return error;
377 }
378
SavePosition(void)379 void Decoder::SavePosition(void)
380 {
381 mSavedIndex = mIndex;
382 mSavedEnd = mEnd;
383 mSavedNumOpenStructs = mNumOpenStructs;
384 }
385
ResetToSaved(void)386 otError Decoder::ResetToSaved(void)
387 {
388 otError error = OT_ERROR_NONE;
389
390 VerifyOrExit(IsSavedPositionValid(), error = OT_ERROR_INVALID_STATE);
391
392 mIndex = mSavedIndex;
393 mEnd = mSavedEnd;
394 mNumOpenStructs = mSavedNumOpenStructs;
395
396 exit:
397 return error;
398 }
399
400 } // namespace Spinel
401 } // namespace ot
402