vlm / asn1c

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

Extensible SEQUENCE OF with SIZE constraint encodes into invalid uPER data #433

Open kellerkindt opened 3 years ago

kellerkindt commented 3 years ago

TLDR; I tried to encode a CPM with asn1c and decode it with asn1rs and OSS Nokalva's online decoder. Both failed while https://github.com/riebl/asn1c from @riebl and https://github.com/mouse07410/asn1c from @mouse07410 seem to work fine. Related to #383? Complete and compilable example project: https://github.com/kellerkindt/asn1c-issue-433

  1. Download the CPM v0.0.22 Draft or use the simplified version below
    itu-t (0) identified-organization (4) etsi (0) itsDomain (5) wg1 (1) tr (103562) cpm (1) version (1)

Simplified

Schema DEFINITIONS AUTOMATIC TAGS ::= 
BEGIN

CPM ::= SEQUENCE {
    header ItsPduHeader,
    cpm    CollectivePerceptionMessage
}
ItsPduHeader ::= SEQUENCE {
    protocolVersion INTEGER (0..255),
    messageID INTEGER (0..255),
    stationID INTEGER (0..4294967295)
}

CollectivePerceptionMessage ::= SEQUENCE {
    generationDeltaTime         INTEGER (0..65535),
    cpmParameters               CpmParameters
}

CpmParameters ::= SEQUENCE {
    managementContainer         CpmManagementContainer,
    stationDataContainer        INTEGER  OPTIONAL,
    sensorInformationContainer  INTEGER  OPTIONAL,
    perceivedObjectContainer    INTEGER  OPTIONAL,
    freeSpaceAddendumContainer  FreeSpaceAddendumContainer OPTIONAL,
    numberOfPerceivedObjects    INTEGER (0..255),
    ...,
    timeReference               INTEGER
}

FreeSpaceAddendumContainer ::= SEQUENCE SIZE(1..128, ...) OF FreeSpaceAddendum

FreeSpaceAddendum ::= SEQUENCE {
    freeSpaceConfidence    INTEGER (0..101),
    freeSpaceArea          FreeSpaceArea,
    sensorIDList           INTEGER     OPTIONAL,
    shadowingApplies       BOOLEAN DEFAULT TRUE,
    ...
}

FreeSpaceArea ::= CHOICE {
    freeSpacePolygon     INTEGER,
    freeSpaceCircular    AreaCircular,
    freeSpaceEllipse     INTEGER,
    freeSpaceRectangle   INTEGER,
    ...
}

AreaCircular ::= SEQUENCE {
    nodeCenterPoint      INTEGER OPTIONAL,
    radius               INTEGER (0..10000)
}

CpmManagementContainer ::= SEQUENCE {
    stationType                         INTEGER (0..255),
    perceivedObjectContainerSegmentInfo INTEGER OPTIONAL,
    referencePosition                   ReferencePosition,
    ...
}

ReferencePosition ::= SEQUENCE {
    latitude                    INTEGER (-900000000..900000001),
    longitude                   INTEGER (-1800000000..1800000001),
    positionConfidenceEllipse   PosConfidenceEllipse,
    altitude                    Altitude
}

Altitude ::= SEQUENCE {
    altitudeValue       INTEGER (-100000..800001),
    altitudeConfidence  AltitudeConfidence
}

AltitudeConfidence ::= ENUMERATED {
    alt-000-01(0),
    alt-000-02(1),
    alt-000-05(2),
    alt-000-10(3),
    alt-000-20(4),
    alt-000-50(5),
    alt-001-00(6),
    alt-002-00(7),
    alt-005-00(8),
    alt-010-00(9),
    alt-020-00(10),
    alt-050-00(11),
    alt-100-00(12),
    alt-200-00(13),
    outOfRange(14),
    unavailable(15)
}

PosConfidenceEllipse ::= SEQUENCE {
    semiMajorConfidence     INTEGER (0..4095),
    semiMinorConfidence     INTEGER (0..4095),
    semiMajorOrientation    INTEGER (0..3601)
}

