vlm / asn1c

The ASN.1 Compiler
http://lionet.info/asn1c/
BSD 2-Clause "Simplified" License
1.03k stars 551 forks source link

Error encoding timestamp (INTEGER_T) #303

Open momor10 opened 5 years ago

momor10 commented 5 years ago

i have a type TimeStampIts that's defined like this: TimeStampIts::= INTEGER (0..4398046511103) the generated type:

/* TimeStampIts */
typedef INTEGER_t    TimeStampIts_t;

In a DENM Message im trying to set the value, encoding keeps failing:


    INTEGER_t timeResult;
    memset(&timeResult, 0, sizeof(timeResult));
    asn_umax2INTEGER(&timeResult, 4398046511103);
    denm_p->denm.management.detectionTime = timeResult;
...

        asn_encode_to_new_buffer_result_s result = asn_encode_to_new_buffer(0, ATS_UNALIGNED_BASIC_PER, &asn_DEF_Denm, denm_p);
        if (result.result.encoded == -1) {
            qDebug() << "Error Encoding: " << result.result.failed_type->name;
        } else {
            ...
        }

Does anyone have a clue on how to find out whats going wrong? Is setting the value like that the wrong way?

velichkov commented 5 years ago

Hi @momor10,

Does anyone have a clue on how to find out whats going wrong?

Recompile with -DASN_ASN_EMIT_DEBUG=1 in CFLAGS and provide the full stderr output.

Does it succeed when you set a smaller time stamp?

denm_p->denm.management.detectionTime = timeResult;

Copying structs that contain pointers like this seems suspicious. Try to set the value directly without using a local variable

    asn_umax2INTEGER(&(denm_p->denm.management.detectionTime), 4398046511103);
momor10 commented 5 years ago

Thanks for the suggestion, the problem however remains. asn_umax2INTEGER(&(denm_p->denm.management.detectionTime), 4398046511103); here the stderr output:

