From e1fa08a4d672d588a3efee279c7ccd27051b7634 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Fri, 21 Jan 2022 22:34:12 -0600 Subject: [PATCH] asn1: Fix 5 shift/reduce conflicts There remains one tough shift/reduce conflict, the warning for which is quieted with an `%expect 1` directive. The remaining conflict has to do with whether a constraint attaches to the inner type that some other outer type is a SET OF or SEQUENCE OF or tagged-type of, or whether it attaches to the outer type. The two are really the same thing. The latter is the reduce side, so it's not used, but if it were we could grab the constraint in the action and attach it to the inner type anyways. --- lib/asn1/Makefile.am | 2 +- lib/asn1/asn1parse.y | 84 ++++++++++++++++++++++++++------------------ lib/asn1/symbol.h | 3 +- 3 files changed, 53 insertions(+), 36 deletions(-) diff --git a/lib/asn1/Makefile.am b/lib/asn1/Makefile.am index c4eb6a18a..5a9a4e1f8 100644 --- a/lib/asn1/Makefile.am +++ b/lib/asn1/Makefile.am @@ -4,7 +4,7 @@ include $(top_srcdir)/Makefile.am.common WFLAGS += $(WFLAGS_ENUM_CONV) -YFLAGS = -d -t +YFLAGS = -o asn1parse.c -t AM_CPPFLAGS += $(ROKEN_RENAME) -I$(top_builddir)/include -I$(top_srcdir)/lib/base diff --git a/lib/asn1/asn1parse.y b/lib/asn1/asn1parse.y index 290cb8631..5491ea61c 100644 --- a/lib/asn1/asn1parse.y +++ b/lib/asn1/asn1parse.y @@ -242,6 +242,7 @@ static unsigned long idcounter; %type BooleanType %type ChoiceType %type ConstrainedType +%type UnconstrainedType %type EnumeratedType %type IntegerType %type NullType @@ -288,6 +289,7 @@ static unsigned long idcounter; %type Constraint %type ConstraintSpec +%type SubtypeConstraint %type GeneralConstraint %type ContentsConstraint %type UserDefinedConstraint @@ -295,7 +297,7 @@ static unsigned long idcounter; %type ComponentRelationConstraint - +%expect 1 %start ModuleDefinition %% @@ -364,8 +366,6 @@ ModuleDefinition: Identifier objid_opt kw_DEFINITIONS TagDefault ExtensionDefaul fprintf(jsonfile, "]}\n"); free(o); } - | CLASS_IDENTIFIER objid_opt kw_DEFINITIONS TagDefault ExtensionDefault - EEQUAL kw_BEGIN ModuleBody kw_END ; TagDefault : kw_EXPLICIT kw_TAGS @@ -914,10 +914,9 @@ ParamGovernor : DefinedObjectClass /* | Type */ ; -Type : BuiltinType - | ReferencedType - | ConstrainedType - ; +UnconstrainedType : BuiltinType | ReferencedType; + +Type : UnconstrainedType | ConstrainedType ; BuiltinType : BitStringType | BooleanType @@ -948,39 +947,49 @@ BooleanType : kw_BOOLEAN } ; -range : '(' Value RANGE Value ')' + /* + * The spec says the values in a ValueRange are Values, but a) all + * the various value ranges do not involve OBJECT IDENTIFIER, b) + * we only support integer value ranges at this time (as opposed + * to, e.g., time ranges, and we don't even support time values at + * this time), c) allowing OBJECT IDENTIFIER here causes a + * shift-reduce conflict, so we limit ourselves to integer values + * in ranges. We could always define IntegerValueRange, + * TimeValueRange, etc. when we add support for more value types. + */ +range : IntegerValue RANGE IntegerValue { - if($2->type != integervalue) + if($1->type != integervalue) lex_error_message("Non-integer used in first part of range"); - if($2->type != integervalue) + if($1->type != integervalue) lex_error_message("Non-integer in second part of range"); $$ = ecalloc(1, sizeof(*$$)); - $$->min = $2->u.integervalue; - $$->max = $4->u.integervalue; + $$->min = $1->u.integervalue; + $$->max = $3->u.integervalue; } - | '(' Value RANGE kw_MAX ')' + | IntegerValue RANGE kw_MAX { - if($2->type != integervalue) + if($1->type != integervalue) lex_error_message("Non-integer in first part of range"); $$ = ecalloc(1, sizeof(*$$)); - $$->min = $2->u.integervalue; + $$->min = $1->u.integervalue; $$->max = INT_MAX; } - | '(' kw_MIN RANGE Value ')' + | kw_MIN RANGE IntegerValue { - if($4->type != integervalue) + if($3->type != integervalue) lex_error_message("Non-integer in second part of range"); $$ = ecalloc(1, sizeof(*$$)); $$->min = INT_MIN; - $$->max = $4->u.integervalue; + $$->max = $3->u.integervalue; } - | '(' Value ')' + | IntegerValue { - if($2->type != integervalue) + if($1->type != integervalue) lex_error_message("Non-integer used in limit"); $$ = ecalloc(1, sizeof(*$$)); - $$->min = $2->u.integervalue; - $$->max = $2->u.integervalue; + $$->min = $1->u.integervalue; + $$->max = $1->u.integervalue; } ; @@ -990,12 +999,6 @@ IntegerType : kw_INTEGER $$ = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, new_type(TInteger)); } - | kw_INTEGER range - { - $$ = new_type(TInteger); - $$->range = $2; - $$ = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, $$); - } | kw_INTEGER '{' NamedNumberList '}' { $$ = new_type(TInteger); @@ -1101,8 +1104,8 @@ NullType : kw_NULL size : { $$ = NULL; } - | kw_SIZE range - { $$ = $2; } + | kw_SIZE '(' range ')' + { $$ = $3; } ; @@ -1250,10 +1253,17 @@ UsefulType : kw_GeneralizedTime } ; -ConstrainedType : Type Constraint +ConstrainedType : UnconstrainedType Constraint { $$ = $1; - $$->constraint = $2; + if ($2->ctype == CT_RANGE) { + if ($1->type != TTag || $1->subtype->type != TInteger) + lex_error_message("RANGE constraints apply only to INTEGER types"); + $$->subtype->range = $2->u.range; + free($2); + } else { + $$->constraint = $2; + } /* if (Constraint.type == contentConstraint) { assert(Constraint.u.constraint.type == octetstring|bitstring-w/o-NamedBitList); // remember to check type reference too if (Constraint.u.constraint.type) { @@ -1274,9 +1284,15 @@ Constraint : '(' ConstraintSpec ')' } ; -ConstraintSpec : GeneralConstraint +ConstraintSpec : SubtypeConstraint | GeneralConstraint ; +SubtypeConstraint: range + { + $$ = new_constraint_spec(CT_RANGE); + $$->u.range = $1; + } + GeneralConstraint: ContentsConstraint | UserDefinedConstraint | TableConstraint @@ -1452,7 +1468,7 @@ tagenv : /* */ ; -ValueAssignment : Identifier Type EEQUAL Value +ValueAssignment : VALUE_IDENTIFIER Type EEQUAL Value { Symbol *s; s = addsym ($1); diff --git a/lib/asn1/symbol.h b/lib/asn1/symbol.h index 933d9fa06..8a24e2515 100644 --- a/lib/asn1/symbol.h +++ b/lib/asn1/symbol.h @@ -120,7 +120,7 @@ struct range { int64_t max; }; -enum ctype { CT_CONTENTS, CT_USER, CT_TABLE_CONSTRAINT } ; +enum ctype { CT_CONTENTS, CT_USER, CT_TABLE_CONSTRAINT, CT_RANGE } ; struct constraint_spec; @@ -217,6 +217,7 @@ struct constraint_spec { struct value *encoding; struct component_relation_constraint crel; } content; + struct range *range; } u; };