END
  1. Encode some Data (helper_* prefixed functions are local helpers that work as their name suggest, BAIL exits on error):

        CPM_t *cpm = calloc(1, sizeof(CPM_t)); 
        cpm->header.protocolVersion = 1;
        cpm->header.messageID = 1;
        cpm->header.stationID = 1337;
        cpm->cpm.generationDeltaTime = 123;
        cpm->cpm.cpmParameters.managementContainer.stationType = 1;
        cpm->cpm.cpmParameters.managementContainer.perceivedObjectContainerSegmentInfo = NULL;
        cpm->cpm.cpmParameters.managementContainer.referencePosition.latitude = 2;
        cpm->cpm.cpmParameters.managementContainer.referencePosition.longitude = 3;
        cpm->cpm.cpmParameters.managementContainer.referencePosition.positionConfidenceEllipse.semiMajorConfidence = 4;
        cpm->cpm.cpmParameters.managementContainer.referencePosition.positionConfidenceEllipse.semiMinorConfidence = 5;
        cpm->cpm.cpmParameters.managementContainer.referencePosition.positionConfidenceEllipse.semiMajorOrientation = 6;
        cpm->cpm.cpmParameters.managementContainer.referencePosition.altitude.altitudeValue = 7;
        cpm->cpm.cpmParameters.managementContainer.referencePosition.altitude.altitudeConfidence = 15;
        cpm->cpm.cpmParameters.stationDataContainer = NULL;
        cpm->cpm.cpmParameters.sensorInformationContainer = NULL;
        cpm->cpm.cpmParameters.perceivedObjectContainer = NULL;
        cpm->cpm.cpmParameters.freeSpaceAddendumContainer = calloc(1, sizeof(FreeSpaceAddendumContainer_t));
        cpm->cpm.cpmParameters.numberOfPerceivedObjects = 42;
        cpm->cpm.cpmParameters.timeReference = NULL;
    
        FreeSpaceAddendum_t *fsa = calloc(1, sizeof(FreeSpaceAddendum_t));
        fsa->freeSpaceConfidence = 4;
        fsa->freeSpaceArea.present = FreeSpaceArea_PR_freeSpaceCircular;
        fsa->freeSpaceArea.choice.freeSpaceCircular.nodeCenterPoint = NULL;
        fsa->freeSpaceArea.choice.freeSpaceCircular.radius = 2;
        fsa->sensorIDList = NULL;
        fsa->shadowingApplies = NULL;
        asn_sequence_add(&(cpm->cpm.cpmParameters.freeSpaceAddendumContainer->list), fsa);
    
        BAIL("printing cpm", helper_print_cpm(cpm, stdout));
        BAIL("checking constraints", helper_check_cpm(cpm, stderr));
        BAIL("sending cpm", helper_send_cpm(cpm));

With asn1c version 0.9.28 from the ubuntu repo and the current master, the above code produces the following text and binary (hex) output:

CPM ::= {
    header: ItsPduHeader ::= {
        protocolVersion: 1
        messageID: 1
        stationID: 1337
    }
    cpm: CollectivePerceptionMessage ::= {
        generationDeltaTime: 123
        cpmParameters: CpmParameters ::= {
            managementContainer: CpmManagementContainer ::= {
                stationType: 1
                referencePosition: ReferencePosition ::= {
                    latitude: 2
                    longitude: 3
                    positionConfidenceEllipse: PosConfidenceEllipse ::= {
                        semiMajorConfidence: 4
                        semiMinorConfidence: 5
                        semiMajorOrientation: 6
                    }
                    altitude: Altitude ::= {
                        altitudeValue: 7
                        altitudeConfidence: 15
                    }
                }
            }
            freeSpaceAddendumContainer: FreeSpaceAddendumContainer ::= {
                FreeSpaceAddendum ::= {
                    freeSpaceConfidence: 4
                    freeSpaceArea: AreaCircular ::= {
                        radius: 2
                    }
                }
            }
            numberOfPerceivedObjects: 42
        }
    }
}
010100000539007b0802d693a409ad27480c01001401861a9fc00084001150
  1. Decoding with asn1c works fine
  2. Decoding with asn1rs and OSS Nokalva's online decoder does not (first error at freeSpaceConfidence, which should be 4 but decodes to 8):
    
    OSS ASN-1Step Version 10.0.1
    Copyright (C) 2020 OSS Nokalva, Inc.  All rights reserved.
    This product is licensed for use by "OSS Nokalva, Inc."

C0043I: 0 error messages, 0 warning messages and 0 informatory messages issued.

ASN1STEP: Decoding PDU #1 :

rec1value CPM ::= { --TYPE INFORMATION: SEQUENCE --OFFSET: 0,0 header { --TYPE INFORMATION: SEQUENCE --OFFSET: 0,0 protocolVersion 1, --TYPE INFORMATION: INTEGER (0..255) --OFFSET: 0,0; LENGTH: 1,0 --contents: .01 messageID 1, --TYPE INFORMATION: INTEGER (0..255) --OFFSET: 1,0; LENGTH: 1,0 --contents: .01 stationID 1337 --TYPE INFORMATION: INTEGER (0..4294967295) --OFFSET: 2,0; LENGTH: 4,0 --contents: .00.00.05.39 }, cpm { --TYPE INFORMATION: SEQUENCE --OFFSET: 6,0 generationDeltaTime 123, --TYPE INFORMATION: INTEGER (0..65535) --OFFSET: 6,0; LENGTH: 2,0 --contents: .00.7B cpmParameters { --TYPE INFORMATION: SEQUENCE --OFFSET: 8,0 --extension flag: <.0> --preamble: <0001> --bit #0 = 0: 'stationDataContainer' is absent --bit #1 = 0: 'sensorInformationContainer' is absent --bit #2 = 0: 'perceivedObjectContainer' is absent --bit #3 = 1: 'freeSpaceAddendumContainer' is present managementContainer { --TYPE INFORMATION: SEQUENCE --OFFSET: 8,5 --extension flag: <0> --preamble: <0> --bit #0 = 0: 'perceivedObjectContainerSegmentInfo' is absent stationType 1, --TYPE INFORMATION: INTEGER (0..255) --OFFSET: 8,7; LENGTH: 1,0 --contents: <0.0000001> referencePosition { --TYPE INFORMATION: SEQUENCE --OFFSET: 9,7 latitude 2, --TYPE INFORMATION: INTEGER (-900000000..900000001) --OFFSET: 9,7; LENGTH: 3,7 --contents: <0>.D6.93.A4.<000010> longitude 3, --TYPE INFORMATION: INTEGER (-1800000000..1800000001) --OFFSET: 13,6; LENGTH: 4,0 --contents: <01>.AD.27.48.<000011> positionConfidenceEllipse { --TYPE INFORMATION: SEQUENCE --OFFSET: 17,6 semiMajorConfidence 4, --TYPE INFORMATION: INTEGER (0..4095) --OFFSET: 17,6; LENGTH: 1,4 --contents: <00>.01.<00> semiMinorConfidence 5, --TYPE INFORMATION: INTEGER (0..4095) --OFFSET: 19,2; LENGTH: 1,4 --contents: <000000.000101> semiMajorOrientation 6 --TYPE INFORMATION: INTEGER (0..3601) --OFFSET: 20,6; LENGTH: 1,4 --contents: <00>.01.<10> }, altitude { --TYPE INFORMATION: SEQUENCE --OFFSET: 22,2 altitudeValue 7, --TYPE INFORMATION: INTEGER (-100000..800001) --OFFSET: 22,2; LENGTH: 2,4 --contents: <000110>.1A.<100111> altitudeConfidence unavailable --TYPE INFORMATION: ENUMERATED {alt-000-01,alt-000-02,alt-000-05,alt-000-10,alt-000-20,alt-000-50,alt-001-00,alt-002-00,alt-005-00,alt-010-00,alt-020-00,alt-050-00,alt-100-00,alt-200-00,outOfRange,unavailable} --OFFSET: 24,6; LENGTH: 0,4 --contents: <11.11> } } }, freeSpaceAddendumContainer { --TYPE INFORMATION: SEQUENCE (SIZE(1..128,...)) OF OPTIONAL --OFFSET: 25,2 --extension range: <0> --length: <00000.00> (decoded as 1) { --TYPE INFORMATION: SEQUENCE --OFFSET: 26,2 --extension flag: <0> --preamble: <00> --bit #0 = 0: 'sensorIDList' is absent --bit #1 = 0: 'shadowingApplies' is absent freeSpaceConfidence 8, --TYPE INFORMATION: INTEGER (0..101) --OFFSET: 26,5; LENGTH: 0,7 --contents: <000.1000> freeSpaceArea --choice value: --TYPE INFORMATION: CHOICE --OFFSET: 27,4 --extension flag: <0> --choice index: <10> (index = 2) freeSpaceEllipse : 0 --TYPE INFORMATION: INTEGER --OFFSET: 27,7; LENGTH: 1,0 --length: <0.0000000> (decoded as 0) } }, numberOfPerceivedObjects 8 --TYPE INFORMATION: INTEGER (0..255) --OFFSET: 28,7; LENGTH: 1,0 --contents: <0.0001000> } } } --PDU padding: <0> --TOTAL LENGTH: 30,0 Successfully decoded 30 bytes. rec1value CPM ::= { header { protocolVersion 1, messageID 1, stationID 1337 }, cpm { generationDeltaTime 123, cpmParameters { managementContainer { stationType 1, referencePosition { latitude 2, longitude 3, positionConfidenceEllipse { semiMajorConfidence 4, semiMinorConfidence 5, semiMajorOrientation 6 }, altitude { altitudeValue 7, altitudeConfidence unavailable } } }, freeSpaceAddendumContainer { { freeSpaceConfidence 8, freeSpaceArea freeSpaceEllipse : 0 } }, numberOfPerceivedObjects 8 } } } Value notation is written to the file 'data.txt'.

ASN1STEP: Decoded '1' record, the remaining '1' bytes are skipped.

The output may be truncated. Please sign in to get unlimited access.


5. Use https://github.com/riebl/asn1c and repeat from 2. 
6. Profit. The binary data has now changed to the following, which can be decoded successfully:
```hex
010100000539007b0802d693a409ad27480c01001401861a9fc000420008a8
OSS ASN-1Step Version 10.0.1
Copyright (C) 2020 OSS Nokalva, Inc.  All rights reserved.
This product is licensed for use by "OSS Nokalva, Inc."

C0043I: 0 error messages, 0 warning messages and 0 informatory messages issued.

ASN1STEP: Decoding PDU #1 :

rec1value CPM ::= 
{
  --TYPE INFORMATION: SEQUENCE
  --OFFSET: 0,0
  header
  {
    --TYPE INFORMATION: SEQUENCE
    --OFFSET: 0,0
    protocolVersion 1,
      --TYPE INFORMATION: INTEGER (0..255)
      --OFFSET: 0,0; LENGTH: 1,0
      --contents: .01
    messageID 1,
      --TYPE INFORMATION: INTEGER (0..255)
      --OFFSET: 1,0; LENGTH: 1,0
      --contents: .01
    stationID 1337
      --TYPE INFORMATION: INTEGER (0..4294967295)
      --OFFSET: 2,0; LENGTH: 4,0
      --contents: .00.00.05.39
  },
  cpm
  {
    --TYPE INFORMATION: SEQUENCE
    --OFFSET: 6,0
    generationDeltaTime 123,
      --TYPE INFORMATION: INTEGER (0..65535)
      --OFFSET: 6,0; LENGTH: 2,0
      --contents: .00.7B
    cpmParameters
    {
      --TYPE INFORMATION: SEQUENCE
      --OFFSET: 8,0
      --extension flag: <.0>
      --preamble: <0001>
        --bit #0 = 0: 'stationDataContainer' is absent
        --bit #1 = 0: 'sensorInformationContainer' is absent
        --bit #2 = 0: 'perceivedObjectContainer' is absent
        --bit #3 = 1: 'freeSpaceAddendumContainer' is present
      managementContainer
      {
        --TYPE INFORMATION: SEQUENCE
        --OFFSET: 8,5
        --extension flag: <0>
        --preamble: <0>
          --bit #0 = 0: 'perceivedObjectContainerSegmentInfo' is absent
        stationType 1,
          --TYPE INFORMATION: INTEGER (0..255)
          --OFFSET: 8,7; LENGTH: 1,0
          --contents: <0.0000001>
        referencePosition
        {
          --TYPE INFORMATION: SEQUENCE
          --OFFSET: 9,7
          latitude 2,
            --TYPE INFORMATION: INTEGER (-900000000..900000001)
            --OFFSET: 9,7; LENGTH: 3,7
            --contents: <0>.D6.93.A4.<000010>
          longitude 3,
            --TYPE INFORMATION: INTEGER (-1800000000..1800000001)
            --OFFSET: 13,6; LENGTH: 4,0
            --contents: <01>.AD.27.48.<000011>
          positionConfidenceEllipse
          {
            --TYPE INFORMATION: SEQUENCE
            --OFFSET: 17,6
            semiMajorConfidence 4,
              --TYPE INFORMATION: INTEGER (0..4095)
              --OFFSET: 17,6; LENGTH: 1,4
              --contents: <00>.01.<00>
            semiMinorConfidence 5,
              --TYPE INFORMATION: INTEGER (0..4095)
              --OFFSET: 19,2; LENGTH: 1,4
              --contents: <000000.000101>
            semiMajorOrientation 6
              --TYPE INFORMATION: INTEGER (0..3601)
              --OFFSET: 20,6; LENGTH: 1,4
              --contents: <00>.01.<10>
          },
          altitude
          {
            --TYPE INFORMATION: SEQUENCE
            --OFFSET: 22,2
            altitudeValue 7,
              --TYPE INFORMATION: INTEGER (-100000..800001)
              --OFFSET: 22,2; LENGTH: 2,4
              --contents: <000110>.1A.<100111>
            altitudeConfidence unavailable
              --TYPE INFORMATION: ENUMERATED {alt-000-01,alt-000-02,alt-000-05,alt-000-10,alt-000-20,alt-000-50,alt-001-00,alt-002-00,alt-005-00,alt-010-00,alt-020-00,alt-050-00,alt-100-00,alt-200-00,outOfRange,unavailable}
              --OFFSET: 24,6; LENGTH: 0,4
              --contents: <11.11>
          }
        }
      },
      freeSpaceAddendumContainer
      {
        --TYPE INFORMATION: SEQUENCE (SIZE(1..128,...)) OF OPTIONAL
        --OFFSET: 25,2
        --extension range: <0>
        --length: <00000.00> (decoded as 1)
        {
          --TYPE INFORMATION: SEQUENCE
          --OFFSET: 26,2
          --extension flag: <0>
          --preamble: <00>
            --bit #0 = 0: 'sensorIDList' is absent
            --bit #1 = 0: 'shadowingApplies' is absent
          freeSpaceConfidence 4,
            --TYPE INFORMATION: INTEGER (0..101)
            --OFFSET: 26,5; LENGTH: 0,7
            --contents: <000.0100>
          freeSpaceArea --choice value:
            --TYPE INFORMATION: CHOICE
            --OFFSET: 27,4
            --extension flag: <0>
            --choice index: <01> (index = 1)
            freeSpaceCircular :
            {
              --TYPE INFORMATION: SEQUENCE
              --OFFSET: 27,7
              --preamble: <0>
                --bit #0 = 0: 'nodeCenterPoint' is absent
              radius 2
                --TYPE INFORMATION: INTEGER (0..10000)
                --OFFSET: 28,0; LENGTH: 1,6
                --contents: .00.<000010>
            }
        }
      },
      numberOfPerceivedObjects 42
        --TYPE INFORMATION: INTEGER (0..255)
        --OFFSET: 29,6; LENGTH: 1,0
        --contents: <00.101010>
    }
  }
}
--PDU padding: <00>
--TOTAL LENGTH: 31,0
Successfully decoded 31 bytes.
rec1value CPM ::= 
{
  header 
  {
    protocolVersion 1,
    messageID 1,
    stationID 1337
  },
  cpm 
  {
    generationDeltaTime 123,
    cpmParameters 
    {
      managementContainer 
      {
        stationType 1,
        referencePosition 
        {
          latitude 2,
          longitude 3,
          positionConfidenceEllipse 
          {
            semiMajorConfidence 4,
            semiMinorConfidence 5,
            semiMajorOrientation 6
          },
          altitude 
          {
            altitudeValue 7,
            altitudeConfidence unavailable
          }
        }
      },
      freeSpaceAddendumContainer 
      {
        {
          freeSpaceConfidence 4,
          freeSpaceArea freeSpaceCircular : 
            {
              radius 2
            }
        }
      },
      numberOfPerceivedObjects 42
    }
  }
}
Value notation is written to the file 'data.txt'.

The output may be truncated. Please sign in to get unlimited access.
  1. Once you replace the extensible SEQUENCE OF
    FreeSpaceAddendumContainer ::= SEQUENCE SIZE(1..128, ...) OF FreeSpaceAddendum

    by a non-extensible SEQUENCE OF

    FreeSpaceAddendumContainer ::= SEQUENCE SIZE(1..128) OF FreeSpaceAddendum

    the binary data from 2. can be decoded by asn1rs and OSS Nokalva's online decoder.

mouse07410 commented 3 years ago

@kellerkindt Can you do me a favor and try encoding/decoding with https://github.com/mouse07410/asn1c.git (branch vlm_master)? It should have the fix from https://github.com/riebl/asn1c.git .

Alternatively, could you provide a complete compile-able program that I can build and try on my machine?

Thanks!

Update

I tested with my fork your UPER encoding that came from riebl/asn1c, successfully decoded it to XER, then successfully encoded back to UPER, and cross-checked all the results with Nokalva OSS. It seems to work fine.

kellerkindt commented 3 years ago

@mouse07410 yeah, your fork seems to produce the same valid hex value as the one from riebl:

010100000539007b0802d693a409ad27480c01001401861a9fc000420008a8

Do you know the exact reason / commit / fix?

kellerkindt commented 3 years ago

@mouse07410 here you go https://github.com/kellerkindt/asn1c-issue-433 - an complete and compilable example project

mouse07410 commented 3 years ago

Do you know the exact reason / commit / fix?

I think I do. It's probably https://github.com/riebl/asn1c/commit/c35ebd330b7c7e15c1bd61c9782e4259bd9bcb03, which my fork has.

fried-gluttony commented 2 years ago

Thanks very much guys, I can at least approve that after adding https://github.com/riebl/asn1c/commit/c35ebd330b7c7e15c1bd61c9782e4259bd9bcb03 my CPMs decode fine!