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