Skip to content

fix(linker): prevent stack overflow from over-eager recursion marking#96

Merged
6d7a merged 1 commit intomainfrom
fix/95-recursive-so
Mar 12, 2025
Merged

fix(linker): prevent stack overflow from over-eager recursion marking#96
6d7a merged 1 commit intomainfrom
fix/95-recursive-so

Conversation

@6d7a
Copy link
Copy Markdown
Member

@6d7a 6d7a commented Mar 12, 2025

Fixes #95
Stops recursion detection at options and sequence members that are already marked is_recursive. Options and members that are marked recursive will be Boxed. The Box constitutes a recursion breaker, so we do not have to check its children for recursion.

@6d7a 6d7a merged commit 6a0ab6c into main Mar 12, 2025
1 of 2 checks passed
@6d7a 6d7a deleted the fix/95-recursive-so branch March 12, 2025 16:59
@DavidLeeds
Copy link
Copy Markdown
Contributor

DavidLeeds commented Mar 12, 2025

Unfortunately, I am still seeing a stack overflow with v0.8.1. If desired, I am happy to send some ASN.1 that can reproduce it.

@6d7a
Copy link
Copy Markdown
Member Author

6d7a commented Mar 13, 2025

@DavidLeeds please do, the example from #95 compiles fine.

@DavidLeeds
Copy link
Copy Markdown
Contributor

DavidLeeds commented Mar 13, 2025

@6d7a Here is a snippet that reproduces it.

flowchart BT
    VariableSpecification --> TypeSpecification
    TypeSpecification --> TypeDescription
    TypeDescription --> TypeSpecification
Loading
ISO-9506-MMS-Snippet

DEFINITIONS ::= BEGIN

maxIdentifier INTEGER ::= 32

Integer8 ::= INTEGER (-128..127)

Integer16 ::= INTEGER (-32768..32767)

Integer32 ::= INTEGER (-2147483648..2147483647)

Unsigned8 ::= INTEGER (0..127)

Unsigned16 ::= INTEGER (0..32767)

Unsigned32 ::= INTEGER (0..2147483647)

FloatingPoint ::= OCTET STRING

MMSString ::= VisibleString

MMS255String ::= VisibleString (SIZE (1..255))

TimeOfDay ::= OCTET STRING (SIZE (4 | 6))

Identifier ::= VisibleString (SIZE (1..maxIdentifier))

Address ::= CHOICE {
   numericAddress [0] IMPLICIT Unsigned32,
   symbolicAddress [1] MMSString,
   unconstrainedAddress [2] IMPLICIT OCTET STRING
}

ObjectName ::= CHOICE {
   vmd-specific [0] IMPLICIT Identifier,
   domain-specific [1] IMPLICIT SEQUENCE {
      domainID Identifier,
      itemID Identifier
   },
   aa-specific [2] IMPLICIT Identifier
}

TypeDescription ::= CHOICE {
   array [1] IMPLICIT SEQUENCE {
      packed [0] IMPLICIT BOOLEAN DEFAULT FALSE,
      numberOfElements [1] IMPLICIT Unsigned32,
      elementType [2] TypeSpecification
   },
   structure [2] IMPLICIT SEQUENCE {
      packed [0] IMPLICIT BOOLEAN DEFAULT FALSE,
      components [1] IMPLICIT SEQUENCE OF SEQUENCE {
         componentName [0] IMPLICIT Identifier OPTIONAL,
         componentType [1] TypeSpecification
      }
   },
   boolean [3] IMPLICIT NULL,
   bit-string [4] IMPLICIT Integer32,
   integer [5] IMPLICIT Unsigned8,
   unsigned [6] IMPLICIT Unsigned8,
   floating-point [7] IMPLICIT SEQUENCE {
      format-width Unsigned8,
      exponent-width Unsigned8
   },
   octet-string [9] IMPLICIT Integer32,
   visible-string [10] IMPLICIT Integer32,
   generalized-time [11] IMPLICIT NULL,
   binary-time [12] IMPLICIT BOOLEAN,
   bcd [13] IMPLICIT Unsigned8,
   objId [15] IMPLICIT NULL,
   ...,
   mMSString [16] Integer32
}

