OLD | NEW |
| (Empty) |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "mojo/public/c/bindings/array.h" | |
6 | |
7 #include <assert.h> | |
8 #include <stddef.h> | |
9 #include <stdint.h> | |
10 #include <string.h> | |
11 | |
12 #include "mojo/public/c/bindings/buffer.h" | |
13 #include "mojo/public/c/bindings/interface.h" | |
14 #include "mojo/public/c/bindings/lib/type_descriptor.h" | |
15 #include "mojo/public/c/bindings/lib/util.h" | |
16 #include "mojo/public/c/bindings/union.h" | |
17 | |
18 struct MojomArrayHeader* MojomArray_New(struct MojomBuffer* buf, | |
19 uint32_t num_elements, | |
20 uint32_t element_byte_size) { | |
21 assert(buf); | |
22 | |
23 uint64_t num_bytes = sizeof(struct MojomArrayHeader) + | |
24 (uint64_t)num_elements * element_byte_size; | |
25 if (num_bytes > UINT32_MAX) | |
26 return NULL; | |
27 | |
28 struct MojomArrayHeader* arr = | |
29 (struct MojomArrayHeader*)MojomBuffer_Allocate(buf, (uint32_t)num_bytes); | |
30 if (arr == NULL) | |
31 return NULL; | |
32 | |
33 assert((uintptr_t)arr + MOJOM_INTERNAL_ROUND_TO_8(num_bytes) == | |
34 (uintptr_t)buf->buf + buf->num_bytes_used); | |
35 | |
36 arr->num_elements = num_elements; | |
37 arr->num_bytes = MOJOM_INTERNAL_ROUND_TO_8((uint32_t)num_bytes); | |
38 | |
39 return arr; | |
40 } | |
41 | |
42 // Gets the |index|th element (whose type is described by |type|) of |array|. | |
43 // Only supports non-POD types. | |
44 static void* array_index_by_type(const struct MojomArrayHeader* array, | |
45 enum MojomTypeDescriptorType type, | |
46 size_t index) { | |
47 switch (type) { | |
48 case MOJOM_TYPE_DESCRIPTOR_TYPE_STRUCT_PTR: | |
49 case MOJOM_TYPE_DESCRIPTOR_TYPE_MAP_PTR: | |
50 case MOJOM_TYPE_DESCRIPTOR_TYPE_ARRAY_PTR: | |
51 return MOJOM_ARRAY_INDEX(array, union MojomPointer, index); | |
52 case MOJOM_TYPE_DESCRIPTOR_TYPE_UNION: | |
53 return MOJOM_ARRAY_INDEX(array, struct MojomUnionLayout, index); | |
54 case MOJOM_TYPE_DESCRIPTOR_TYPE_HANDLE: | |
55 return MOJOM_ARRAY_INDEX(array, MojoHandle, index); | |
56 case MOJOM_TYPE_DESCRIPTOR_TYPE_INTERFACE: | |
57 return MOJOM_ARRAY_INDEX(array, struct MojomInterfaceData, index); | |
58 case MOJOM_TYPE_DESCRIPTOR_TYPE_UNION_PTR: | |
59 case MOJOM_TYPE_DESCRIPTOR_TYPE_POD: | |
60 // This is a type that isn't supported in an array. | |
61 assert(0); | |
62 break; | |
63 } | |
64 return NULL; | |
65 } | |
66 | |
67 size_t MojomArray_ComputeSerializedSize( | |
68 const struct MojomTypeDescriptorArray* in_type_desc, | |
69 const struct MojomArrayHeader* in_array) { | |
70 assert(in_array); | |
71 assert(in_type_desc); | |
72 | |
73 size_t size = in_array->num_bytes; | |
74 if (!MojomType_IsPointer(in_type_desc->elem_type) && | |
75 in_type_desc->elem_type != MOJOM_TYPE_DESCRIPTOR_TYPE_UNION) | |
76 return size; | |
77 | |
78 for (uint32_t i = 0; i < in_array->num_elements; i++) { | |
79 size += MojomType_DispatchComputeSerializedSize( | |
80 in_type_desc->elem_type, | |
81 in_type_desc->elem_descriptor, | |
82 in_type_desc->nullable, | |
83 array_index_by_type(in_array, in_type_desc->elem_type, i)); | |
84 } | |
85 | |
86 return size; | |
87 } | |
88 | |
89 void MojomArray_EncodePointersAndHandles( | |
90 const struct MojomTypeDescriptorArray* in_type_desc, | |
91 struct MojomArrayHeader* inout_array, | |
92 uint32_t in_array_size, | |
93 struct MojomHandleBuffer* inout_handles_buffer) { | |
94 assert(in_type_desc); | |
95 assert(inout_array); | |
96 assert(in_array_size >= sizeof(struct MojomArrayHeader)); | |
97 assert(in_array_size >= inout_array->num_bytes); | |
98 | |
99 // Nothing to encode for POD types. | |
100 if (in_type_desc->elem_type == MOJOM_TYPE_DESCRIPTOR_TYPE_POD) | |
101 return; | |
102 | |
103 for (size_t i = 0; i < inout_array->num_elements; i++) { | |
104 char* elem_data = | |
105 array_index_by_type(inout_array, in_type_desc->elem_type, i); | |
106 assert(elem_data < (char*)inout_array + in_array_size); | |
107 | |
108 MojomType_DispatchEncodePointersAndHandles( | |
109 in_type_desc->elem_type, | |
110 in_type_desc->elem_descriptor, | |
111 in_type_desc->nullable, | |
112 elem_data, | |
113 in_array_size - (uint32_t)(elem_data - (char*)inout_array), | |
114 inout_handles_buffer); | |
115 } | |
116 } | |
117 | |
118 void MojomArray_DecodePointersAndHandles( | |
119 const struct MojomTypeDescriptorArray* in_type_desc, | |
120 struct MojomArrayHeader* inout_array, | |
121 uint32_t in_array_size, | |
122 MojoHandle* inout_handles, | |
123 uint32_t in_num_handles) { | |
124 assert(in_type_desc); | |
125 assert(inout_array); | |
126 assert(inout_handles != NULL || in_num_handles == 0); | |
127 | |
128 // Nothing to encode for POD types. | |
129 if (in_type_desc->elem_type == MOJOM_TYPE_DESCRIPTOR_TYPE_POD) | |
130 return; | |
131 | |
132 for (size_t i = 0; i < inout_array->num_elements; i++) { | |
133 char* elem_data = | |
134 array_index_by_type(inout_array, in_type_desc->elem_type, i); | |
135 assert(elem_data < (char*)inout_array + in_array_size); | |
136 | |
137 MojomType_DispatchDecodePointersAndHandles( | |
138 in_type_desc->elem_type, | |
139 in_type_desc->elem_descriptor, | |
140 in_type_desc->nullable, | |
141 elem_data, | |
142 in_array_size - (uint32_t)(elem_data - (char*)inout_array), | |
143 inout_handles, | |
144 in_num_handles); | |
145 } | |
146 } | |
147 | |
148 // Rounds up to nearest byte. | |
149 static uint64_t bits_to_bytes(uint64_t bits) { | |
150 return (bits + 7) / 8; | |
151 } | |
152 | |
153 static MojomValidationResult validate_array_header( | |
154 const struct MojomTypeDescriptorArray* in_type_desc, | |
155 const struct MojomArrayHeader* in_array, | |
156 uint32_t in_buf_size) { | |
157 if (in_buf_size < sizeof(struct MojomArrayHeader)) | |
158 return MOJOM_VALIDATION_ILLEGAL_MEMORY_RANGE; | |
159 | |
160 if (in_array->num_bytes < sizeof(struct MojomArrayHeader)) | |
161 return MOJOM_VALIDATION_UNEXPECTED_ARRAY_HEADER; | |
162 | |
163 if (in_array->num_bytes > in_buf_size) | |
164 return MOJOM_VALIDATION_ILLEGAL_MEMORY_RANGE; | |
165 | |
166 if (in_type_desc->num_elements != 0 && | |
167 in_array->num_elements != in_type_desc->num_elements) | |
168 return MOJOM_VALIDATION_UNEXPECTED_ARRAY_HEADER; | |
169 | |
170 // Array size is less than what we need to fit the elements. | |
171 if (in_array->num_bytes < | |
172 sizeof(struct MojomArrayHeader) + | |
173 bits_to_bytes((uint64_t)in_type_desc->elem_num_bits * | |
174 (uint64_t)in_array->num_elements)) { | |
175 return MOJOM_VALIDATION_UNEXPECTED_ARRAY_HEADER; | |
176 } | |
177 | |
178 return MOJOM_VALIDATION_ERROR_NONE; | |
179 } | |
180 | |
181 MojomValidationResult MojomArray_Validate( | |
182 const struct MojomTypeDescriptorArray* in_type_desc, | |
183 const struct MojomArrayHeader* in_array, | |
184 uint32_t in_array_size, | |
185 uint32_t in_num_handles, | |
186 struct MojomValidationContext* inout_context) { | |
187 assert(in_type_desc); | |
188 assert(in_array); | |
189 | |
190 MojomValidationResult result = | |
191 validate_array_header(in_type_desc, in_array, in_array_size); | |
192 if (result != MOJOM_VALIDATION_ERROR_NONE) | |
193 return result; | |
194 | |
195 // From here on out, all pointers need to point past the end of this struct. | |
196 inout_context->next_pointer = (char*)in_array + in_array->num_bytes; | |
197 | |
198 // Nothing to validate for POD types. | |
199 if (in_type_desc->elem_type == MOJOM_TYPE_DESCRIPTOR_TYPE_POD) | |
200 return MOJOM_VALIDATION_ERROR_NONE; | |
201 | |
202 for (size_t i = 0; i < in_array->num_elements; i++) { | |
203 char* elem_data = | |
204 array_index_by_type(in_array, in_type_desc->elem_type, i); | |
205 | |
206 MojomValidationResult result = MojomType_DispatchValidate( | |
207 in_type_desc->elem_type, | |
208 in_type_desc->elem_descriptor, | |
209 in_type_desc->nullable, | |
210 elem_data, | |
211 in_array_size - (uint32_t)(elem_data - (char*)in_array), | |
212 in_num_handles, | |
213 inout_context); | |
214 if (result != MOJOM_VALIDATION_ERROR_NONE) | |
215 return result; | |
216 } | |
217 | |
218 return MOJOM_VALIDATION_ERROR_NONE; | |
219 } | |
220 | |
221 bool MojomArray_DeepCopy( | |
222 struct MojomBuffer* buffer, | |
223 const struct MojomTypeDescriptorArray* in_type_desc, | |
224 const struct MojomArrayHeader* in_array, | |
225 struct MojomArrayHeader** out_array) { | |
226 assert(in_type_desc); | |
227 assert(in_array); | |
228 assert(out_array); | |
229 | |
230 *out_array = MojomBuffer_Allocate(buffer, in_array->num_bytes); | |
231 if (*out_array == NULL) | |
232 return false; | |
233 | |
234 memcpy(*out_array, in_array, in_array->num_bytes); | |
235 | |
236 // Nothing else to copy for POD types. | |
237 if (in_type_desc->elem_type == MOJOM_TYPE_DESCRIPTOR_TYPE_POD) | |
238 return true; | |
239 | |
240 for (size_t i = 0; i < in_array->num_elements; i++) { | |
241 void* in_elem_data = | |
242 array_index_by_type(in_array, in_type_desc->elem_type, i); | |
243 void* out_elem_data = | |
244 array_index_by_type(*out_array, in_type_desc->elem_type, i); | |
245 | |
246 if (!MojomType_DispatchDeepCopy(buffer, in_type_desc->elem_type, | |
247 in_type_desc->elem_descriptor, in_elem_data, | |
248 out_elem_data)) { | |
249 return false; | |
250 } | |
251 } | |
252 | |
253 return true; | |
254 } | |
OLD | NEW |