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;
236
237 SuccessOrExit(error = ReadIp6Address(ipv6AddrPtr));
238 aIp6Addr = *ipv6AddrPtr;
239
240 exit:
241 return error;
242 }
243
ReadIp6Address(otIp6Address & aIp6Addr)244 otError Decoder::ReadIp6Address(otIp6Address &aIp6Addr)
245 {
246 otError error = OT_ERROR_NONE;
247 const otIp6Address *ipv6AddrPtr;
248
249 SuccessOrExit(error = ReadIp6Address(ipv6AddrPtr));
250 aIp6Addr = *ipv6AddrPtr;
251
252 exit:
253 return error;
254 }
255
ReadEui64(spinel_eui64_t & aEui64)256 otError Decoder::ReadEui64(spinel_eui64_t &aEui64)
257 {
258 otError error = OT_ERROR_NONE;
259 const spinel_eui64_t *eui64Ptr;
260
261 SuccessOrExit(error = ReadEui64(eui64Ptr));
262 aEui64 = *eui64Ptr;
263
264 exit:
265 return error;
266 }
267
ReadEui64(otExtAddress & aEui64)268 otError Decoder::ReadEui64(otExtAddress &aEui64)
269 {
270 otError error = OT_ERROR_NONE;
271 const otExtAddress *eui64Ptr;
272
273 SuccessOrExit(error = ReadEui64(eui64Ptr));
274 aEui64 = *eui64Ptr;
275
276 exit:
277 return error;
278 }
279
ReadEui48(spinel_eui48_t & aEui48)280 otError Decoder::ReadEui48(spinel_eui48_t &aEui48)
281 {
282 otError error = OT_ERROR_NONE;
283 const spinel_eui48_t *eui48Ptr;
284
285 SuccessOrExit(error = ReadEui48(eui48Ptr));
286 aEui48 = *eui48Ptr;
287
288 exit:
289 return error;
290 }
291
ReadUtf8(const char * & aUtf8)292 otError Decoder::ReadUtf8(const char *&aUtf8)
293 {
294 otError error = OT_ERROR_NONE;
295 size_t len;
296
297 // Ensure there is at least one byte (for null character).
298 VerifyOrExit(mIndex + sizeof(uint8_t) <= mEnd, error = OT_ERROR_PARSE);
299
300 len = StringLength(reinterpret_cast<const char *>(&mFrame[mIndex]), mEnd - mIndex);
301 VerifyOrExit(len < static_cast<uint16_t>(mEnd - mIndex), error = OT_ERROR_PARSE);
302
303 aUtf8 = reinterpret_cast<const char *>(&mFrame[mIndex]);
304
305 // `sizeof(uint8_t)` is added for the terminating null character.
306 mIndex += static_cast<uint16_t>(len + sizeof(uint8_t));
307
308 exit:
309 return error;
310 }
311
ReadData(const uint8_t * & aData,uint16_t & aDataLen)312 otError Decoder::ReadData(const uint8_t *&aData, uint16_t &aDataLen)
313 {
314 aDataLen = mEnd - mIndex;
315
316 return ReadItem(&aData, aDataLen);
317 }
318
ReadDataWithLen(const uint8_t * & aData,uint16_t & aDataLen)319 otError Decoder::ReadDataWithLen(const uint8_t *&aData, uint16_t &aDataLen)
320 {
321 otError error = OT_ERROR_NONE;
322 uint16_t len;
323
324 SuccessOrExit(error = ReadUint16(len));
325 SuccessOrExit(error = ReadItem(&aData, len));
326 aDataLen = len;
327
328 exit:
329 return error;
330 }
331
OpenStruct(void)332 otError Decoder::OpenStruct(void)
333 {
334 otError error = OT_ERROR_NONE;
335 uint16_t structLen;
336
337 VerifyOrExit(mNumOpenStructs < kMaxNestedStructs, error = OT_ERROR_INVALID_STATE);
338
339 SuccessOrExit(error = ReadUint16(structLen));
340 VerifyOrExit(structLen <= mEnd - mIndex, error = OT_ERROR_PARSE);
341
342 mPrevEnd[mNumOpenStructs] = mEnd;
343 mEnd = (mIndex + structLen);
344 mNumOpenStructs++;
345
346 exit:
347 return error;
348 }
349
CloseStruct(void)350 otError Decoder::CloseStruct(void)
351 {
352 otError error = OT_ERROR_NONE;
353
354 VerifyOrExit(mNumOpenStructs > 0, error = OT_ERROR_INVALID_STATE);
355
356 // If there is a saved position and it is contained
357 // within the current struct being closed, the saved
358 // position is cleared to ensure user cannot go back
359 // to middle of an already closed struct.
360
361 if (IsSavedPositionValid() && (mNumOpenStructs == mSavedNumOpenStructs))
362 {
363 ClearSavedPosition();
364 }
365
366 mNumOpenStructs--;
367 mIndex = mEnd;
368 mEnd = mPrevEnd[mNumOpenStructs];
369
370 exit:
371 return error;
372 }
373
SavePosition(void)374 void Decoder::SavePosition(void)
375 {
376 mSavedIndex = mIndex;
377 mSavedEnd = mEnd;
378 mSavedNumOpenStructs = mNumOpenStructs;
379 }
380
ResetToSaved(void)381 otError Decoder::ResetToSaved(void)
382 {
383 otError error = OT_ERROR_NONE;
384
385 VerifyOrExit(IsSavedPositionValid(), error = OT_ERROR_INVALID_STATE);
386
387 mIndex = mSavedIndex;
388 mEnd = mSavedEnd;
389 mNumOpenStructs = mSavedNumOpenStructs;
390
391 exit:
392 return error;
393 }
394
395 } // namespace Spinel
396 } // namespace ot
397