TypeSpecification ::= CHOICE {
   typeName [0] ObjectName,
   typeDescription TypeDescription
}

VariableSpecification ::= CHOICE {
   name [0] ObjectName,
   address [1] Address,
   variableDescription [2] IMPLICIT SEQUENCE {
      address Address,
      typeSpecification TypeSpecification
   }
}

END

We see endless recursion in the stack trace:

#10 0x000055555581616e in rasn_compiler::intermediate::ASN1Type::recurses (self=0x555555ac69d0, name="VariableSpecification", tlds=0x7fffffffb7b0) at src/validator/linking/mod.rs:573
#11 0x000055555581621a in rasn_compiler::validator::linking::{impl#2}::recurses::{closure#1} (opt=0x555555ac69d0) at src/validator/linking/mod.rs:581
#12 0x00005555555fd9da in core::slice::iter::{impl#182}::any<rasn_compiler::intermediate::types::ChoiceOption, rasn_compiler::validator::linking::{impl#2}::recurses::{closure_env#1}> (
    self=0x7fffff7ff698, f=...) at /home/davidleeds/.rustup/toolchains/1.85.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/iter/macros.rs:285
#13 0x000055555581607e in rasn_compiler::intermediate::ASN1Type::recurses (self=0x555555aca8c8, name="VariableSpecification", tlds=0x7fffffffb7b0) at src/validator/linking/mod.rs:577
#14 0x0000555555810fa9 in rasn_compiler::intermediate::ToplevelDefinition::recurses (self=0x555555aca8c0, name="VariableSpecification", tlds=0x7fffffffb7b0) at src/validator/linking/mod.rs:122
#15 0x00005555558161d7 in rasn_compiler::validator::linking::{impl#2}::recurses::{closure#0} (tld=0x555555aca8c0) at src/validator/linking/mod.rs:575
#16 0x00005555556c3e60 in core::option::Option<&rasn_compiler::intermediate::ToplevelDefinition>::is_some_and<&rasn_compiler::intermediate::ToplevelDefinition, rasn_compiler::validator::linking::{impl#2}::recurses::{closure_env#0}> (self=..., f=...) at /home/davidleeds/.rustup/toolchains/1.85.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:631
#17 0x000055555581619a in rasn_compiler::intermediate::ASN1Type::recurses (self=0x555555ac7340, name="VariableSpecification", tlds=0x7fffffffb7b0) at src/validator/linking/mod.rs:573
#18 0x000055555581621a in rasn_compiler::validator::linking::{impl#2}::recurses::{closure#1} (opt=0x555555ac7340) at src/validator/linking/mod.rs:581
#19 0x00005555555fd9da in core::slice::iter::{impl#182}::any<rasn_compiler::intermediate::types::ChoiceOption, rasn_compiler::validator::linking::{impl#2}::recurses::{closure_env#1}> (
    self=0x7fffff7ff988, f=...) at /home/davidleeds/.rustup/toolchains/1.85.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/iter/macros.rs:285
#20 0x000055555581607e in rasn_compiler::intermediate::ASN1Type::recurses (self=0x555555acc508, name="VariableSpecification", tlds=0x7fffffffb7b0) at src/validator/linking/mod.rs:577
#21 0x0000555555810fa9 in rasn_compiler::intermediate::ToplevelDefinition::recurses (self=0x555555acc500, name="VariableSpecification", tlds=0x7fffffffb7b0) at src/validator/linking/mod.rs:122
#22 0x00005555558161d7 in rasn_compiler::validator::linking::{impl#2}::recurses::{closure#0} (tld=0x555555acc500) at src/validator/linking/mod.rs:575
#23 0x00005555556c3e60 in core::option::Option<&rasn_compiler::intermediate::ToplevelDefinition>::is_some_and<&rasn_compiler::intermediate::ToplevelDefinition, rasn_compiler::validator::linking::{impl#2}::recurses::{closure_env#0}> (self=..., f=...) at /home/davidleeds/.rustup/toolchains/1.85.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:631
...

@6d7a
Copy link
Copy Markdown
Member Author

6d7a commented Mar 13, 2025

Great! Thank you. I'll have a look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Nested recursive creates stack overflow

2 participants