File: validation.c

package info (click to toggle)
nanopb 0.4.9.1-1
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,676 kB
  • sloc: ansic: 12,144; python: 2,795; cpp: 190; sh: 163; makefile: 85
file content (163 lines) | stat: -rw-r--r-- 5,091 bytes parent folder | download | duplicates (3)
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));
    }
}