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