1 : /* -*- c++ -*- */
2 : /*
3 : * Copyright (c) 2013 The Native Client Authors. All rights reserved.
4 : * Use of this source code is governed by a BSD-style license that can be
5 : * found in the LICENSE file.
6 : */
7 :
8 : #include "native_client/src/shared/serialization/serialization.h"
9 :
10 : #include <stdio.h>
11 : #include <string.h>
12 :
13 : #include "native_client/src/shared/platform/nacl_check.h"
14 :
15 : namespace nacl {
16 :
17 : int const kInitialBufferSize = 256;
18 :
19 : SerializationBuffer::SerializationBuffer()
20 : : nbytes_(0)
21 : , in_use_(0)
22 51 : , read_ix_(0) {}
23 :
24 :
25 2 : SerializationBuffer::SerializationBuffer(uint8_t const *data_buffer,
26 2 : size_t nbytes)
27 : : nbytes_(0) // EnsureTotalSize will update
28 : , in_use_(nbytes)
29 2 : , read_ix_(0) {
30 1 : EnsureTotalSize(nbytes);
31 2 : memcpy(&buffer_[0], data_buffer, nbytes);
32 2 : }
33 :
34 2 : bool SerializationBuffer::Serialize(char const *cstr, size_t char_count) {
35 2 : if (char_count > ~(uint32_t) 0) {
36 0 : return false;
37 : }
38 2 : AddTag<char *>();
39 2 : AddVal(static_cast<uint32_t>(char_count));
40 842 : for (size_t ix = 0; ix < char_count; ++ix) {
41 419 : AddVal<uint8_t>(cstr[ix]);
42 419 : }
43 2 : return true;
44 2 : }
45 :
46 2 : bool SerializationBuffer::Serialize(char const *cstr) {
47 2 : size_t len = strlen(cstr) + 1; // The ASCII character NUL is included
48 2 : return Serialize(cstr, len);
49 : }
50 :
51 31 : bool SerializationBuffer::Serialize(std::string str) {
52 31 : size_t bytes = str.size();
53 31 : if (bytes > ~(uint32_t) 0) {
54 0 : return false;
55 : }
56 31 : AddTag<std::string>();
57 31 : AddVal(static_cast<uint32_t>(bytes));
58 1788 : for (size_t ix = 0; ix < bytes; ++ix) {
59 863 : AddVal<uint8_t>(str[ix]);
60 863 : }
61 31 : return true;
62 31 : }
63 :
64 3 : bool SerializationBuffer::Deserialize(char *cstr, size_t *buffer_size) {
65 3 : size_t orig = cur_read_pos();
66 3 : if (bytes_unread() < kTagBytes + SerializationTraits<uint32_t>::kBytes) {
67 0 : return false;
68 : }
69 3 : if (ReadTag() != SerializationTraits<char *>::kTag) {
70 0 : reset_read_pos(orig);
71 0 : return false;
72 : }
73 3 : uint32_t char_count;
74 3 : if (!GetUint32(&char_count)) {
75 0 : reset_read_pos(orig);
76 0 : return false;
77 : }
78 3 : if (char_count > *buffer_size) {
79 1 : *buffer_size = char_count;
80 1 : reset_read_pos(orig);
81 1 : return true; // true means check buffer_size!
82 : }
83 842 : for (size_t ix = 0; ix < char_count; ++ix) {
84 419 : uint8_t byte;
85 419 : if (!GetVal(&byte)) {
86 0 : reset_read_pos(orig);
87 0 : return false; // encoded data is garbled!
88 : }
89 419 : cstr[ix] = byte;
90 419 : }
91 2 : *buffer_size = char_count;
92 2 : return true;
93 3 : }
94 :
95 1 : bool SerializationBuffer::Deserialize(char **cstr_out) {
96 1 : size_t nbytes = 256;
97 1 : char *buffer = new char[nbytes];
98 :
99 1 : size_t used = nbytes;
100 1 : if (!Deserialize(buffer, &used)) {
101 0 : delete[] buffer;
102 0 : return false;
103 : }
104 1 : if (used > nbytes) {
105 2 : delete[] buffer;
106 1 : buffer = new char[used];
107 3 : CHECK(Deserialize(buffer, &used));
108 1 : }
109 1 : *cstr_out = buffer;
110 1 : return true;
111 1 : }
112 :
113 15 : bool SerializationBuffer::Deserialize(std::string *str) {
114 15 : size_t orig = cur_read_pos();
115 15 : if (bytes_unread() < kTagBytes + SerializationTraits<uint32_t>::kBytes) {
116 0 : return false;
117 : }
118 15 : if (ReadTag() != SerializationTraits<std::string>::kTag) {
119 0 : reset_read_pos(orig);
120 0 : return false;
121 : }
122 15 : uint32_t bytes;
123 15 : if (!GetUint32(&bytes)) {
124 0 : reset_read_pos(orig);
125 0 : return false;
126 : }
127 1692 : for (size_t ix = 0; ix < bytes; ++ix) {
128 831 : uint8_t b;
129 831 : if (!GetUint8(&b)) {
130 0 : reset_read_pos(orig);
131 0 : return false;
132 : }
133 831 : str->push_back(b);
134 831 : }
135 15 : return true;
136 15 : }
137 :
138 1396 : void SerializationBuffer::AddUint8(uint8_t value) {
139 1396 : EnsureAvailableSpace(sizeof value);
140 1396 : buffer_[in_use_] = value;
141 1396 : in_use_ += sizeof value;
142 1396 : }
143 :
144 5 : void SerializationBuffer::AddUint16(uint16_t value) {
145 5 : EnsureAvailableSpace(sizeof value);
146 5 : buffer_[in_use_ + 0] = static_cast<uint8_t>(value >> 0);
147 5 : buffer_[in_use_ + 1] = static_cast<uint8_t>(value >> 8);
148 5 : in_use_ += sizeof value;
149 5 : }
150 :
151 148 : void SerializationBuffer::AddUint32(uint32_t value) {
152 148 : EnsureAvailableSpace(sizeof value);
153 148 : buffer_[in_use_ + 0] = static_cast<uint8_t>(value >> 0);
154 148 : buffer_[in_use_ + 1] = static_cast<uint8_t>(value >> 8);
155 148 : buffer_[in_use_ + 2] = static_cast<uint8_t>(value >> 16);
156 148 : buffer_[in_use_ + 3] = static_cast<uint8_t>(value >> 24);
157 148 : in_use_ += sizeof value;
158 148 : }
159 :
160 4 : void SerializationBuffer::AddUint64(uint64_t value) {
161 4 : EnsureAvailableSpace(sizeof value);
162 4 : buffer_[in_use_ + 0] = static_cast<uint8_t>(value >> 0);
163 4 : buffer_[in_use_ + 1] = static_cast<uint8_t>(value >> 8);
164 4 : buffer_[in_use_ + 2] = static_cast<uint8_t>(value >> 16);
165 4 : buffer_[in_use_ + 3] = static_cast<uint8_t>(value >> 24);
166 4 : buffer_[in_use_ + 4] = static_cast<uint8_t>(value >> 32);
167 4 : buffer_[in_use_ + 5] = static_cast<uint8_t>(value >> 40);
168 4 : buffer_[in_use_ + 6] = static_cast<uint8_t>(value >> 48);
169 4 : buffer_[in_use_ + 7] = static_cast<uint8_t>(value >> 56);
170 4 : in_use_ += sizeof value;
171 4 : }
172 :
173 : #if defined(NACL_HAS_IEEE_754)
174 : void SerializationBuffer::AddFloat(float value) {
175 : union ieee754_float v;
176 : v.f = value;
177 : AddUint32((static_cast<uint32_t>(v.ieee.negative) << 31) |
178 : (static_cast<uint32_t>(v.ieee.exponent) << 23) |
179 : (static_cast<uint32_t>(v.ieee.mantissa) << 0));
180 : }
181 :
182 : void SerializationBuffer::AddDouble(double value) {
183 : union ieee754_double v;
184 : v.d = value;
185 : AddUint64((static_cast<uint64_t>(v.ieee.negative) << 63) |
186 : (static_cast<uint64_t>(v.ieee.exponent) << 52) |
187 : (static_cast<uint64_t>(v.ieee.mantissa0) << 32) |
188 : (static_cast<uint64_t>(v.ieee.mantissa1) << 0));
189 : }
190 :
191 : void SerializationBuffer::AddLongDouble(long double value) {
192 : union ieee854_long_double v;
193 : v.d = value;
194 : AddUint16((static_cast<uint16_t>(v.ieee.negative) << 15) |
195 : (static_cast<uint16_t>(v.ieee.exponent) << 0));
196 : AddUint64((static_cast<uint64_t>(v.ieee.mantissa0) << 32) |
197 : (static_cast<uint64_t>(v.ieee.mantissa1) << 0));
198 : }
199 : #endif
200 :
201 1256 : bool SerializationBuffer::GetUint8(uint8_t *value) {
202 1256 : if (bytes_unread() < sizeof *value) {
203 0 : return false;
204 : }
205 1256 : *value = static_cast<uint8_t>(buffer_[read_ix_]);
206 1256 : read_ix_ += sizeof *value;
207 1256 : return true;
208 1256 : }
209 :
210 8 : bool SerializationBuffer::GetUint16(uint16_t *value) {
211 8 : if (bytes_unread() < sizeof *value) {
212 0 : return false;
213 : }
214 8 : *value = ((static_cast<uint16_t>(buffer_[read_ix_ + 0]) << 0) |
215 8 : (static_cast<uint16_t>(buffer_[read_ix_ + 1]) << 8));
216 8 : read_ix_ += sizeof *value;
217 8 : return true;
218 8 : }
219 :
220 34 : bool SerializationBuffer::GetUint32(uint32_t *value) {
221 34 : if (bytes_unread() < sizeof *value) {
222 0 : return false;
223 : }
224 34 : *value = ((static_cast<uint32_t>(buffer_[read_ix_ + 0]) << 0) |
225 34 : (static_cast<uint32_t>(buffer_[read_ix_ + 1]) << 8) |
226 34 : (static_cast<uint32_t>(buffer_[read_ix_ + 2]) << 16) |
227 34 : (static_cast<uint32_t>(buffer_[read_ix_ + 3]) << 24));
228 34 : read_ix_ += sizeof *value;
229 34 : return true;
230 34 : }
231 :
232 6 : bool SerializationBuffer::GetUint64(uint64_t *value) {
233 6 : if (bytes_unread() < sizeof *value) {
234 0 : return false;
235 : }
236 6 : *value = ((static_cast<uint64_t>(buffer_[read_ix_ + 0]) << 0) |
237 6 : (static_cast<uint64_t>(buffer_[read_ix_ + 1]) << 8) |
238 6 : (static_cast<uint64_t>(buffer_[read_ix_ + 2]) << 16) |
239 6 : (static_cast<uint64_t>(buffer_[read_ix_ + 3]) << 24) |
240 6 : (static_cast<uint64_t>(buffer_[read_ix_ + 4]) << 32) |
241 6 : (static_cast<uint64_t>(buffer_[read_ix_ + 5]) << 40) |
242 6 : (static_cast<uint64_t>(buffer_[read_ix_ + 6]) << 48) |
243 6 : (static_cast<uint64_t>(buffer_[read_ix_ + 7]) << 56));
244 6 : read_ix_ += sizeof *value;
245 6 : return true;
246 6 : }
247 :
248 : #if defined(NACL_HAS_IEEE_754)
249 : bool SerializationBuffer::GetFloat(float *value) {
250 : union ieee754_float v;
251 : uint32_t encoded = 0;
252 : if (!GetUint32(&encoded)) {
253 : return false;
254 : }
255 : v.ieee.negative = encoded >> 31;
256 : v.ieee.exponent = encoded >> 23;
257 : v.ieee.mantissa = encoded;
258 : *value = v.f;
259 : return true;
260 : }
261 :
262 : bool SerializationBuffer::GetDouble(double *value) {
263 : union ieee754_double v;
264 : uint64_t encoded;
265 : if (!GetUint64(&encoded)) {
266 : return false;
267 : }
268 : v.ieee.negative = encoded >> 63;
269 : v.ieee.exponent = encoded >> 52;
270 : v.ieee.mantissa0 = encoded >> 32;
271 : v.ieee.mantissa1 = encoded;
272 : *value = v.d;
273 : return true;
274 : }
275 :
276 : bool SerializationBuffer::GetLongDouble(long double *value) {
277 : union ieee854_long_double v;
278 : uint16_t encoded1;
279 : uint64_t encoded2;
280 : if (in_use_ < read_ix_ + 10) {
281 : return false;
282 : }
283 : if (!GetUint16(&encoded1) || !GetUint64(&encoded2)) {
284 : return false;
285 : }
286 : v.ieee.negative = (encoded1 >> 15) & 1;
287 : v.ieee.exponent = encoded1;
288 : v.ieee.mantissa0 = encoded2 >> 32;
289 : v.ieee.mantissa1 = encoded2;
290 : *value = v.d;
291 : return true;
292 : }
293 : #endif
294 :
295 1554 : void SerializationBuffer::EnsureTotalSize(size_t req_size) {
296 1554 : if (nbytes_ >= req_size) {
297 1528 : return;
298 : }
299 78 : size_t new_size = (0 == nbytes_) ? kInitialBufferSize : 2 * nbytes_;
300 78 : CHECK(new_size > nbytes_); // no arithmetic overflow
301 26 : if (new_size < req_size) {
302 1 : new_size = req_size;
303 1 : }
304 26 : buffer_.resize(new_size);
305 26 : nbytes_ = new_size;
306 1580 : }
307 :
308 1553 : void SerializationBuffer::EnsureAvailableSpace(size_t req_space) {
309 4659 : CHECK(nbytes_ >= in_use_);
310 4659 : CHECK((~(size_t) 0) - in_use_ >= req_space);
311 1553 : size_t new_size = in_use_ + req_space;
312 1553 : EnsureTotalSize(new_size);
313 1553 : }
314 :
315 : } // namespace nacl
|