mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-28 15:13:34 +08:00
pyuavcan: DSDL length validation
This commit is contained in:
@@ -8,4 +8,4 @@ uint8 PROTOCOL_ID_RTCM2 = 2
|
|||||||
uint8 PROTOCOL_ID_RTCM3 = 3
|
uint8 PROTOCOL_ID_RTCM3 = 3
|
||||||
uint8 protocol_id
|
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;
|
os << get_node_info_rsp << std::endl << "==========" << std::endl;
|
||||||
|
|
||||||
root_ns_a::Deep ps;
|
root_ns_a::Deep ps;
|
||||||
ps.a.resize(2);
|
ps.a.resize(1);
|
||||||
os << ps << std::endl << "==========" << std::endl;
|
os << ps << std::endl << "==========" << std::endl;
|
||||||
|
|
||||||
static const std::string Reference =
|
static const std::string Reference =
|
||||||
@@ -81,45 +81,19 @@ TEST(Dsdl, Streaming)
|
|||||||
" scalar: 0\n"
|
" scalar: 0\n"
|
||||||
" vector: \n"
|
" vector: \n"
|
||||||
" - \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"
|
" bools: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
|
||||||
" - \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"
|
|
||||||
" 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"
|
|
||||||
" bools: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
|
" bools: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
|
||||||
"b: \n"
|
"b: \n"
|
||||||
" - \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"
|
" bools: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
|
||||||
" - \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"
|
" bools: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
|
||||||
"==========\n";
|
"==========\n";
|
||||||
std::cout << os.str();
|
std::cout << os.str();
|
||||||
ASSERT_EQ(Reference, 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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,4 +5,4 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
float32 scalar
|
float32 scalar
|
||||||
B[3] vector
|
B[2] vector
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
float64[4] vector
|
float64[2] vector
|
||||||
bool[16] bools
|
bool[16] bools
|
||||||
@@ -3,6 +3,6 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
bool c
|
bool c
|
||||||
uint8[<64] str
|
uint8[<20] str
|
||||||
A[<3] a
|
A[<2] a
|
||||||
B[3] b
|
B[2] b
|
||||||
|
|||||||
@@ -22,8 +22,12 @@ except NameError:
|
|||||||
long = int
|
long = int
|
||||||
|
|
||||||
MAX_FULL_TYPE_NAME_LEN = 80
|
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:
|
class Type:
|
||||||
'''
|
'''
|
||||||
@@ -286,7 +290,6 @@ class Parser:
|
|||||||
default_dtid = int(default_dtid)
|
default_dtid = int(default_dtid)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
error('Invalid default data type ID [%s]', default_dtid)
|
error('Invalid default data type ID [%s]', default_dtid)
|
||||||
validate_data_type_id(default_dtid)
|
|
||||||
full_name = self._namespace_from_filename(filename) + '.' + name
|
full_name = self._namespace_from_filename(filename) + '.' + name
|
||||||
validate_compound_type_full_name(full_name)
|
validate_compound_type_full_name(full_name)
|
||||||
return full_name, default_dtid
|
return full_name, default_dtid
|
||||||
@@ -492,6 +495,7 @@ class Parser:
|
|||||||
max_bitlen = t.get_max_bitlen()
|
max_bitlen = t.get_max_bitlen()
|
||||||
max_bytelen = bitlen_to_bytelen(max_bitlen)
|
max_bytelen = bitlen_to_bytelen(max_bitlen)
|
||||||
|
|
||||||
|
validate_data_type_id(t)
|
||||||
validate_data_struct_len(t)
|
validate_data_struct_len(t)
|
||||||
self.log.info('Type [%s], default DTID: %s, signature: %08x, maxbits: %s, maxbytes: %s, DSSD:',
|
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)
|
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):
|
def validate_attribute_name(name):
|
||||||
enforce(re.match(r'[a-zA-Z][a-zA-Z0-9_]*$', name), 'Invalid attribute name [%s]', name)
|
enforce(re.match(r'[a-zA-Z][a-zA-Z0-9_]*$', name), 'Invalid attribute name [%s]', name)
|
||||||
|
|
||||||
def validate_data_type_id(dtid):
|
def validate_data_type_id(t):
|
||||||
enforce(0 <= dtid <= DATA_TYPE_ID_MAX, 'Invalid data type ID [%s]', dtid)
|
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):
|
def validate_data_struct_len(t):
|
||||||
enforce(t.category == t.CATEGORY_COMPOUND, 'Data structure length can be enforced only for compound types')
|
enforce(t.category == t.CATEGORY_COMPOUND, 'Data structure length can be enforced only for compound types')
|
||||||
|
# EXtracting sizes
|
||||||
if t.kind == t.KIND_MESSAGE:
|
if t.kind == t.KIND_MESSAGE:
|
||||||
bitlens = [t.get_max_bitlen()]
|
bitlens = [t.get_max_bitlen()]
|
||||||
elif t.kind == t.KIND_SERVICE:
|
elif t.kind == t.KIND_SERVICE:
|
||||||
bitlens = t.get_max_bitlen_request(), t.get_max_bitlen_response()
|
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:
|
for bitlen in bitlens:
|
||||||
bytelen = bitlen_to_bytelen(bitlen)
|
bytelen = bitlen_to_bytelen(bitlen)
|
||||||
enforce(0 <= bytelen <= MAX_DATA_STRUCT_LEN_BYTES,
|
enforce(0 <= bytelen <= max_bytes,
|
||||||
'Max data structure length is invalid: %d bits, %d bytes', bitlen, bytelen)
|
'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):
|
def parse_namespaces(source_dirs, search_dirs=None):
|
||||||
|
|||||||
Reference in New Issue
Block a user