1 #include "validation.h"
2 #include "malloc_wrappers.h"
3 #include <pb_common.h>
4 #include <assert.h>
5
validate_static(pb_field_iter_t * iter)6 void validate_static(pb_field_iter_t *iter)
7 {
8 pb_size_t count = 1;
9 pb_size_t i;
10 bool truebool = true;
11 bool falsebool = false;
12
13 if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED && iter->pSize)
14 {
15 /* Array count must be between 0 and statically allocated size */
16 count = *(pb_size_t*)iter->pSize;
17 assert(count <= iter->array_size);
18 }
19 else if (PB_HTYPE(iter->type) == PB_HTYPE_OPTIONAL && iter->pSize)
20 {
21 /* Boolean has_ field must have a valid value */
22 assert(memcmp(iter->pSize, &truebool, sizeof(bool)) == 0 ||
23 memcmp(iter->pSize, &falsebool, sizeof(bool)) == 0);
24 }
25 else if (PB_HTYPE(iter->type) == PB_HTYPE_ONEOF)
26 {
27 if (*(pb_size_t*)iter->pSize != iter->tag)
28 {
29 /* Some different field in oneof */
30 return;
31 }
32 }
33
34 for (i = 0; i < count; i++)
35 {
36 void *pData = (char*)iter->pData + iter->data_size * i;
37
38 if (PB_LTYPE(iter->type) == PB_LTYPE_STRING)
39 {
40 /* String length must be at most statically allocated size */
41 assert(strlen(pData) + 1 <= iter->data_size);
42 }
43 else if (PB_LTYPE(iter->type) == PB_LTYPE_BYTES)
44 {
45 /* Bytes length must be at most statically allocated size */
46 pb_bytes_array_t *bytes = pData;
47 assert(PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) <= iter->data_size);
48 }
49 else if (PB_LTYPE(iter->type) == PB_LTYPE_BOOL)
50 {
51 /* Bool fields must have valid value */
52 assert(memcmp(pData, &truebool, sizeof(bool)) == 0 ||
53 memcmp(pData, &falsebool, sizeof(bool)) == 0);
54 }
55 else if (PB_LTYPE_IS_SUBMSG(iter->type))
56 {
57 validate_message(pData, 0, iter->submsg_desc);
58 }
59 }
60 }
61
validate_pointer(pb_field_iter_t * iter)62 void validate_pointer(pb_field_iter_t *iter)
63 {
64 pb_size_t count = 1;
65 pb_size_t i;
66 bool truebool = true;
67 bool falsebool = false;
68
69 if (PB_HTYPE(iter->type) == PB_HTYPE_ONEOF)
70 {
71 if (*(pb_size_t*)iter->pSize != iter->tag)
72 {
73 /* Some different field in oneof */
74 return;
75 }
76 }
77 else if (!iter->pData)
78 {
79 /* Nothing allocated */
80 if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED && iter->pSize != &iter->array_size)
81 {
82 assert(*(pb_size_t*)iter->pSize == 0);
83 }
84 return;
85 }
86
87 if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED)
88 {
89 /* Check that enough memory has been allocated for array */
90 size_t allocated_size = get_allocation_size(iter->pData);
91 count = *(pb_size_t*)iter->pSize;
92 assert(allocated_size >= count * iter->data_size);
93 }
94 else if (PB_LTYPE(iter->type) != PB_LTYPE_STRING && PB_LTYPE(iter->type) != PB_LTYPE_BYTES)
95 {
96 size_t allocated_size = get_allocation_size(iter->pData);
97 assert(allocated_size >= iter->data_size);
98 }
99
100 for (i = 0; i < count; i++)
101 {
102 void *pData = (char*)iter->pData + iter->data_size * i;
103
104 if (PB_LTYPE(iter->type) == PB_LTYPE_STRING)
105 {
106 /* Check that enough memory is allocated for string and that
107 the string is properly terminated. */
108 const char *str = pData;
109
110 if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED)
111 {
112 /* String arrays are stored as array of pointers */
113 str = ((const char**)iter->pData)[i];
114 }
115
116 assert(strlen(str) + 1 <= get_allocation_size(str));
117 }
118 else if (PB_LTYPE(iter->type) == PB_LTYPE_BYTES)
119 {
120 /* Bytes length must be at most statically allocated size */
121 const pb_bytes_array_t *bytes = pData;
122
123 if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED)
124 {
125 /* Bytes arrays are stored as array of pointers */
126 bytes = ((const pb_bytes_array_t**)iter->pData)[i];
127 }
128
129 assert(PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) <= get_allocation_size(bytes));
130 }
131 else if (PB_LTYPE(iter->type) == PB_LTYPE_BOOL)
132 {
133 /* Bool fields must have valid value */
134 assert(memcmp(pData, &truebool, sizeof(bool)) == 0 ||
135 memcmp(pData, &falsebool, sizeof(bool)) == 0);
136 }
137 else if (PB_LTYPE_IS_SUBMSG(iter->type))
138 {
139 validate_message(pData, 0, iter->submsg_desc);
140 }
141 }
142 }
143
validate_message(const void * msg,size_t structsize,const pb_msgdesc_t * msgtype)144 void validate_message(const void *msg, size_t structsize, const pb_msgdesc_t *msgtype)
145 {
146 pb_field_iter_t iter;
147
148 if (pb_field_iter_begin_const(&iter, msgtype, msg))
149 {
150 do
151 {
152 if (PB_ATYPE(iter.type) == PB_ATYPE_STATIC)
153 {
154 validate_static(&iter);
155 }
156 else if (PB_ATYPE(iter.type) == PB_ATYPE_POINTER)
157 {
158 validate_pointer(&iter);
159 }
160 } while (pb_field_iter_next(&iter));
161 }
162 }
163
164