Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
flatbuffers
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
flatbuffers
Commits
377a8ba6
Commit
377a8ba6
authored
Dec 20, 2016
by
Wouter van Oortmerssen
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
https://github.com/google/flatbuffers
parents
13cf6e66
6d6271db
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
295 additions
and
11 deletions
+295
-11
CMakeLists.txt
CMakeLists.txt
+3
-0
flatbuffers.h
include/flatbuffers/flatbuffers.h
+37
-8
reflection.h
include/flatbuffers/reflection.h
+9
-0
reflection.cpp
src/reflection.cpp
+226
-0
test.cpp
tests/test.cpp
+20
-3
No files found.
CMakeLists.txt
View file @
377a8ba6
...
...
@@ -203,6 +203,9 @@ if(FLATBUFFERS_BUILD_TESTS)
compile_flatbuffers_schema_to_cpp
(
tests/monster_test.fbs
)
include_directories
(
${
CMAKE_CURRENT_BINARY_DIR
}
/tests
)
add_executable
(
flattests
${
FlatBuffers_Tests_SRCS
}
)
set_property
(
TARGET flattests
PROPERTY COMPILE_DEFINITIONS FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
FLATBUFFERS_DEBUG_VERIFICATION_FAILURE=1
)
compile_flatbuffers_schema_to_cpp
(
samples/monster.fbs
)
include_directories
(
${
CMAKE_CURRENT_BINARY_DIR
}
/samples
)
...
...
include/flatbuffers/flatbuffers.h
View file @
377a8ba6
...
...
@@ -252,9 +252,9 @@ template<typename T> struct IndirectHelper<const T *> {
// calling Get() for every element.
template
<
typename
T
,
typename
IT
>
struct
VectorIterator
:
public
std
::
iterator
<
std
::
input
_iterator_tag
,
IT
,
uoffset_t
>
{
:
public
std
::
iterator
<
std
::
random_access
_iterator_tag
,
IT
,
uoffset_t
>
{
typedef
std
::
iterator
<
std
::
input
_iterator_tag
,
IT
,
uoffset_t
>
super_type
;
typedef
std
::
iterator
<
std
::
random_access
_iterator_tag
,
IT
,
uoffset_t
>
super_type
;
public
:
VectorIterator
(
const
uint8_t
*
data
,
uoffset_t
i
)
:
...
...
@@ -274,15 +274,15 @@ public:
return
*
this
;
}
bool
operator
==
(
const
VectorIterator
&
other
)
const
{
bool
operator
==
(
const
VectorIterator
&
other
)
const
{
return
data_
==
other
.
data_
;
}
bool
operator
!=
(
const
VectorIterator
&
other
)
const
{
bool
operator
!=
(
const
VectorIterator
&
other
)
const
{
return
data_
!=
other
.
data_
;
}
ptrdiff_t
operator
-
(
const
VectorIterator
&
other
)
const
{
ptrdiff_t
operator
-
(
const
VectorIterator
&
other
)
const
{
return
(
data_
-
other
.
data_
)
/
IndirectHelper
<
T
>::
element_stride
;
}
...
...
@@ -300,11 +300,40 @@ public:
}
VectorIterator
operator
++
(
int
)
{
VectorIterator
temp
(
data_
,
0
);
VectorIterator
temp
(
data_
,
0
);
data_
+=
IndirectHelper
<
T
>::
element_stride
;
return
temp
;
}
VectorIterator
operator
+
(
const
uoffset_t
&
offset
)
{
return
VectorIterator
(
data_
+
offset
*
IndirectHelper
<
T
>::
element_stride
,
0
);
}
VectorIterator
&
operator
+=
(
const
uoffset_t
&
offset
)
{
data_
+=
offset
*
IndirectHelper
<
T
>::
element_stride
;
return
*
this
;
}
VectorIterator
&
operator
--
()
{
data_
-=
IndirectHelper
<
T
>::
element_stride
;
return
*
this
;
}
VectorIterator
operator
--
(
int
)
{
VectorIterator
temp
(
data_
,
0
);
data_
-=
IndirectHelper
<
T
>::
element_stride
;
return
temp
;
}
VectorIterator
operator
-
(
const
uoffset_t
&
offset
)
{
return
VectorIterator
(
data_
-
offset
*
IndirectHelper
<
T
>::
element_stride
,
0
);
}
VectorIterator
&
operator
-=
(
const
uoffset_t
&
offset
)
{
data_
-=
offset
*
IndirectHelper
<
T
>::
element_stride
;
return
*
this
;
}
private
:
const
uint8_t
*
data_
;
};
...
...
@@ -1453,9 +1482,9 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
size_t
max_depth_
;
size_t
num_tables_
;
size_t
max_tables_
;
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
mutable
const
uint8_t
*
upper_bound_
;
#endif
#endif
};
// Convenient way to bundle a buffer and its length, to pass it around
...
...
include/flatbuffers/reflection.h
View file @
377a8ba6
...
...
@@ -428,6 +428,15 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
const
Table
&
table
,
bool
use_string_pooling
=
false
);
// Verifies the provided flatbuffer using reflection.
// root should point to the root type for this flatbuffer.
// buf should point to the start of flatbuffer data.
// length specifies the size of the flatbuffer data.
bool
Verify
(
const
reflection
::
Schema
&
schema
,
const
reflection
::
Object
&
root
,
const
uint8_t
*
buf
,
size_t
length
);
}
// namespace flatbuffers
#endif // FLATBUFFERS_REFLECTION_H_
src/reflection.cpp
View file @
377a8ba6
...
...
@@ -481,4 +481,230 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
}
}
bool
VerifyStruct
(
flatbuffers
::
Verifier
&
v
,
const
flatbuffers
::
Table
&
parent_table
,
voffset_t
field_offset
,
const
reflection
::
Object
&
obj
,
bool
required
)
{
auto
offset
=
parent_table
.
GetOptionalFieldOffset
(
field_offset
);
if
(
required
&&
!
offset
)
{
return
false
;
}
return
!
offset
||
v
.
Verify
(
reinterpret_cast
<
const
uint8_t
*>
(
&
parent_table
)
+
offset
,
obj
.
bytesize
());
}
bool
VerifyVectorOfStructs
(
flatbuffers
::
Verifier
&
v
,
const
flatbuffers
::
Table
&
parent_table
,
voffset_t
field_offset
,
const
reflection
::
Object
&
obj
,
bool
required
)
{
auto
p
=
parent_table
.
GetPointer
<
const
uint8_t
*>
(
field_offset
);
const
uint8_t
*
end
;
if
(
required
&&
!
p
)
{
return
false
;
}
return
!
p
||
v
.
VerifyVector
(
p
,
obj
.
bytesize
(),
&
end
);
}
// forward declare to resolve cyclic deps between VerifyObject and VerifyVector
bool
VerifyObject
(
flatbuffers
::
Verifier
&
v
,
const
reflection
::
Schema
&
schema
,
const
reflection
::
Object
&
obj
,
const
flatbuffers
::
Table
*
table
,
bool
isRequired
);
bool
VerifyVector
(
flatbuffers
::
Verifier
&
v
,
const
reflection
::
Schema
&
schema
,
const
flatbuffers
::
Table
&
table
,
const
reflection
::
Field
&
vec_field
)
{
assert
(
vec_field
.
type
()
->
base_type
()
==
reflection
::
BaseType
::
Vector
);
if
(
!
table
.
VerifyField
<
uoffset_t
>
(
v
,
vec_field
.
offset
()))
return
false
;
switch
(
vec_field
.
type
()
->
element
())
{
case
reflection
:
:
BaseType
::
None
:
assert
(
false
);
break
;
case
reflection
:
:
BaseType
::
UType
:
return
v
.
Verify
(
flatbuffers
::
GetFieldV
<
uint8_t
>
(
table
,
vec_field
));
case
reflection
:
:
BaseType
::
Bool
:
case
reflection
:
:
BaseType
::
Byte
:
case
reflection
:
:
BaseType
::
UByte
:
return
v
.
Verify
(
flatbuffers
::
GetFieldV
<
int8_t
>
(
table
,
vec_field
));
case
reflection
:
:
BaseType
::
Short
:
case
reflection
:
:
BaseType
::
UShort
:
return
v
.
Verify
(
flatbuffers
::
GetFieldV
<
int16_t
>
(
table
,
vec_field
));
case
reflection
:
:
BaseType
::
Int
:
case
reflection
:
:
BaseType
::
UInt
:
return
v
.
Verify
(
flatbuffers
::
GetFieldV
<
int32_t
>
(
table
,
vec_field
));
case
reflection
:
:
BaseType
::
Long
:
case
reflection
:
:
BaseType
::
ULong
:
return
v
.
Verify
(
flatbuffers
::
GetFieldV
<
int64_t
>
(
table
,
vec_field
));
case
reflection
:
:
BaseType
::
Float
:
return
v
.
Verify
(
flatbuffers
::
GetFieldV
<
float
>
(
table
,
vec_field
));
case
reflection
:
:
BaseType
::
Double
:
return
v
.
Verify
(
flatbuffers
::
GetFieldV
<
double
>
(
table
,
vec_field
));
case
reflection
:
:
BaseType
::
String
:
{
auto
vecString
=
flatbuffers
::
GetFieldV
<
flatbuffers
::
Offset
<
flatbuffers
::
String
>>
(
table
,
vec_field
);
if
(
v
.
Verify
(
vecString
)
&&
v
.
VerifyVectorOfStrings
(
vecString
))
{
return
true
;
}
else
{
return
false
;
}
}
case
reflection
:
:
BaseType
::
Vector
:
assert
(
false
);
break
;
case
reflection
:
:
BaseType
::
Obj
:
{
auto
obj
=
schema
.
objects
()
->
Get
(
vec_field
.
type
()
->
index
());
if
(
obj
->
is_struct
())
{
if
(
!
VerifyVectorOfStructs
(
v
,
table
,
vec_field
.
offset
(),
*
obj
,
vec_field
.
required
()))
{
return
false
;
}
}
else
{
auto
vec
=
flatbuffers
::
GetFieldV
<
flatbuffers
::
Offset
<
flatbuffers
::
Table
>>
(
table
,
vec_field
);
if
(
!
v
.
Verify
(
vec
))
return
false
;
if
(
vec
)
{
for
(
uoffset_t
j
=
0
;
j
<
vec
->
size
();
j
++
)
{
if
(
!
VerifyObject
(
v
,
schema
,
*
obj
,
vec
->
Get
(
j
),
true
))
{
return
false
;
}
}
}
}
return
true
;
}
case
reflection
:
:
BaseType
::
Union
:
assert
(
false
);
break
;
default:
assert
(
false
);
break
;
}
return
false
;
}
bool
VerifyObject
(
flatbuffers
::
Verifier
&
v
,
const
reflection
::
Schema
&
schema
,
const
reflection
::
Object
&
obj
,
const
flatbuffers
::
Table
*
table
,
bool
required
)
{
if
(
!
table
)
{
if
(
!
required
)
return
true
;
else
return
false
;
}
if
(
!
table
->
VerifyTableStart
(
v
))
return
false
;
for
(
size_t
i
=
0
;
i
<
obj
.
fields
()
->
size
();
i
++
)
{
auto
field_def
=
obj
.
fields
()
->
Get
(
i
);
switch
(
field_def
->
type
()
->
base_type
())
{
case
reflection
:
:
BaseType
::
None
:
assert
(
false
);
break
;
case
reflection
:
:
BaseType
::
UType
:
if
(
!
table
->
VerifyField
<
uint8_t
>
(
v
,
field_def
->
offset
()))
return
false
;
break
;
case
reflection
:
:
BaseType
::
Bool
:
case
reflection
:
:
BaseType
::
Byte
:
case
reflection
:
:
BaseType
::
UByte
:
if
(
!
table
->
VerifyField
<
int8_t
>
(
v
,
field_def
->
offset
()))
return
false
;
break
;
case
reflection
:
:
BaseType
::
Short
:
case
reflection
:
:
BaseType
::
UShort
:
if
(
!
table
->
VerifyField
<
int16_t
>
(
v
,
field_def
->
offset
()))
return
false
;
break
;
case
reflection
:
:
BaseType
::
Int
:
case
reflection
:
:
BaseType
::
UInt
:
if
(
!
table
->
VerifyField
<
int32_t
>
(
v
,
field_def
->
offset
()))
return
false
;
break
;
case
reflection
:
:
BaseType
::
Long
:
case
reflection
:
:
BaseType
::
ULong
:
if
(
!
table
->
VerifyField
<
int64_t
>
(
v
,
field_def
->
offset
()))
return
false
;
break
;
case
reflection
:
:
BaseType
::
Float
:
if
(
!
table
->
VerifyField
<
float
>
(
v
,
field_def
->
offset
()))
return
false
;
break
;
case
reflection
:
:
BaseType
::
Double
:
if
(
!
table
->
VerifyField
<
double
>
(
v
,
field_def
->
offset
()))
return
false
;
break
;
case
reflection
:
:
BaseType
::
String
:
if
(
!
table
->
VerifyField
<
uoffset_t
>
(
v
,
field_def
->
offset
())
||
!
v
.
Verify
(
flatbuffers
::
GetFieldS
(
*
table
,
*
field_def
)))
{
return
false
;
}
break
;
case
reflection
:
:
BaseType
::
Vector
:
if
(
!
VerifyVector
(
v
,
schema
,
*
table
,
*
field_def
))
return
false
;
break
;
case
reflection
:
:
BaseType
::
Obj
:
{
auto
child_obj
=
schema
.
objects
()
->
Get
(
field_def
->
type
()
->
index
());
if
(
child_obj
->
is_struct
())
{
if
(
!
VerifyStruct
(
v
,
*
table
,
field_def
->
offset
(),
*
child_obj
,
field_def
->
required
()))
{
return
false
;
}
}
else
{
if
(
!
VerifyObject
(
v
,
schema
,
*
child_obj
,
flatbuffers
::
GetFieldT
(
*
table
,
*
field_def
),
field_def
->
required
()))
{
return
false
;
}
}
break
;
}
case
reflection
:
:
BaseType
::
Union
:
{
// get union type from the prev field
voffset_t
utype_offset
=
field_def
->
offset
()
-
sizeof
(
voffset_t
);
auto
utype
=
table
->
GetField
<
uint8_t
>
(
utype_offset
,
0
);
if
(
utype
!=
0
)
{
// Means we have this union field present
auto
fb_enum
=
schema
.
enums
()
->
Get
(
field_def
->
type
()
->
index
());
auto
child_obj
=
fb_enum
->
values
()
->
Get
(
utype
)
->
object
();
if
(
!
VerifyObject
(
v
,
schema
,
*
child_obj
,
flatbuffers
::
GetFieldT
(
*
table
,
*
field_def
),
field_def
->
required
()))
{
return
false
;
}
}
break
;
}
default:
assert
(
false
);
break
;
}
}
return
true
;
}
bool
Verify
(
const
reflection
::
Schema
&
schema
,
const
reflection
::
Object
&
root
,
const
uint8_t
*
buf
,
size_t
length
)
{
Verifier
v
(
buf
,
length
);
return
VerifyObject
(
v
,
schema
,
root
,
flatbuffers
::
GetAnyRoot
(
buf
),
true
);
}
}
// namespace flatbuffers
tests/test.cpp
View file @
377a8ba6
...
...
@@ -14,9 +14,6 @@
* limitations under the License.
*/
#define FLATBUFFERS_DEBUG_VERIFICATION_FAILURE 1
#define FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
...
...
@@ -493,8 +490,15 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) {
TEST_NOTNULL
(
pos_table_ptr
);
TEST_EQ_STR
(
pos_table_ptr
->
name
()
->
c_str
(),
"MyGame.Example.Vec3"
);
// Now use it to dynamically access a buffer.
auto
&
root
=
*
flatbuffers
::
GetAnyRoot
(
flatbuf
);
// Verify the buffer first using reflection based verification
TEST_EQ
(
flatbuffers
::
Verify
(
schema
,
*
schema
.
root_table
(),
flatbuf
,
length
),
true
);
auto
hp
=
flatbuffers
::
GetFieldI
<
uint16_t
>
(
root
,
hp_field
);
TEST_EQ
(
hp
,
80
);
...
...
@@ -523,6 +527,10 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) {
hp_int64
=
flatbuffers
::
GetAnyFieldI
(
root
,
hp_field
);
TEST_EQ
(
hp_int64
,
300
);
// Test buffer is valid after the modifications
TEST_EQ
(
flatbuffers
::
Verify
(
schema
,
*
schema
.
root_table
(),
flatbuf
,
length
),
true
);
// Reset it, for further tests.
flatbuffers
::
SetField
<
uint16_t
>
(
&
root
,
hp_field
,
80
);
...
...
@@ -584,6 +592,11 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) {
reinterpret_cast
<
const
uint8_t
*>
(
resizingbuf
.
data
()),
resizingbuf
.
size
());
TEST_EQ
(
VerifyMonsterBuffer
(
resize_verifier
),
true
);
// Test buffer is valid using reflection as well
TEST_EQ
(
flatbuffers
::
Verify
(
schema
,
*
schema
.
root_table
(),
resizingbuf
.
data
(),
resizingbuf
.
size
()),
true
);
// As an additional test, also set it on the name field.
// Note: unlike the name change above, this just overwrites the offset,
// rather than changing the string in-place.
...
...
@@ -600,6 +613,10 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) {
fbb
.
Finish
(
root_offset
,
MonsterIdentifier
());
// Test that it was copied correctly:
AccessFlatBufferTest
(
fbb
.
GetBufferPointer
(),
fbb
.
GetSize
());
// Test buffer is valid using reflection as well
TEST_EQ
(
flatbuffers
::
Verify
(
schema
,
*
schema
.
root_table
(),
fbb
.
GetBufferPointer
(),
fbb
.
GetSize
()),
true
);
}
// Parse a .proto schema, output as .fbs
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment