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/struct.h" | |
6 | |
7 #include <assert.h> | |
8 #include <string.h> | |
9 | |
10 #include "mojo/public/c/bindings/lib/type_descriptor.h" | |
11 #include "mojo/public/c/bindings/union.h" | |
12 | |
13 size_t MojomStruct_ComputeSerializedSize( | |
14 const struct MojomTypeDescriptorStruct* in_type_desc, | |
15 const struct MojomStructHeader* in_struct) { | |
16 assert(in_struct); | |
17 assert(in_type_desc); | |
18 | |
19 size_t size = in_struct->num_bytes; | |
20 for (size_t i = 0; i < in_type_desc->num_entries; i++) { | |
21 const struct MojomTypeDescriptorStructEntry* entry = | |
22 &(in_type_desc->entries[i]); | |
23 | |
24 if (!MojomType_IsPointer(entry->elem_type) && | |
25 entry->elem_type != MOJOM_TYPE_DESCRIPTOR_TYPE_UNION) | |
26 continue; | |
27 | |
28 if (in_struct->version < entry->min_version) | |
29 continue; | |
30 | |
31 size += MojomType_DispatchComputeSerializedSize( | |
32 entry->elem_type, entry->elem_descriptor, entry->nullable, | |
33 (char*)in_struct + sizeof(struct MojomStructHeader) + entry->offset); | |
34 } | |
35 return size; | |
36 } | |
37 | |
38 void MojomStruct_EncodePointersAndHandles( | |
39 const struct MojomTypeDescriptorStruct* in_type_desc, | |
40 struct MojomStructHeader* inout_struct, | |
41 uint32_t in_struct_size, | |
42 struct MojomHandleBuffer* inout_handles_buffer) { | |
43 assert(in_type_desc); | |
44 assert(inout_struct); | |
45 assert(in_struct_size >= sizeof(struct MojomStructHeader)); | |
46 | |
47 for (size_t i = 0; i < in_type_desc->num_entries; i++) { | |
48 const struct MojomTypeDescriptorStructEntry* entry = | |
49 &(in_type_desc->entries[i]); | |
50 | |
51 if (inout_struct->version < entry->min_version) | |
52 continue; | |
53 | |
54 assert(sizeof(struct MojomStructHeader) + entry->offset < in_struct_size); | |
55 void* elem_data = ((char*)inout_struct + sizeof(struct MojomStructHeader) + | |
56 entry->offset); | |
57 | |
58 MojomType_DispatchEncodePointersAndHandles( | |
59 entry->elem_type, | |
60 entry->elem_descriptor, | |
61 entry->nullable, | |
62 elem_data, | |
63 in_struct_size - ((char*)elem_data - (char*)inout_struct), | |
64 inout_handles_buffer); | |
65 } | |
66 } | |
67 | |
68 void MojomStruct_DecodePointersAndHandles( | |
69 const struct MojomTypeDescriptorStruct* in_type_desc, | |
70 struct MojomStructHeader* inout_struct, | |
71 uint32_t in_struct_size, | |
72 MojoHandle* inout_handles, | |
73 uint32_t in_num_handles) { | |
74 assert(in_type_desc); | |
75 assert(inout_struct); | |
76 assert(inout_handles != NULL || in_num_handles == 0); | |
77 | |
78 for (size_t i = 0; i < in_type_desc->num_entries; i++) { | |
79 const struct MojomTypeDescriptorStructEntry* entry = | |
80 &(in_type_desc->entries[i]); | |
81 | |
82 if (inout_struct->version < entry->min_version) | |
83 continue; | |
84 | |
85 assert(sizeof(struct MojomStructHeader) + entry->offset < in_struct_size); | |
86 void* elem_data = ((char*)inout_struct + sizeof(struct MojomStructHeader) + | |
87 entry->offset); | |
88 | |
89 MojomType_DispatchDecodePointersAndHandles( | |
90 entry->elem_type, | |
91 entry->elem_descriptor, | |
92 entry->nullable, | |
93 elem_data, | |
94 in_struct_size - ((char*)elem_data - (char*)inout_struct), | |
95 inout_handles, | |
96 in_num_handles); | |
97 } | |
98 } | |
99 | |
100 static bool is_valid_size_for_version( | |
101 const struct MojomStructHeader* in_struct, | |
102 const struct MojomTypeDescriptorStructVersion versions[], | |
103 uint32_t num_versions) { | |
104 // Scan for a version size in reverse order (assuming structs are often newer | |
105 // versions than old). Seek to the most recent version that |in_struct| is | |
106 // compatible with. | |
107 uint32_t i = num_versions - 1; | |
108 for (; i > 0 && versions[i].version > in_struct->version; i--); | |
109 | |
110 if (in_struct->version == versions[i].version) { | |
111 return in_struct->num_bytes == versions[i].num_bytes; | |
112 } else { | |
113 return in_struct->num_bytes >= versions[i].num_bytes; | |
114 } | |
115 } | |
116 | |
117 MojomValidationResult MojomStruct_Validate( | |
118 const struct MojomTypeDescriptorStruct* in_type_desc, | |
119 const struct MojomStructHeader* in_struct, | |
120 uint32_t in_struct_size, | |
121 uint32_t in_num_handles, | |
122 struct MojomValidationContext* inout_context) { | |
123 assert(in_type_desc); | |
124 assert(in_struct); | |
125 | |
126 // Struct header validation. | |
127 if (in_struct_size < sizeof(struct MojomStructHeader)) | |
128 return MOJOM_VALIDATION_ILLEGAL_MEMORY_RANGE; | |
129 | |
130 if (in_struct->num_bytes > in_struct_size) | |
131 return MOJOM_VALIDATION_ILLEGAL_MEMORY_RANGE; | |
132 | |
133 if (!is_valid_size_for_version(in_struct, in_type_desc->versions, | |
134 in_type_desc->num_versions)) { | |
135 return MOJOM_VALIDATION_UNEXPECTED_STRUCT_HEADER; | |
136 } | |
137 | |
138 if ((in_struct->num_bytes & 7) != 0) | |
139 return MOJOM_VALIDATION_MISALIGNED_OBJECT; | |
140 | |
141 // From here on out, all pointers need to point past the end of this struct. | |
142 inout_context->next_pointer = (char*)in_struct + in_struct->num_bytes; | |
143 | |
144 for (size_t i = 0; i < in_type_desc->num_entries; i++) { | |
145 const struct MojomTypeDescriptorStructEntry* entry = | |
146 &(in_type_desc->entries[i]); | |
147 | |
148 if (in_struct->version < entry->min_version) | |
149 continue; | |
150 | |
151 void* elem_data = ((char*)in_struct + sizeof(struct MojomStructHeader) + | |
152 entry->offset); | |
153 MojomValidationResult result = MojomType_DispatchValidate( | |
154 entry->elem_type, | |
155 entry->elem_descriptor, | |
156 entry->nullable, | |
157 elem_data, | |
158 in_struct_size - ((char*)elem_data - (char*)in_struct), | |
159 in_num_handles, | |
160 inout_context); | |
161 if (result != MOJOM_VALIDATION_ERROR_NONE) | |
162 return result; | |
163 } | |
164 | |
165 return MOJOM_VALIDATION_ERROR_NONE; | |
166 } | |
167 | |
168 bool MojomStruct_DeepCopy( | |
169 struct MojomBuffer* buffer, | |
170 const struct MojomTypeDescriptorStruct* in_type_desc, | |
171 const struct MojomStructHeader* in_struct, | |
172 struct MojomStructHeader** out_struct) { | |
173 assert(in_type_desc); | |
174 assert(in_struct); | |
175 assert(out_struct); | |
176 | |
177 *out_struct = MojomBuffer_Allocate(buffer, in_struct->num_bytes); | |
178 if (*out_struct == NULL) | |
179 return false; | |
180 | |
181 memcpy(*out_struct, in_struct, in_struct->num_bytes); | |
182 | |
183 for (size_t i = 0; i < in_type_desc->num_entries; i++) { | |
184 const struct MojomTypeDescriptorStructEntry* entry = | |
185 &(in_type_desc->entries[i]); | |
186 | |
187 if (in_struct->version < entry->min_version) | |
188 continue; | |
189 | |
190 void* in_elem_data = | |
191 ((char*)in_struct + sizeof(struct MojomStructHeader) + entry->offset); | |
192 void* out_elem_data = ((char*)*out_struct + | |
193 sizeof(struct MojomStructHeader) + entry->offset); | |
194 if (!MojomType_DispatchDeepCopy( | |
195 buffer, | |
196 entry->elem_type, | |
197 entry->elem_descriptor, | |
198 in_elem_data, | |
199 out_elem_data)) { | |
200 return false; | |
201 } | |
202 } | |
203 | |
204 return true; | |
205 } | |
OLD | NEW |