-
Notifications
You must be signed in to change notification settings - Fork 197
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inconsistent data truncation of unsupported data types in SDO upload #436
Comments
PR #440 implements four test cases ( Why do we have the logic of |
Maybe use 64 bits instead of 8 is the easiest solution. Hopefully it shouldn't happen too often after 48 bits support is added. |
It depends on not getting a future datatype which is larger than 64 bits. If we chose to cap it at 64, I would suggest that we warn about it to the logger that the data has been capped with an unknown datatype. (And the test in PR #440 must be altered to make it pass.) |
I'm not really fond of replacing the fall-back 8 bits value by 64 bits. It makes sense for any type to have at least 8 bits, since one octet is the smallest unit supported by SDO (disregarding PDO mapping with finer granularity here). Using any other fall-back value is arbitrary and will break unexpectedly when it does. We should rather fix the min(OD, SDO) length assumption to only get applied when the OD size is actually meaningful and not itself a fall-back value. |
I think this makes sense. Since the data type is of unknown type, no assumptions about the data contents can be made. So it should be passed transparently without truncation. -- Especially since it would pass transparently if the object have no OD entry. |
I agree, better to check if size is known or not. |
I attempted var = self.od.get_variable(index, subindex)
if var is not None:
if var.data_type not in objectdictionary.DATA_TYPES:
# Use max to determine enough space for the unknown data type
var_size = max(len(var) // 8, response_size)
if response_size is None or var_size < response_size:
# This wil never happen...
data = data[0:var_size]
return data But it turned out a bit non-sensical. So I'm kind of back at: Why do we even truncate? Why do we want to reduce the data for something we don't know what is? |
Just a quick note, the truncating was introduced to avoid an exception from the struct methods. They are quite strict about the buffer length, but could be tricked otherwise by slicing. Will need to take another good look at the alternatives and code flow... |
I would assume that known data types can or should be truncated in case of excessive data. Here we're talking about unknown data types with no reference to validate its proper size. |
I'm really still uncertain what the actual problem here is. The real culprit here is IMHO the check And maybe this whole check should be moved to |
I think we have two independent factors or conditions for any object ready by SDO upload:
(The PR #440 contains unit tests for both of these cases)
So I think the summary of the problem statement is that the current implementation truncates the data in the latter case. |
I think the problem is to more clearly define what is a "known" data type. The check against Also, your second case is impossible, as the data type is defined in the OD entry, thus without one we cannot know. |
Yes, I think that is a good idea. We must except array-types from this truncation, being
Yes, you're right. Without OD one cannot know the data type. I missed the fact. It is possible thou to read an object with SDO that is missing from the OD and thus its data type is missing. Its data should definitely not be truncated. |
Right, so to summarize: We only truncate if the OD contains an entry AND its data type is contained in STRUCT_TYPES. That automatically leaves array types (DOMAIN etc.) untouched, and will not explode for yet undefined type constants. On to the other questions:
|
It must look up the OD to get the data type, so in order for IMHO Today the deserialization happens in EDIT I vote for removing any validation from PPS! Should we validate, e.g. by warning or error, or should we truncate (and warn)? |
The only reason for doing validation in When moving the validation to
Notes:
Does that all seem correct? Would it be okay for you if we used this table as basis for the implementation and tested each case? |
This is a really good overview. There are two independent usages of length involved here
|
I'd really like to get this one fixed soon, but right now we only have ideas and not a complete and well-tested implementation draft of these last suggestions. Therefore I think we should focus on getting a release out the door to avoid problems like #455 and come back to this afterwards. OK for you @sveinse? |
@acolomb Yes, let's not delay the release because of this. Current behavior is what it is and we're not introducing any regressions by not fixing this issue. |
* Implement the remaining canopen datatypes * Add datatype defs for the canopen standard types * Move datatypes_24.py classes to datatypes.py * Replace Unsigned24 and Interger24 by generic UnsignedN and IntegerN respectively * Add EDS-file containing all datatypes * Added tests for encoding and decoding all datatypes * Added tests for SDO uploads of all datatypes * Annotate type hint for STRUCT_TYPES listing. * Disable failing tests waiting on a fix for #436. Co-authored-by: André Colomb <[email protected]>
@friederschueler not sure I'd label this one as an enhancement. Its describing unexpected behavior, so it's a bug. |
I'm having problems reading SDO objects that are using UNSIGNED48. It used to work before PR #395 by @ljungholm - but it turns out to be coincidental.
canopen/canopen/sdo/client.py
Lines 123 to 133 in 24df6e8
I believe the root cause is that canopen doesn't support the UNSIGNED48 type (which I'll contribute in another PR). The unfortunate behavior is that due to the unknown type, the data gets truncated to 1 byte. It didn't do that before #395 .
Observations:
ODVariable.__len__()
return 8 on unknown types, while it reports number of bits in the other types. This is why it gets truncated to one byte.Would you agree that
upload()
should return the the full data for both of the first use cases? Is the fix thatODVariable.__len__()
on unknown datatypes should return 64?The text was updated successfully, but these errors were encountered: