pyuavcan: DSDL length validation

This commit is contained in:
Pavel Kirienko
2015-04-30 11:50:01 +03:00
parent 898fe67225
commit 0ea4e5e4e0
6 changed files with 38 additions and 44 deletions
@@ -8,4 +8,4 @@ uint8 PROTOCOL_ID_RTCM2 = 2
uint8 PROTOCOL_ID_RTCM3 = 3
uint8 protocol_id
uint8[<=400] data
uint8[<=100] data
@@ -41,7 +41,7 @@ TEST(Dsdl, Streaming)
os << get_node_info_rsp << std::endl << "==========" << std::endl;
root_ns_a::Deep ps;
ps.a.resize(2);
ps.a.resize(1);
os << ps << std::endl << "==========" << std::endl;
static const std::string Reference =
@@ -81,45 +81,19 @@ TEST(Dsdl, Streaming)
" scalar: 0\n"
" vector: \n"
" - \n"
" vector: [0, 0, 0, 0]\n"
" vector: [0, 0]\n"
" bools: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
" - \n"
" vector: [0, 0, 0, 0]\n"
" bools: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
" - \n"
" vector: [0, 0, 0, 0]\n"
" bools: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
" - \n"
" scalar: 0\n"
" vector: \n"
" - \n"
" vector: [0, 0, 0, 0]\n"
" bools: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
" - \n"
" vector: [0, 0, 0, 0]\n"
" bools: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
" - \n"
" vector: [0, 0, 0, 0]\n"
" vector: [0, 0]\n"
" bools: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
"b: \n"
" - \n"
" vector: [0, 0, 0, 0]\n"
" vector: [0, 0]\n"
" bools: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
" - \n"
" vector: [0, 0, 0, 0]\n"
" bools: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
" - \n"
" vector: [0, 0, 0, 0]\n"
" vector: [0, 0]\n"
" bools: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
"==========\n";
std::cout << os.str();
ASSERT_EQ(Reference, os.str());
}
TEST(Dsdl, OStream)
{
root_ns_a::Deep ps;
ps.a.resize(2);
uavcan::OStream::instance() << ps << uavcan::OStream::endl;
}
+1 -1
View File
@@ -5,4 +5,4 @@
#
float32 scalar
B[3] vector
B[2] vector
+1 -1
View File
@@ -1,2 +1,2 @@
float64[4] vector
float64[2] vector
bool[16] bools
@@ -3,6 +3,6 @@
#
bool c
uint8[<64] str
A[<3] a
B[3] b
uint8[<20] str
A[<2] a
B[2] b
+27 -7
View File
@@ -22,8 +22,12 @@ except NameError:
long = int
MAX_FULL_TYPE_NAME_LEN = 80
DATA_TYPE_ID_MAX = 2047 # TODO: different limits for messages and services
MAX_DATA_STRUCT_LEN_BYTES = 439 # TODO: different limits for messages and services
SERVICE_DATA_TYPE_ID_MAX = 511
MESSAGE_DATA_TYPE_ID_MAX = 2047
MAX_SERVICE_STRUCT_LEN_BYTES = 439
MAX_MESSAGE_STRUCT_LEN_BYTES = 126 # Broadcast
class Type:
'''
@@ -286,7 +290,6 @@ class Parser:
default_dtid = int(default_dtid)
except ValueError:
error('Invalid default data type ID [%s]', default_dtid)
validate_data_type_id(default_dtid)
full_name = self._namespace_from_filename(filename) + '.' + name
validate_compound_type_full_name(full_name)
return full_name, default_dtid
@@ -492,6 +495,7 @@ class Parser:
max_bitlen = t.get_max_bitlen()
max_bytelen = bitlen_to_bytelen(max_bitlen)
validate_data_type_id(t)
validate_data_struct_len(t)
self.log.info('Type [%s], default DTID: %s, signature: %08x, maxbits: %s, maxbytes: %s, DSSD:',
full_typename, default_dtid, t.get_dsdl_signature(), max_bitlen, max_bytelen)
@@ -560,19 +564,35 @@ def validate_compound_type_full_name(name):
def validate_attribute_name(name):
enforce(re.match(r'[a-zA-Z][a-zA-Z0-9_]*$', name), 'Invalid attribute name [%s]', name)
def validate_data_type_id(dtid):
enforce(0 <= dtid <= DATA_TYPE_ID_MAX, 'Invalid data type ID [%s]', dtid)
def validate_data_type_id(t):
if t.default_dtid is None:
return
if t.kind == t.KIND_MESSAGE:
enforce(0 <= t.default_dtid <= MESSAGE_DATA_TYPE_ID_MAX,
'Invalid data type ID for message [%s]', t.default_dtid)
elif t.kind == t.KIND_SERVICE:
enforce(0 <= t.default_dtid <= SERVICE_DATA_TYPE_ID_MAX,
'Invalid data type ID for service [%s]', t.default_dtid)
else:
error('Invalid kind: %s', t.kind)
def validate_data_struct_len(t):
enforce(t.category == t.CATEGORY_COMPOUND, 'Data structure length can be enforced only for compound types')
# EXtracting sizes
if t.kind == t.KIND_MESSAGE:
bitlens = [t.get_max_bitlen()]
elif t.kind == t.KIND_SERVICE:
bitlens = t.get_max_bitlen_request(), t.get_max_bitlen_response()
# Detecting the limit
if t.kind == t.KIND_MESSAGE and t.default_dtid is not None:
max_bytes = MAX_MESSAGE_STRUCT_LEN_BYTES
else:
max_bytes = MAX_SERVICE_STRUCT_LEN_BYTES
# Checking
for bitlen in bitlens:
bytelen = bitlen_to_bytelen(bitlen)
enforce(0 <= bytelen <= MAX_DATA_STRUCT_LEN_BYTES,
'Max data structure length is invalid: %d bits, %d bytes', bitlen, bytelen)
enforce(0 <= bytelen <= max_bytes,
'Max data structure length is invalid: %d bits, %d bytes; limit %d bytes', bitlen, bytelen, max_bytes)
def parse_namespaces(source_dirs, search_dirs=None):