Encoding Denm as SEQUENCE (UPER)
first_extension = -1, elements = 2
About to encode ItsPduHeader
Encoding Denm->header:ItsPduHeader
Encoding ItsPduHeader as SEQUENCE (UPER)
first_extension = -1, elements = 3
About to encode ProtocolVersion
Encoding ItsPduHeader->protocolVersion:ProtocolVersion
Encoding NativeInteger ProtocolVersion 1 (UPER)
Value 1 (01/1) lb 0 ub 255 fix
Encoding integer 1 (1) with range 8 bits
[PER put 8 bits 1 to 095FCAAC+0 bits]
[PER out 8 1/1 (t=0,o=8) 0&0=0]
[PER out 1/1 => 01 buf+0]
Freeing INTEGER as a primitive type
About to encode MessageID
Encoding ItsPduHeader->messageID:MessageID
Encoding NativeInteger MessageID 2 (UPER)
Value 2 (02/1) lb 0 ub 255 fix
Encoding integer 2 (2) with range 8 bits
[PER put 8 bits 2 to 095FCAAC+8 bits]
[PER out 8 2/2 (t=0,o=8) 0&0=0]
[PER out 2/2 => 02 buf+1]
Freeing INTEGER as a primitive type
About to encode StationID
Encoding ItsPduHeader->stationID:StationID
Encoding NativeInteger StationID 1 (UPER)
Value 1 (01/1) lb 0 ub 4294967295 fix
Encoding integer 1 (1) with range 32 bits
[PER put 1 bits 0 to 095FCAAD+8 bits]
[PER out 1 0/0 (t=0,o=1) f0&0=0]
[PER out 0/0 => 00 buf+2]
[PER put 31 bits 1 to 095FCAAE+1 bits]
[PER out 31 1/1 (t=1,o=32) 0&80=0]
[PER put 24 bits 0 to 095FCAAE+1 bits]
[PER out 24 0/0 (t=1,o=25) 0&80=0]
[PER out 0/0 => 00 buf+2]
[PER put 7 bits 1 to 095FCAAE+25 bits]
[PER out 7 1/1 (t=1,o=8) 0&80=0]
[PER out 1/1 => 01 buf+5]
[PER out 1/1 => 00 buf+5]
Freeing INTEGER as a primitive type
About to encode DecentralizedEnvironmentalNotificationMessage
Encoding Denm->denm:DecentralizedEnvironmentalNotificationMessage
Encoding DecentralizedEnvironmentalNotificationMessage as SEQUENCE (UPER)
Element ptr wtv DecentralizedEnvironmentalNotificationMessage->situation is present
[PER put 1 bits 1 to 095FCAB1+8 bits]
[PER out 1 1/1 (t=0,o=1) 0&0=0]
[PER out 128/80 => 80 buf+6]
Element ptr wtv DecentralizedEnvironmentalNotificationMessage->location is absent
[PER put 1 bits 0 to 095FCAB2+1 bits]
[PER out 1 0/0 (t=1,o=2) 80&80=80]
[PER out 0/0 => 80 buf+6]
Element ptr wtv DecentralizedEnvironmentalNotificationMessage->alacarte is absent
[PER put 1 bits 0 to 095FCAB2+2 bits]
[PER out 1 0/0 (t=2,o=3) 80&c0=80]
[PER out 0/0 => 80 buf+6]
first_extension = -1, elements = 4
About to encode ManagementContainer
Encoding DecentralizedEnvironmentalNotificationMessage->management:ManagementContainer
Encoding ManagementContainer as SEQUENCE (UPER)
[PER put 1 bits 0 to 095FCAB2+3 bits]
[PER out 1 0/0 (t=3,o=4) 80&e0=80]
[PER out 0/0 => 80 buf+6]
Element ptr wtv ManagementContainer->termination is absent
[PER put 1 bits 0 to 095FCAB2+4 bits]
[PER out 1 0/0 (t=4,o=5) 80&f0=80]
[PER out 0/0 => 80 buf+6]
Element ptr wtv ManagementContainer->relevanceDistance is absent
[PER put 1 bits 0 to 095FCAB2+5 bits]
[PER out 1 0/0 (t=5,o=6) 80&f8=80]
[PER out 0/0 => 80 buf+6]
Element ptr wtv ManagementContainer->relevanceTrafficDirection is absent
[PER put 1 bits 0 to 095FCAB2+6 bits]
[PER out 1 0/0 (t=6,o=7) 80&fc=80]
[PER out 0/0 => 80 buf+6]
Element ptr wtv ManagementContainer->validityDuration is absent
[PER put 1 bits 0 to 095FCAB2+7 bits]
[PER out 1 0/0 (t=7,o=8) 80&fe=80]
[PER out 0/0 => 80 buf+6]
Element ptr wtv ManagementContainer->transmissionInterval is absent
[PER put 1 bits 0 to 095FCAB2+8 bits]
[PER out 1 0/0 (t=0,o=1) 0&0=0]
[PER out 0/0 => 00 buf+7]
first_extension = 10, elements = 10
About to encode ActionID
Encoding ManagementContainer->actionID:ActionID
Encoding ActionID as SEQUENCE (UPER)
first_extension = -1, elements = 2
About to encode StationID
Encoding ActionID->originatingStationID:StationID
Encoding NativeInteger StationID 0 (UPER)
Value 0 (00/1) lb 0 ub 4294967295 fix
Encoding integer 0 (0) with range 32 bits
[PER put 1 bits 0 to 095FCAB3+1 bits]
[PER out 1 0/0 (t=1,o=2) 0&80=0]
[PER out 0/0 => 00 buf+7]
[PER put 31 bits 0 to 095FCAB3+2 bits]
[PER out 31 0/0 (t=2,o=33) 0&c0=0]
[PER put 24 bits 0 to 095FCAB3+2 bits]
[PER out 24 0/0 (t=2,o=26) 0&c0=0]
[PER out 0/0 => 00 buf+7]
[PER put 7 bits 0 to 095FCAB3+26 bits]
[PER out 7 0/0 (t=2,o=9) 0&c0=0]
[PER out 0/0 => 00 buf+10]
[PER out 0/0 => 00 buf+10]
Freeing INTEGER as a primitive type
About to encode SequenceNumber
Encoding ActionID->sequenceNumber:SequenceNumber
Encoding NativeInteger SequenceNumber 65535 (UPER)
Value 65535 (00/3) lb 0 ub 65535 fix
Encoding integer 65535 (65535) with range 16 bits
[PER put 16 bits ffff to 095FCAB6+9 bits]
[PER out 16 65535/ffff (t=1,o=17) 0&80=0]
[PER out 8388480/7fff80 => 7f buf+11]
Freeing INTEGER as a primitive type
About to encode TimeStampIts
Encoding ManagementContainer->detectionTime:TimeStampIts
Failed to encode element TimeStampIts
velichkov commented 5 years ago

