damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

flatcc_verifier.h (10906B)


      1 #ifndef FLATCC_VERIFIER_H
      2 #define FLATCC_VERIFIER_H
      3 
      4 #ifdef __cplusplus
      5 extern "C" {
      6 #endif
      7 
      8 /*
      9  * Runtime support for verifying flatbuffers.
     10  *
     11  * Link with the verifier implementation file.
     12  *
     13  * Note:
     14  *
     15  * 1) nested buffers will NOT have their identifier verified.
     16  * The user may do so subsequently. The reason is in part because
     17  * the information is not readily avaible without generated reader code,
     18  * in part because the buffer might use a different, but valid,
     19  * identifier and the user has no chance of specifiying this in the
     20  * verifier code. The root verifier also doesn't assume a specific id
     21  * but accepts a user supplied input which may be null.
     22  *
     23  * 2) All offsets in a buffer are verified for alignment relative to the
     24  * buffer start, but the buffer itself is only assumed to aligned to
     25  * uoffset_t. A reader should therefore ensure buffer alignment separately
     26  * before reading the buffer. Nested buffers are in fact checked for
     27  * alignment, but still only relative to the root buffer.
     28  *
     29  * 3) The max nesting level includes nested buffer nestings, so the
     30  * verifier might fail even if the individual buffers are otherwise ok.
     31  * This is to prevent abuse with lots of nested buffers.
     32  *
     33  *
     34  * IMPORTANT:
     35  *
     36  * Even if verifier passes, the buffer may be invalid to access due to
     37  * lack of alignemnt in memory, but the verifier is safe to call.
     38  *
     39  * NOTE: The buffer is not safe to modify after verification because an
     40  * attacker may craft overlapping data structures such that modification
     41  * of one field updates another in a way that violates the buffer
     42  * constraints. This may also be caused by a clever compression scheme.
     43  *
     44  * It is likely faster to rewrite the table although this is also
     45  * dangerous because an attacker (or even normal user) can draft a DAG
     46  * that explodes when expanded carelesslessly. A safer approach is to
     47  * hash all object references written and reuse those that match. This
     48  * will expand references into other objects while bounding expansion
     49  * and it will be safe to update assuming shared objects are ok to
     50  * update.
     51  *
     52  */
     53 
     54 #include "flatcc_types.h"
     55 
     56 #define FLATCC_VERIFY_ERROR_MAP(XX)\
     57     XX(ok, "ok")\
     58     XX(buffer_header_too_small, "buffer header too small")\
     59     XX(identifier_mismatch, "identifier mismatch")\
     60     XX(max_nesting_level_reached, "max nesting level reached")\
     61     XX(required_field_missing, "required field missing")\
     62     XX(runtime_buffer_header_not_aligned, "runtime: buffer header not aligned")\
     63     XX(runtime_buffer_size_too_large, "runtime: buffer size too large")\
     64     XX(string_not_zero_terminated, "string not zero terminated")\
     65     XX(string_out_of_range, "string out of range")\
     66     XX(struct_out_of_range, "struct out of range")\
     67     XX(struct_size_overflow, "struct size overflow")\
     68     XX(struct_unaligned, "struct unaligned")\
     69     XX(table_field_not_aligned, "table field not aligned")\
     70     XX(table_field_out_of_range, "table field out of range")\
     71     XX(table_field_size_overflow, "table field size overflow")\
     72     XX(table_header_out_of_range_or_unaligned, "table header out of range or unaligned")\
     73     XX(vector_header_out_of_range_or_unaligned, "vector header out of range or unaligned")\
     74     XX(string_header_out_of_range_or_unaligned, "string header out of range or unaligned")\
     75     XX(offset_out_of_range, "offset out of range")\
     76     XX(table_offset_out_of_range_or_unaligned, "table offset out of range or unaligned")\
     77     XX(table_size_out_of_range, "table size out of range")\
     78     XX(type_field_absent_from_required_union_field, "type field absent from required union field")\
     79     XX(type_field_absent_from_required_union_vector_field, "type field absent from required union vector field")\
     80     XX(union_cannot_have_a_table_without_a_type, "union cannot have a table without a type")\
     81     XX(union_type_NONE_cannot_have_a_value, "union value field present with type NONE")\
     82     XX(vector_count_exceeds_representable_vector_size, "vector count exceeds representable vector size")\
     83     XX(vector_out_of_range, "vector out of range")\
     84     XX(vtable_header_out_of_range, "vtable header out of range")\
     85     XX(vtable_header_too_small, "vtable header too small")\
     86     XX(vtable_offset_out_of_range_or_unaligned, "vtable offset out of range or unaligned")\
     87     XX(vtable_size_out_of_range_or_unaligned, "vtable size out of range or unaligned")\
     88     XX(vtable_size_overflow, "vtable size overflow")\
     89     XX(union_element_absent_without_type_NONE, "union element absent without type NONE")\
     90     XX(union_element_present_with_type_NONE, "union element present with type NONE")\
     91     XX(union_vector_length_mismatch, "union type and table vectors have different lengths")\
     92     XX(union_vector_verification_not_supported, "union vector verification not supported")\
     93     XX(not_supported, "not supported")
     94 
     95 
     96 enum flatcc_verify_error_no {
     97 #define XX(no, str) flatcc_verify_error_##no,
     98     FLATCC_VERIFY_ERROR_MAP(XX)
     99 #undef XX
    100 };
    101 
    102 #define flatcc_verify_ok flatcc_verify_error_ok
    103 
    104 const char *flatcc_verify_error_string(int err);
    105 
    106 /*
    107  * Type specific table verifier function that checks each known field
    108  * for existence in the vtable and then calls the appropriate verifier
    109  * function in this library.
    110  *
    111  * The table descriptor values have been verified for bounds, overflow,
    112  * and alignment, but vtable entries after header must be verified
    113  * for all fields the table verifier function understands.
    114  *
    115  * Calls other typespecific verifier functions recursively whenever a
    116  * table field, union or table vector is encountered.
    117  */
    118 typedef struct flatcc_table_verifier_descriptor flatcc_table_verifier_descriptor_t;
    119 struct flatcc_table_verifier_descriptor {
    120     /* Pointer to buffer. Not assumed to be aligned beyond uoffset_t. */
    121     const void *buf;
    122     /* Buffer size. */
    123     flatbuffers_uoffset_t end;
    124     /* Time to live: number nesting levels left before failure. */
    125     int ttl;
    126     /* Vtable of current table. */
    127     const void *vtable;
    128     /* Table offset relative to buffer start */
    129     flatbuffers_uoffset_t table;
    130     /* Table end relative to buffer start as per vtable[1] field. */
    131     flatbuffers_voffset_t tsize;
    132     /* Size of vtable in bytes. */
    133     flatbuffers_voffset_t vsize;
    134 };
    135 
    136 typedef int flatcc_table_verifier_f(flatcc_table_verifier_descriptor_t *td);
    137 
    138 typedef struct flatcc_union_verifier_descriptor flatcc_union_verifier_descriptor_t;
    139 
    140 struct flatcc_union_verifier_descriptor {
    141     /* Pointer to buffer. Not assumed to be aligned beyond uoffset_t. */
    142     const void *buf;
    143     /* Buffer size. */
    144     flatbuffers_uoffset_t end;
    145     /* Time to live: number nesting levels left before failure. */
    146     int ttl;
    147     /* Type of union value to be verified */
    148     flatbuffers_utype_t type;
    149     /* Offset relative to buffer start to where union value offset is stored. */
    150     flatbuffers_uoffset_t base;
    151     /* Offset of union value relative to base. */
    152     flatbuffers_uoffset_t offset;
    153 };
    154 
    155 typedef int flatcc_union_verifier_f(flatcc_union_verifier_descriptor_t *ud);
    156 
    157 /*
    158  * The `as_root` functions are normally the only functions called
    159  * explicitly in this interface.
    160  *
    161  * If `fid` is null, the identifier is not checked and is allowed to be entirely absent.
    162  *
    163  * The buffer must at least be aligned to uoffset_t on systems that
    164  * require aligned memory addresses. The buffer pointers alignment is
    165  * not significant to internal verification of the buffer.
    166  */
    167 int flatcc_verify_struct_as_root(const void *buf, size_t bufsiz, const char *fid,
    168         size_t size, uint16_t align);
    169 
    170 int flatcc_verify_struct_as_typed_root(const void *buf, size_t bufsiz, flatbuffers_thash_t thash,
    171         size_t size, uint16_t align);
    172 
    173 int flatcc_verify_table_as_root(const void *buf, size_t bufsiz, const char *fid,
    174         flatcc_table_verifier_f *root_tvf);
    175 
    176 int flatcc_verify_table_as_typed_root(const void *buf, size_t bufsiz, flatbuffers_thash_t thash,
    177         flatcc_table_verifier_f *root_tvf);
    178 /*
    179  * The buffer header is verified by any of the `_as_root` verifiers, but
    180  * this function may be used as a quick sanity check.
    181  */
    182 int flatcc_verify_buffer_header(const void *buf, size_t bufsiz, const char *fid);
    183 
    184 int flatcc_verify_typed_buffer_header(const void *buf, size_t bufsiz, flatbuffers_thash_t type_hash);
    185 
    186 /*
    187  * The following functions are typically called by a generated table
    188  * verifier function.
    189  */
    190 
    191 /* Scalar, enum or struct field. */
    192 int flatcc_verify_field(flatcc_table_verifier_descriptor_t *td,
    193         flatbuffers_voffset_t id, size_t size, uint16_t align);
    194 /* Vector of scalars, enums or structs. */
    195 int flatcc_verify_vector_field(flatcc_table_verifier_descriptor_t *td,
    196         flatbuffers_voffset_t id, int required, size_t elem_size, uint16_t align, size_t max_count);
    197 int flatcc_verify_string_field(flatcc_table_verifier_descriptor_t *td,
    198         flatbuffers_voffset_t id, int required);
    199 int flatcc_verify_string_vector_field(flatcc_table_verifier_descriptor_t *td,
    200         flatbuffers_voffset_t id, int required);
    201 int flatcc_verify_table_field(flatcc_table_verifier_descriptor_t *td,
    202     flatbuffers_voffset_t id, int required, flatcc_table_verifier_f tvf);
    203 int flatcc_verify_table_vector_field(flatcc_table_verifier_descriptor_t *td,
    204     flatbuffers_voffset_t id, int required, flatcc_table_verifier_f tvf);
    205 /* Table verifiers pass 0 as fid. */
    206 int flatcc_verify_struct_as_nested_root(flatcc_table_verifier_descriptor_t *td,
    207         flatbuffers_voffset_t id, int required, const char *fid,
    208         size_t size, uint16_t align);
    209 int flatcc_verify_table_as_nested_root(flatcc_table_verifier_descriptor_t *td,
    210         flatbuffers_voffset_t id, int required, const char *fid,
    211         uint16_t align, flatcc_table_verifier_f tvf);
    212 
    213 /*
    214  * A NONE type will not accept a table being present, and a required
    215  * union will not accept a type field being absent, and an absent type
    216  * field will not accept a table field being present.
    217  *
    218  * If the above checks out and the type is not NONE, the uvf callback
    219  * is executed. It must test each known table type and silently accept
    220  * any unknown table type for forward compatibility. A union table
    221  * value is verified without the required flag because an absent table
    222  * encodes a typed NULL value while an absent type field encodes a
    223  * missing union which fails if required.
    224  */
    225 int flatcc_verify_union_field(flatcc_table_verifier_descriptor_t *td,
    226         flatbuffers_voffset_t id, int required, flatcc_union_verifier_f uvf);
    227 
    228 int flatcc_verify_union_vector_field(flatcc_table_verifier_descriptor_t *td,
    229     flatbuffers_voffset_t id, int required, flatcc_union_verifier_f uvf);
    230 
    231 int flatcc_verify_union_table(flatcc_union_verifier_descriptor_t *ud, flatcc_table_verifier_f *tvf);
    232 int flatcc_verify_union_struct(flatcc_union_verifier_descriptor_t *ud, size_t size, uint16_t align);
    233 int flatcc_verify_union_string(flatcc_union_verifier_descriptor_t *ud);
    234 
    235 #ifdef __cplusplus
    236 }
    237 #endif
    238 
    239 #endif /* FLATCC_VERIFIER_H */