LCOV - code coverage report
Current view: top level - src/runtime - verifier.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 125 135 92.6 %
Date: 2016-11-30 13:12:14 Functions: 17 21 81.0 %
Branches: 120 272 44.1 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Runtime support for verifying flatbuffers.
       3                 :            :  *
       4                 :            :  * Depends mutually on generated verifier functions for table types that
       5                 :            :  * call into this library.
       6                 :            :  */
       7                 :            : #include <assert.h>
       8                 :            : #include <string.h>
       9                 :            : 
      10                 :            : #include "flatcc/flatcc_rtconfig.h"
      11                 :            : #include "flatcc/flatcc_flatbuffers.h"
      12                 :            : #include "flatcc/flatcc_verifier.h"
      13                 :            : 
      14                 :            : /* Customization for testing. */
      15                 :            : #if FLATCC_DEBUG_VERIFY
      16                 :            : #define FLATCC_VERIFIER_ASSERT_ON_ERROR 1
      17                 :            : #include <stdio.h>
      18                 :            : #define FLATCC_VERIFIER_ASSERT(cond, reason)                                \
      19                 :            :     if (!(cond)) { fprintf(stderr, "verifier assert: %s\n",                 \
      20                 :            :         flatcc_verify_error_string(reason)); assert(0); return reason; }
      21                 :            : #endif
      22                 :            : 
      23                 :            : #ifdef FLATCC_TRACE_VERIFY
      24                 :            : #include <stdio.h>
      25                 :            : #define trace_verify(s, p) \
      26                 :            :     fprintf(stderr, "trace verify: %s: 0x%02x\n", (s), (unsigned)(size_t)(p));
      27                 :            : #else
      28                 :            : #define trace_verify(s, p) ((void)0)
      29                 :            : #endif
      30                 :            : 
      31                 :            : /* The runtime library does not use the global config file. */
      32                 :            : 
      33                 :            : /* This is a guideline, not an exact measure. */
      34                 :            : #ifndef FLATCC_VERIFIER_MAX_LEVELS
      35                 :            : #define FLATCC_VERIFIER_MAX_LEVELS 100
      36                 :            : #endif
      37                 :            : 
      38                 :            : #ifndef FLATCC_VERIFIER_ASSERT_ON_ERROR
      39                 :            : #define FLATCC_VERIFIER_ASSERT_ON_ERROR 0
      40                 :            : #endif
      41                 :            : 
      42                 :            : /*
      43                 :            :  * Generally a check should tell if a buffer is valid or not such
      44                 :            :  * that runtime can take appropriate actions rather than crash,
      45                 :            :  * also in debug, but assertions are helpful in debugging a problem.
      46                 :            :  *
      47                 :            :  * This must be compiled into the debug runtime library to take effect.
      48                 :            :  */
      49                 :            : #ifndef FLATCC_VERIFIER_ASSERT_ON_ERROR
      50                 :            : #define FLATCC_VERIFIER_ASSERT_ON_ERROR 1
      51                 :            : #endif
      52                 :            : 
      53                 :            : /* May be redefined for logging purposes. */
      54                 :            : #ifndef FLATCC_VERIFIER_ASSERT
      55                 :            : #define FLATCC_VERIFIER_ASSERT(cond, reason) assert(cond)
      56                 :            : #endif
      57                 :            : 
      58                 :            : #if FLATCC_VERIFIER_ASSERT_ON_ERROR
      59                 :            : #define flatcc_verify(cond, reason) if (!(cond)) { FLATCC_VERIFIER_ASSERT(cond, reason); return reason; }
      60                 :            : #else
      61                 :            : #define flatcc_verify(cond, reason) if (!(cond)) { return reason; }
      62                 :            : #endif
      63                 :            : 
      64                 :            : 
      65                 :            : #define uoffset_t flatbuffers_uoffset_t
      66                 :            : #define soffset_t flatbuffers_soffset_t
      67                 :            : #define voffset_t flatbuffers_voffset_t
      68                 :            : #define thash_t flatbuffers_thash_t
      69                 :            : 
      70                 :            : #define uoffset_size sizeof(uoffset_t)
      71                 :            : #define soffset_size sizeof(soffset_t)
      72                 :            : #define voffset_size sizeof(voffset_t)
      73                 :            : #define thash_size sizeof(thash_t)
      74                 :            : #define offset_size uoffset_size
      75                 :            : 
      76         [ #  # ]:          0 : const char *flatcc_verify_error_string(int err)
      77                 :            : {
      78                 :            :     switch (err) {
      79                 :            : #define XX(no, str)                                                         \
      80                 :            :     case flatcc_verify_error_##no:                                          \
      81                 :            :         return str;
      82                 :            :         FLATCC_VERIFY_ERROR_MAP(XX)
      83                 :            : #undef XX
      84                 :            :     default:
      85                 :            :         return "unknown";
      86                 :            :     }
      87                 :            : }
      88                 :            : 
      89                 :            : /* `cond` may have side effects. */
      90                 :            : #define verify(cond, reason) do { int c = (cond); flatcc_verify(c, reason); } while(0)
      91                 :            : 
      92                 :            : /*
      93                 :            :  * Identify checks related to runtime conditions (buffer size and
      94                 :            :  * alignment) as seperate from those related to buffer content.
      95                 :            :  */
      96                 :            : #define verify_runtime(cond, reason) verify(cond, reason)
      97                 :            : 
      98                 :            : #define check_result(x) if (x) { return (x); }
      99                 :            : 
     100                 :            : #define check_field(td, id, required, base) do {                   \
     101                 :            :     int ret = get_offset_field(td, id, required, &base);                    \
     102                 :            :     if (ret || !base) { return ret; }} while (0)
     103                 :            : 
     104                 :            : static inline uoffset_t read_uoffset(const void *p, uoffset_t base)
     105                 :            : {
     106                 :        408 :     return __flatbuffers_uoffset_read_from_pe((uint8_t *)p + base);
     107                 :            : }
     108                 :            : 
     109                 :            : static inline thash_t read_thash_identifier(const char *identifier)
     110                 :            : {
     111                 :         58 :     flatbuffers_thash_t id = 0;
     112                 :         58 :     strncpy((char *)&id, identifier, sizeof(id));
     113                 :         58 :     return __flatbuffers_thash_cast_from_le(id);
     114                 :            : }
     115                 :            : 
     116                 :            : static inline thash_t read_thash(const void *p, uoffset_t base)
     117                 :            : {
     118                 :            :     return __flatbuffers_thash_read_from_pe((uint8_t *)p + base);
     119                 :            : }
     120                 :            : 
     121                 :            : static inline voffset_t read_voffset(const void *p, uoffset_t base)
     122                 :            : {
     123                 :        886 :     return __flatbuffers_voffset_read_from_pe((uint8_t *)p + base);
     124                 :            : }
     125                 :            : 
     126                 :            : static inline int check_header(uoffset_t end, uoffset_t base, uoffset_t offset)
     127                 :            : {
     128                 :        209 :     uoffset_t k = base + offset;
     129                 :            : 
     130                 :            :     if (uoffset_size <= voffset_size && k + offset_size < k) {
     131                 :            :         return 0;
     132                 :            :     }
     133                 :            : 
     134                 :            :     /* The `k > base` rather than `k >= base` is to avoid null offsets. */
     135 [ +  - ][ +  - ]:        209 :     return k > base && k + offset_size <= end && !(k & (offset_size - 1));
         [ -  + ][ +  - ]
         [ +  - ][ -  + ]
     136                 :            : }
     137                 :            : 
     138                 :            : static inline int check_aligned_header(uoffset_t end, uoffset_t base, uoffset_t offset, uint16_t align)
     139                 :            : {
     140                 :         21 :     uoffset_t k = base + offset;
     141                 :            : 
     142                 :            :     if (uoffset_size <= voffset_size && k + offset_size < k) {
     143                 :            :         return 0;
     144                 :            :     }
     145                 :            : 
     146                 :            :     /* Note to self: the builder can also use the mask OR trick to propagate `min_align`. */
     147 [ +  - ][ +  - ]:         21 :     return k > base && k + offset_size <= end && !(k & ((offset_size - 1) | (align - 1)));
         [ -  + ][ +  - ]
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ +  - ]
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
                 [ #  # ]
     148                 :            : }
     149                 :            : 
     150                 :            : static inline int verify_struct(uoffset_t end, uoffset_t base, uint16_t align, uoffset_t size)
     151                 :            : {
     152                 :            :     verify(uoffset_size <= voffset_size && base + size < base, flatcc_verify_error_struct_size_overflow);
     153                 :            :     verify(base > 0 && base + size <= end, flatcc_verify_error_struct_out_of_range);
     154                 :            :     verify (!(base & (align - 1)), flatcc_verify_error_struct_unaligned);
     155                 :            :     return flatcc_verify_ok;
     156                 :            : }
     157                 :            : 
     158                 :            : static inline uoffset_t read_vt_entry(flatcc_table_verifier_descriptor_t *td, voffset_t id)
     159                 :            : {
     160                 :       2498 :     voffset_t vo = (id + 2) * sizeof(voffset_t);
     161                 :            : 
     162                 :            :     /* Assumes tsize has been verified for alignment. */
     163 [ +  + ][ +  + ]:       2498 :     if (vo >= td->vsize) {
         [ +  - ][ +  + ]
         [ #  # ][ +  + ]
                 [ +  + ]
     164                 :            :         return 0;
     165                 :            :     }
     166                 :        681 :     return read_voffset(td->vtable, vo);
     167                 :            : }
     168                 :            : 
     169                 :            : static inline const void *get_field_ptr(flatcc_table_verifier_descriptor_t *td, voffset_t id)
     170                 :            : {
     171                 :         95 :     voffset_t vte = read_vt_entry(td, id);
     172 [ +  + ][ #  # ]:         95 :     return vte ? (const uint8_t *)td->buf + td->table + vte : 0;
     173                 :            : }
     174                 :            : 
     175                 :            : static int verify_field(flatcc_table_verifier_descriptor_t *td,
     176                 :            :         voffset_t id, int required, uint16_t align, uoffset_t size)
     177                 :            : {
     178                 :            :     uoffset_t k, k2;
     179                 :            :     voffset_t vte;
     180                 :       1259 :     uoffset_t base = (uoffset_t)(size_t)td->buf;
     181                 :            : 
     182                 :            : 
     183                 :            :     /*
     184                 :            :      * Otherwise range check assumptions break, and normal access code likely also.
     185                 :            :      * We don't require voffset_size < uoffset_size, but some checks are faster if true.
     186                 :            :      */
     187                 :            :     assert(uoffset_size >= voffset_size);
     188                 :            :     assert(soffset_size == uoffset_size);
     189                 :            : 
     190                 :       1245 :     vte = read_vt_entry(td, id);
     191 [ +  + ][ #  # ]:       1245 :     if (!vte) {
     192                 :            :         verify(!required, flatcc_verify_error_required_field_missing);
     193                 :            :         return flatcc_verify_ok;
     194                 :            :     }
     195                 :            :     trace_verify("table buffer", td->buf);
     196                 :            :     trace_verify("table", td->table);
     197                 :            :     trace_verify("id", id);
     198                 :            :     trace_verify("vte", vte);
     199                 :            : 
     200                 :            :     /*
     201                 :            :      * Note that we don't add td.table to k and we test against table
     202                 :            :      * size not table end or buffer end. Otherwise it would not be safe
     203                 :            :      * to optimized out the k <= k2 check for normal uoffset and voffset
     204                 :            :      * configurations.
     205                 :            :      */
     206                 :            :     k = vte;
     207                 :         74 :     k2 = k + size;
     208 [ +  - ][ #  # ]:         74 :     verify(k2 <= td->tsize, flatcc_verify_error_table_field_out_of_range);
         [ +  - ][ #  # ]
     209                 :            :     /* This normally optimizes to nop. */
     210                 :            :     verify(uoffset_size > voffset_size || k <= k2, flatcc_verify_error_table_field_size_overflow);
     211                 :            :     trace_verify("table + vte", vte + td->table);
     212                 :         60 :     k += td->table + base;
     213                 :            :     trace_verify("entry: buf + table + vte", k);
     214                 :            :     trace_verify("align", align);
     215                 :            :     trace_verify("align masked entry", k & (align - 1));
     216 [ +  - ][ #  # ]:         60 :     verify(!(k & (align - 1)), flatcc_verify_error_table_field_not_aligned);
     217                 :            :     /* We assume the table size has already been verified. */
     218                 :            :     return flatcc_verify_ok;
     219                 :            : }
     220                 :            : 
     221                 :        968 : static int get_offset_field(flatcc_table_verifier_descriptor_t *td, voffset_t id, int required, uoffset_t *out)
     222                 :            : {
     223                 :            :     uoffset_t k, k2;
     224                 :            :     voffset_t vte;
     225                 :            : 
     226                 :       1936 :     vte = read_vt_entry(td, id);
     227         [ +  + ]:        968 :     if (!vte) {
     228                 :        831 :         *out = 0;
     229         [ +  - ]:        831 :         if (required) {
     230                 :            :             return flatcc_verify_error_required_field_missing;
     231                 :            :         }
     232                 :            :         /* Missing, but not invalid. */
     233                 :        831 :         return flatcc_verify_ok;
     234                 :            :     }
     235                 :            :     /*
     236                 :            :      * Note that we don't add td.table to k and we test against table
     237                 :            :      * size not table end or buffer end. Otherwise it would not be safe
     238                 :            :      * to optimized out the k <= k2 check for normal uoffset and voffset
     239                 :            :      * configurations.
     240                 :            :      */
     241                 :            :     k = vte;
     242                 :        137 :     k2 = k + offset_size;
     243         [ +  - ]:        137 :     verify(k2 <= td->tsize, flatcc_verify_error_table_field_out_of_range);
     244                 :            :     /* This normally optimizes to nop. */
     245                 :            :     verify(uoffset_size > voffset_size || k <= k2, flatcc_verify_error_table_field_size_overflow);
     246                 :        137 :     k += td->table;
     247         [ +  - ]:        137 :     verify(!(k & (offset_size - 1)), flatcc_verify_error_table_field_not_aligned);
     248                 :            :     /* We assume the table size has already been verified. */
     249                 :        137 :     *out = k;
     250                 :        137 :     return flatcc_verify_ok;
     251                 :            : }
     252                 :            : 
     253                 :        106 : static inline int verify_string(const void *buf, uoffset_t end, uoffset_t base, uoffset_t offset)
     254                 :            : {
     255                 :            :     uoffset_t n;
     256                 :            : 
     257         [ +  - ]:        106 :     verify(check_header(end, base, offset), flatcc_verify_error_table_offset_out_of_range_or_unaligned);
     258                 :            :     base += offset;
     259                 :            :     n = read_uoffset(buf, base);
     260                 :        106 :     base += offset_size;
     261         [ +  - ]:        106 :     verify(end - base >= n + 1, flatcc_verify_error_string_out_of_range);
     262         [ +  - ]:        106 :     verify(((uint8_t *)buf + base)[n] == 0, flatcc_verify_error_string_not_zero_terminated);
     263                 :        106 :     return flatcc_verify_ok;
     264                 :            : }
     265                 :            : 
     266                 :            : /*
     267                 :            :  * Keep interface somwewhat similar ot flatcc_builder_start_vector.
     268                 :            :  * `max_count` is a precomputed division to manage overflow check on vector length.
     269                 :            :  */
     270                 :            : static inline int verify_vector(const void *buf, uoffset_t end, uoffset_t base, uoffset_t offset, uint16_t align, uoffset_t elem_size, uoffset_t max_count)
     271                 :            : {
     272                 :            :     uoffset_t n;
     273                 :            : 
     274 [ +  - ][ +  - ]:         21 :     verify(check_aligned_header(end, base, offset, align), flatcc_verify_error_table_header_out_of_range_or_unaligned);
         [ #  # ][ +  - ]
                 [ #  # ]
     275                 :            :     base += offset;
     276                 :            :     n = read_uoffset(buf, base);
     277                 :         21 :     base += offset_size;
     278                 :            :     /* `n * elem_size` can overflow uncontrollably otherwise. */
     279 [ +  - ][ +  - ]:         21 :     verify(n <= max_count, flatcc_verify_error_vector_count_exceeds_representable_vector_size);
         [ #  # ][ +  - ]
                 [ #  # ]
     280 [ +  - ][ +  - ]:         21 :     verify(end - base >= n * elem_size, flatcc_verify_error_vector_out_of_range);
         [ #  # ][ +  - ]
                 [ #  # ]
     281                 :            :     return flatcc_verify_ok;
     282                 :            : }
     283                 :            : 
     284                 :          4 : static inline int verify_string_vector(const void *buf, uoffset_t end, uoffset_t base, uoffset_t offset)
     285                 :            : {
     286                 :            :     uoffset_t i, n;
     287                 :            : 
     288         [ -  + ]:          4 :     check_result(verify_vector(buf, end, base, offset, offset_size, offset_size, FLATBUFFERS_COUNT_MAX(offset_size)));
     289                 :            :     base += offset;
     290                 :            :     n = read_uoffset(buf, base);
     291                 :          4 :     base += offset_size;
     292         [ +  + ]:         14 :     for (i = 0; i < n; ++i, base += offset_size) {
     293         [ +  - ]:         10 :         check_result(verify_string(buf, end, base, read_uoffset(buf, base)));
     294                 :            :     }
     295                 :            :     return flatcc_verify_ok;
     296                 :            : }
     297                 :            : 
     298                 :        103 : static inline int verify_table(const void *buf, uoffset_t end, uoffset_t base, uoffset_t offset, int ttl, flatcc_table_verifier_f tvf)
     299                 :            : {
     300                 :            :     uoffset_t vbase, vend;
     301                 :            :     flatcc_table_verifier_descriptor_t td;
     302                 :            : 
     303         [ +  - ]:        103 :     verify((td.ttl = ttl - 1), flatcc_verify_error_max_nesting_level_reached);
     304         [ +  - ]:        103 :     verify(check_header(end, base, offset), flatcc_verify_error_table_header_out_of_range_or_unaligned);
     305                 :        103 :     td.table = base + offset;
     306                 :            :     /* Read vtable offset - it is signed, but we want it unsigned, assuming 2's complement works. */
     307                 :        103 :     vbase = td.table - read_uoffset(buf, td.table);
     308 [ +  - ][ -  + ]:        103 :     verify((soffset_t)vbase >= 0 && !(vbase & (voffset_size - 1)), flatcc_verify_error_vtable_offset_out_of_range_or_unaligned);
                 [ +  - ]
     309         [ +  - ]:        103 :     verify(vbase + voffset_size <= end, flatcc_verify_error_vtable_header_out_of_range);
     310                 :            :     /* Read vtable size. */
     311                 :        103 :     td.vsize = read_voffset(buf, vbase);
     312                 :        103 :     vend = vbase + td.vsize;
     313 [ +  + ][ -  + ]:        103 :     verify(vend <= end && !(td.vsize & (voffset_size - 1)), flatcc_verify_error_vtable_size_out_of_range_or_unaligned);
                 [ +  + ]
     314                 :            :     /* Optimizes away overflow check if uoffset_t is large enough. */
     315                 :            :     verify(uoffset_size > voffset_size || vend >= vbase, flatcc_verify_error_vtable_size_overflow);
     316                 :            : 
     317         [ +  - ]:        102 :     verify(td.vsize >= 2 * voffset_size, flatcc_verify_error_vtable_header_too_small);
     318                 :            :     /* Read table size. */
     319                 :        204 :     td.tsize = read_voffset(buf, vbase + voffset_size);
     320         [ +  - ]:        102 :     verify(end - td.table >= td.tsize, flatcc_verify_error_table_size_out_of_range);
     321                 :        102 :     td.vtable = (uint8_t *)buf + vbase;
     322                 :        102 :     td.buf = buf;
     323                 :        102 :     td.end = end;
     324                 :        102 :     return tvf(&td);
     325                 :            : }
     326                 :            : 
     327                 :          5 : static inline int verify_table_vector(const void *buf, uoffset_t end, uoffset_t base, uoffset_t offset, int ttl, flatcc_table_verifier_f tvf)
     328                 :            : {
     329                 :            :     uoffset_t i, n;
     330                 :            : 
     331         [ +  - ]:          5 :     verify(ttl-- > 0, flatcc_verify_error_max_nesting_level_reached);
     332         [ -  + ]:          5 :     check_result(verify_vector(buf, end, base, offset, offset_size, offset_size, FLATBUFFERS_COUNT_MAX(offset_size)));
     333                 :            :     base += offset;
     334                 :            :     n = read_uoffset(buf, base);
     335                 :          5 :     base += offset_size;
     336         [ +  + ]:         27 :     for (i = 0; i < n; ++i, base += offset_size) {
     337         [ -  + ]:         22 :         check_result(verify_table(buf, end, base, read_uoffset(buf, base), ttl, tvf));
     338                 :            :     }
     339                 :            :     return flatcc_verify_ok;
     340                 :            : }
     341                 :            : 
     342                 :       1245 : int flatcc_verify_field(flatcc_table_verifier_descriptor_t *td,
     343                 :            :         voffset_t id, uint16_t align, size_t size)
     344                 :            : {
     345         [ -  + ]:       1245 :     check_result(verify_field(td, id, 0, align, (uoffset_t)size));
     346                 :            :     return flatcc_verify_ok;
     347                 :            : }
     348                 :            : 
     349                 :         99 : int flatcc_verify_string_field(flatcc_table_verifier_descriptor_t *td,
     350                 :            :         voffset_t id, int required)
     351                 :            : {
     352                 :            :     uoffset_t base;
     353                 :            : 
     354 [ +  - ][ +  + ]:         99 :     check_field(td, id, required, base);
     355                 :         96 :     return verify_string(td->buf, td->end, base, read_uoffset(td->buf, base));
     356                 :            : }
     357                 :            : 
     358                 :        380 : int flatcc_verify_vector_field(flatcc_table_verifier_descriptor_t *td,
     359                 :            :         voffset_t id, int required, uint16_t align, size_t elem_size, size_t max_count)
     360                 :            : {
     361                 :            :     uoffset_t base;
     362                 :            : 
     363 [ +  - ][ +  + ]:        380 :     check_field(td, id, required, base);
     364                 :         24 :     return verify_vector(td->buf, td->end, base, read_uoffset(td->buf, base),
     365                 :            :         align, (uoffset_t)elem_size, (uoffset_t)max_count);
     366                 :            : }
     367                 :            : 
     368                 :         95 : int flatcc_verify_string_vector_field(flatcc_table_verifier_descriptor_t *td,
     369                 :            :     voffset_t id, int required)
     370                 :            : {
     371                 :            :     uoffset_t base;
     372                 :            : 
     373 [ +  - ][ +  + ]:         95 :     check_field(td, id, required, base);
     374                 :          4 :     return verify_string_vector(td->buf, td->end, base, read_uoffset(td->buf, base));
     375                 :            : }
     376                 :            : 
     377                 :        299 : int flatcc_verify_table_field(flatcc_table_verifier_descriptor_t *td,
     378                 :            :     voffset_t id, int required, flatcc_table_verifier_f tvf)
     379                 :            : {
     380                 :            :     uoffset_t base;
     381                 :            : 
     382 [ +  - ][ +  + ]:        299 :     check_field(td, id, required, base);
     383                 :         20 :     return verify_table(td->buf, td->end, base, read_uoffset(td->buf, base), td->ttl, tvf);
     384                 :            : }
     385                 :            : 
     386                 :         95 : int flatcc_verify_table_vector_field(flatcc_table_verifier_descriptor_t *td,
     387                 :            :         voffset_t id, int required, flatcc_table_verifier_f tvf)
     388                 :            : {
     389                 :            :     uoffset_t base;
     390                 :            : 
     391 [ +  - ][ +  + ]:         95 :     check_field(td, id, required, base);
     392                 :          5 :     return verify_table_vector(td->buf, td->end, base, read_uoffset(td->buf, base), td->ttl, tvf);
     393                 :            : }
     394                 :            : 
     395                 :         60 : int flatcc_verify_buffer_header(const void *buf, size_t bufsiz, const char *fid)
     396                 :            : {
     397                 :            :     thash_t id, id2;
     398                 :            : 
     399         [ +  - ]:         60 :     verify_runtime(!(((size_t)buf) & (offset_size - 1)), flatcc_verify_error_runtime_buffer_header_not_aligned);
     400                 :            :     /* -8 ensures no scalar or offset field size can overflow. */
     401         [ +  - ]:         60 :     verify_runtime(bufsiz <= FLATBUFFERS_UOFFSET_MAX - 8, flatcc_verify_error_runtime_buffer_size_too_large);
     402                 :            :     /*
     403                 :            :      * Even if we specify no fid, the user might later. Therefore
     404                 :            :      * require space for it. Not all buffer generators will take this
     405                 :            :      * into account, so it is possible to fail an otherwise valid buffer
     406                 :            :      * - but such buffers aren't safe.
     407                 :            :      */
     408         [ +  - ]:         60 :     verify(bufsiz >= offset_size + FLATBUFFERS_IDENTIFIER_SIZE, flatcc_verify_error_buffer_header_too_small);
     409         [ +  + ]:         60 :     if (fid != 0) {
     410                 :            :         id2 = read_thash_identifier(fid);
     411                 :            :         id = read_thash(buf, offset_size);
     412         [ +  + ]:         58 :         verify(id2 == 0 || id == id2, flatcc_verify_error_identifier_mismatch);
     413                 :            :     }
     414                 :            :     return flatcc_verify_ok;
     415                 :            : }
     416                 :            : 
     417                 :          0 : int flatcc_verify_typed_buffer_header(const void *buf, size_t bufsiz, flatbuffers_thash_t thash)
     418                 :            : {
     419                 :            :     thash_t id, id2;
     420                 :            : 
     421 [ +  - ][ #  # ]:          5 :     verify_runtime(!(((size_t)buf) & (offset_size - 1)), flatcc_verify_error_runtime_buffer_header_not_aligned);
         [ +  - ][ #  # ]
                 [ #  # ]
     422                 :            :     /* -8 ensures no scalar or offset field size can overflow. */
     423 [ +  - ][ #  # ]:          5 :     verify_runtime(bufsiz <= FLATBUFFERS_UOFFSET_MAX - 8, flatcc_verify_error_runtime_buffer_size_too_large);
         [ +  - ][ #  # ]
                 [ #  # ]
     424                 :            :     /*
     425                 :            :      * Even if we specify no fid, the user might later. Therefore
     426                 :            :      * require space for it. Not all buffer generators will take this
     427                 :            :      * into account, so it is possible to fail an otherwise valid buffer
     428                 :            :      * - but such buffers aren't safe.
     429                 :            :      */
     430 [ +  - ][ #  # ]:          5 :     verify(bufsiz >= offset_size + FLATBUFFERS_IDENTIFIER_SIZE, flatcc_verify_error_buffer_header_too_small);
         [ +  - ][ #  # ]
                 [ #  # ]
     431 [ +  - ][ #  # ]:          5 :     if (thash != 0) {
         [ +  - ][ #  # ]
                 [ #  # ]
     432                 :            :         id2 = thash;
     433                 :            :         id = read_thash(buf, offset_size);
     434 [ +  - ][ #  # ]:          5 :         verify(id2 == 0 || id == id2, flatcc_verify_error_identifier_mismatch);
         [ +  - ][ #  # ]
                 [ #  # ]
     435                 :            :     }
     436                 :            :     return flatcc_verify_ok;
     437                 :            : }
     438                 :            : 
     439                 :          0 : int flatcc_verify_struct_as_root(const void *buf, size_t bufsiz, const char *fid, uint16_t align, size_t size)
     440                 :            : {
     441         [ #  # ]:          0 :     check_result(flatcc_verify_buffer_header(buf, bufsiz, fid));
     442                 :            :     return verify_struct((uoffset_t)bufsiz, read_uoffset(buf, 0), align, (uoffset_t)size);
     443                 :            : }
     444                 :            : 
     445                 :          2 : int flatcc_verify_struct_as_typed_root(const void *buf, size_t bufsiz, flatbuffers_thash_t thash, uint16_t align, size_t size)
     446                 :            : {
     447         [ -  + ]:          2 :     check_result(flatcc_verify_typed_buffer_header(buf, bufsiz, thash));
     448                 :            :     return verify_struct((uoffset_t)bufsiz, read_uoffset(buf, 0), align, (uoffset_t)size);
     449                 :            : }
     450                 :            : 
     451                 :         57 : int flatcc_verify_table_as_root(const void *buf, size_t bufsiz, const char *fid, flatcc_table_verifier_f *tvf)
     452                 :            : {
     453         [ +  + ]:         57 :     check_result(flatcc_verify_buffer_header(buf, (uoffset_t)bufsiz, fid));
     454                 :         56 :     return verify_table(buf, (uoffset_t)bufsiz, 0, read_uoffset(buf, 0), FLATCC_VERIFIER_MAX_LEVELS, tvf);
     455                 :            : }
     456                 :            : 
     457                 :          3 : int flatcc_verify_table_as_typed_root(const void *buf, size_t bufsiz, flatbuffers_thash_t thash, flatcc_table_verifier_f *tvf)
     458                 :            : {
     459         [ -  + ]:          3 :     check_result(flatcc_verify_typed_buffer_header(buf, (uoffset_t)bufsiz, thash));
     460                 :          3 :     return verify_table(buf, (uoffset_t)bufsiz, 0, read_uoffset(buf, 0), FLATCC_VERIFIER_MAX_LEVELS, tvf);
     461                 :            : }
     462                 :            : 
     463                 :          0 : int flatcc_verify_struct_as_nested_root(flatcc_table_verifier_descriptor_t *td,
     464                 :            :         voffset_t id, int required, const char *fid, uint16_t align, size_t size)
     465                 :            : {
     466                 :            :     const uoffset_t *buf;
     467                 :            :     uoffset_t bufsiz;
     468                 :            : 
     469         [ #  # ]:          0 :     check_result(flatcc_verify_vector_field(td, id, required, align, 1, FLATBUFFERS_COUNT_MAX(1)));
     470         [ #  # ]:          0 :     if (0 == (buf = get_field_ptr(td, id))) {
     471                 :            :         return flatcc_verify_ok;
     472                 :            :     }
     473                 :          0 :     buf = (const uoffset_t *)((size_t)buf + read_uoffset(buf, 0));
     474                 :            :     bufsiz = read_uoffset(buf, 0);
     475                 :          0 :     ++buf;
     476                 :          0 :     return flatcc_verify_struct_as_root(buf, bufsiz, fid, align, size);
     477                 :            : }
     478                 :            : 
     479                 :         95 : int flatcc_verify_table_as_nested_root(flatcc_table_verifier_descriptor_t *td,
     480                 :            :         voffset_t id, int required, const char *fid,
     481                 :            :         uint16_t align, flatcc_table_verifier_f tvf)
     482                 :            : {
     483                 :            :     const uoffset_t *buf;
     484                 :            :     uoffset_t bufsiz;
     485                 :            : 
     486         [ -  + ]:         95 :     check_result(flatcc_verify_vector_field(td, id, required, align, 1, FLATBUFFERS_COUNT_MAX(1)));
     487         [ +  + ]:         95 :     if (0 == (buf = get_field_ptr(td, id))) {
     488                 :            :         return flatcc_verify_ok;
     489                 :            :     }
     490                 :          2 :     buf = (const uoffset_t *)((size_t)buf + read_uoffset(buf, 0));
     491                 :            :     bufsiz = read_uoffset(buf, 0);
     492                 :          2 :     ++buf;
     493                 :            :     /*
     494                 :            :      * Don't verify nested buffers identifier - information is difficult to get and
     495                 :            :      * might not be what is desired anyway. User can do it later.
     496                 :            :      */
     497         [ -  + ]:          2 :     check_result(flatcc_verify_buffer_header(buf, bufsiz, fid));
     498                 :          2 :     return verify_table(buf, bufsiz, 0, read_uoffset(buf, 0), td->ttl, tvf);
     499                 :            : }
     500                 :            : 
     501                 :         95 : int flatcc_verify_union_field(flatcc_table_verifier_descriptor_t *td,
     502                 :            :         voffset_t id, int required, flatcc_union_verifier_f *uvf)
     503                 :            : {
     504                 :            :     voffset_t vte_type, vte_table;
     505                 :            :     const uint8_t *type;
     506                 :            : 
     507         [ +  + ]:         95 :     if (0 == (vte_type = read_vt_entry(td, id - 1))) {
     508                 :        162 :         vte_table = read_vt_entry(td, id);
     509         [ +  - ]:         81 :         verify(vte_table == 0, flatcc_verify_error_union_cannot_have_a_table_without_a_type);
     510         [ +  - ]:         81 :         verify(!required, flatcc_verify_error_type_field_absent_from_required_union_field);
     511                 :         81 :         return flatcc_verify_ok;
     512                 :            :     }
     513                 :            :     /* No need to check required here. */
     514         [ -  + ]:         14 :     check_result(verify_field(td, id - 1, 0, 1, 1));
     515                 :            :     /* Only now is it safe to read the type. */
     516                 :         28 :     vte_table = read_vt_entry(td, id);
     517                 :         14 :     type = (const uint8_t *)td->buf + td->table + vte_type;
     518 [ -  + ][ #  # ]:         14 :     verify(*type || vte_table == 0, flatcc_verify_error_union_type_NONE_cannot_have_a_table);
                 [ +  - ]
     519                 :         14 :     return uvf(td, id, *type);
     520                 :            : }

Generated by: LCOV version 1.12