Encoding ManagementContainer->detectionTime:TimeStampIts Failed to encode element TimeStampIts

Strange! Are you working on 32bit or 64bit platform? Linux or Windows? Did it succeed when you set a smaller timestamp?

momor10 commented 5 years ago

I compiled the latest asn1 source code on a linux machine and copied the generated files to a 64 bit windows 10 machine in qt project using the msvc 2017 32bit compiler

velichkov commented 5 years ago

msvc 2017 32bit compiler

The 32bit compiler could be a problem. Could you test it with 64 bit compiler on both Windows and Linux?

momor10 commented 5 years ago

sorry, but i cant do that just easily, it's kinda a big project using libraries i don't have the 64bit binaries for. (actually i customly compiled the qt sourcecode with msvc2017 with openssl support and a 32bit version of google breakpad.

velichkov commented 5 years ago

sorry, but i cant do that just easily

Ok, then try to create a minimal test case that only contains the asn1 related code that you could compile on 64 and 32 bit platforms.

momor10 commented 5 years ago

ill setup new development environment on a different machine with a minimal project setup.

velichkov commented 5 years ago

If you are good with the MSVC debugger you could also try to step through the INTEGER_encode_uper function and find where it fails.

momor10 commented 5 years ago

it fails on line 740 in Integer.c when calling asn_INTEGER2long:

INTEGER_encode_uper(const asn_TYPE_descriptor_t *td,
                    const asn_per_constraints_t *constraints, const void *sptr,
                    asn_per_outp_t *po) {
...
    if(ct) {
        int inext = 0;
        if(specs && specs->field_unsigned) {
            ....
        } else {
            if(asn_INTEGER2long(st, &value)) //HERE
                ASN__ENCODE_FAILED;

In asn_INTEGER2Long the value is bigger then LONG_MAX which is defined as follows: #define LONG_MAX 2147483647L // maximum (signed) long value

asn_INTEGER2long(const INTEGER_t *iptr, long *l) {
    intmax_t v;
    if(asn_INTEGER2imax(iptr, &v) == 0) {
        if(v < LONG_MIN || v > LONG_MAX) { 
            errno = ERANGE;
            return -1;
velichkov commented 5 years ago

define LONG_MAX 2147483647L // maximum (signed) long value

Thats definitely a bad news.

Check if LLONG_MIN and LLONG_MAX are defined and whether long long is supported by your compiler and if yes you will have to add support for long long.

momor10 commented 5 years ago

yes i replaced ULONG_MAX with ULLONG_MAX and ULONG_MIN with ULLONG_MIN and its encoding successfully now. (however i guess there might be problems using the long value types?) You can lead me to the places where i need to add the long long support? which files are to be changed? will it be enough to look for the calls of asn_INTEGER2.. methods and change the parameters/variables from long to long long (unsigned/signed)?

velichkov commented 5 years ago

i replaced ULONG_MAX with ULLONG_MAX and ULONG_MIN with ULLONG_MIN and its encoding successfully now. (however i guess there might be problems using the long value types?)

Yes, even if it works for your particular case changing only these two constants won't be enough for all cases.

You can lead me to the places where i need to add the long long support? which files are to be changed? will it be enough to look for the calls of asn_INTEGER2.. methods and change the parameters/variables from long to long long (unsigned/signed)?

Instead of long long probably a better approach is to use intmax_t and uintmax_t. First you need to change calls to asn_INTEGER2long with asn_INTEGER2imax and asn_INTEGER2ulong with asn_INTEGER2umax, then change the value and uval types to intmax_t and uintmax_t respectively. Add a new per_intmax_range_rebase similar to per_long_range_rebase that accepts intmax_t and in per_support.h change the lower_bound and upper_bound types.

Compile with -Wall in CFLAGS and fix all warnings. Also make sure that the test suite (make check) gets executed successfully.

And don't forget to contribute your changes back by opening a pull request :smile: