Commit d370e9f5 authored by Lev Walkin's avatar Lev Walkin
Browse files

parsing WITH SYNTAX clauses

parent 57074f10
......@@ -2,9 +2,9 @@
0.9.21: 2006-Mar-14
* skeletons/standard-modules directory is now used for standard types.
* Refactored system for parsing Information Object Classes.
* Fixed class field access problem (Test case 98)
(Severity: medim; Security impact: none)
* Refactored system for parsing Information Object Classes.
0.9.20: 2006-Mar-06
......
......@@ -129,8 +129,10 @@ main(int ac, char **av) {
exit(EX_USAGE);
}
asn1_compiler_flags |= A1C_PDU_AUTO;
} else if(strcmp(optarg, "rint-class-matrix") == 0) {
asn1_printer_flags |= APF_PRINT_CLASS_MATRIX;
} else if(strcmp(optarg, "rint-constraints") == 0) {
asn1_printer_flags |= APF_DEBUG_CONSTRAINTS;
asn1_printer_flags |= APF_PRINT_CONSTRAINTS;
} else if(strcmp(optarg, "rint-lines") == 0) {
asn1_printer_flags |= APF_LINE_COMMENTS;
} else {
......@@ -459,6 +461,7 @@ usage(const char *av0) {
"\n"
" -print-constraints Explain subtype constraints (debug)\n"
" -print-class-matrix Print out the collected object class matrix (debug)\n"
" -print-lines Generate \"-- #line\" comments in -E output\n"
,
......
......@@ -188,8 +188,9 @@ asn1f_fix_module__phase_1(arg_t *arg) {
/* Do not process the parametrized type just yet */
continue;
DEBUG("=== Now processing \"%s\" at line %d ===",
expr->Identifier, expr->_lineno);
DEBUG("=== Now processing \"%s\" (%d/0x%x) at line %d ===",
expr->Identifier, expr->meta_type, expr->expr_type,
expr->_lineno);
assert(expr->meta_type != AMT_INVALID);
/*
......@@ -223,9 +224,10 @@ asn1f_fix_module__phase_1(arg_t *arg) {
RET2RVAL(ret, rvalue);
/*
* Parse WITH SYNTAX in CLASSes.
* Parse class objects and fill up the object class with data.
*/
ret = asn1f_parse_class_with_syntax(arg);
ret = asn1f_parse_class_object(arg);
RET2RVAL(ret, rvalue);
/*
* Resolve references in constraints.
......@@ -293,6 +295,9 @@ asn1f_fix_module__phase_2(arg_t *arg) {
int rvalue = 0;
int ret;
TQ_FOR(expr, &(arg->mod->members), next) {
}
TQ_FOR(expr, &(arg->mod->members), next) {
arg->expr = expr;
......
#include "asn1fix_internal.h"
#include "asn1fix_cws.h"
static int _asn1f_parse_class_object_data(arg_t *, asn1p_expr_t *eclass,
struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax,
uint8_t *buf, const uint8_t *bend,
int optional_mode, uint8_t **newpos);
static int _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell, uint8_t *buf, const uint8_t *bend);
int
asn1f_parse_class_with_syntax(arg_t *arg) {
asn1f_parse_class_object(arg_t *arg) {
asn1p_expr_t *expr = arg->expr;
asn1p_expr_t *eclass;
asn1p_ioc_row_t *row;
void *new_rows_ptr;
int ret;
if(expr->meta_type != AMT_VALUE
|| expr->expr_type != A1TC_REFERENCE
|| !expr->value
|| expr->value->type != ATV_UNPARSED)
return 0;
if(expr->expr_type != A1TC_CLASSDEF
|| expr->with_syntax == NULL)
/*
* Find the governing class.
*/
eclass = asn1f_find_terminal_type(arg, expr);
if(!eclass
|| eclass->meta_type != AMT_OBJECTCLASS
|| eclass->expr_type != A1TC_CLASSDEF) {
return 0;
}
DEBUG("Value %s of CLASS %s found at line %d",
expr->Identifier, eclass->Identifier, expr->_lineno);
if(!eclass->with_syntax) {
DEBUG("Can't process classes without WITH SYNTAX just yet");
return 0;
}
row = asn1p_ioc_row_new(eclass);
assert(row);
ret = _asn1f_parse_class_object_data(arg, eclass, row,
eclass->with_syntax,
expr->value->value.string.buf + 1,
expr->value->value.string.buf
+ expr->value->value.string.size - 1,
0, 0);
if(ret) {
LOG((ret < 0),
"Cannot parse %s of CLASS %s found at line %d",
expr->Identifier, eclass->Identifier, expr->_lineno);
asn1p_ioc_row_delete(row);
return ret;
}
new_rows_ptr = realloc(eclass->object_class_matrix.row,
(eclass->object_class_matrix.rows + 1)
* sizeof(eclass->object_class_matrix.row[0]));
assert(new_rows_ptr);
eclass->object_class_matrix.row = new_rows_ptr;
eclass->object_class_matrix.row[eclass->object_class_matrix.rows] = row;
eclass->object_class_matrix.rows++;
/* Propagate max identifier length */
if(eclass->object_class_matrix.max_identifier_length
< row->max_identifier_length)
eclass->object_class_matrix.max_identifier_length
= row->max_identifier_length;
return 0;
}
#define SKIPSPACES for(; buf < bend && isspace(*buf); buf++)
static int
_asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass,
struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax,
uint8_t *buf, const uint8_t *bend,
int optional_mode, uint8_t **newpos) {
struct asn1p_wsyntx_chunk_s *chunk;
int ret;
DEBUG("Class %s: checking WITH SYNTAX", expr->Identifier);
TQ_FOR(chunk, (&syntax->chunks), next) {
switch(chunk->type) {
case WC_LITERAL: {
int token_len = strlen(chunk->content.token);
SKIPSPACES;
if(bend - buf < token_len
|| memcmp(buf, chunk->content.token, token_len)) {
if(!optional_mode) {
FATAL("While parsing object class value %s at line %d: Expected: \"%s\", found: \"%s\"",
arg->expr->Identifier, arg->expr->_lineno, chunk->content.token, buf);
}
if(newpos) *newpos = buf;
return -1;
}
buf += token_len;
} break;
case WC_WHITESPACE: break; /* Ignore whitespace */
case WC_FIELD: {
struct asn1p_ioc_cell_s *cell;
uint8_t *p;
SKIPSPACES;
int lbraces = 0;
p = buf;
if(p < bend && *p == '{')
lbraces = 1, p++;
for(; p < bend; p++) {
if(lbraces) {
/* Search the terminating brace */
switch(*p) {
case '}': lbraces--; break;
case '{': lbraces++; break;
}
} else if(isspace(*p)) {
break;
}
}
if(lbraces) {
FATAL("Field reference %s found in class value definition for %s at line %d can not be satisfied by broken value \"%s\"",
chunk->content.token,
arg->expr->Identifier, arg->expr->_lineno, buf);
if(newpos) *newpos = buf;
return -1;
}
cell = asn1p_ioc_row_cell_fetch(row,
chunk->content.token);
if(cell == NULL) {
FATAL("Field reference %s found in WITH SYNAX {} clause does not match actual field in Object Class %s",
chunk->content.token,
eclass->Identifier, eclass->_lineno);
if(newpos) *newpos = buf;
return -1;
}
DEBUG("Reference %s satisfied by %s (%d)",
chunk->content.token,
buf, p - buf);
ret = _asn1f_assign_cell_value(arg, row, cell, buf, p);
if(ret) {
if(newpos) *newpos = buf;
return ret;
}
buf = p;
} break;
case WC_OPTIONALGROUP: {
uint8_t *np = 0;
SKIPSPACES;
ret = _asn1f_parse_class_object_data(arg, eclass, row,
chunk->content.syntax, buf, bend, 1, &np);
if(newpos) *newpos = np;
if(ret && np != buf)
return ret;
} break;
}
}
if(newpos) *newpos = buf;
return 0;
}
static int
_asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell,
uint8_t *buf, const uint8_t *bend) {
asn1p_expr_t *expr;
asn1p_ref_t *ref;
char *p;
if((bend - buf) <= 0) {
FATAL("Assignment warning: empty string is being assigned into %s for %s at line %d",
cell->field->Identifier,
arg->expr->Identifier, arg->expr->_lineno);
return -1;
}
p = malloc(bend - buf + 1);
assert(p);
memcpy(p, buf, bend - buf);
p[bend - buf] = '\0';
if(!isalpha(*p)) {
if(isdigit(*p)) {
asn1c_integer_t value;
if(asn1p_atoi(p, &value)) {
FATAL("Value %s at line %d is too large for this compiler! Please contact the asn1c author.\n", p, arg->expr->_lineno);
return -1;
}
expr = asn1p_expr_new(arg->expr->_lineno);
expr->Identifier = p;
expr->meta_type = AMT_VALUE;
expr->expr_type = ASN_BASIC_INTEGER;
expr->value = asn1p_value_fromint(value);
} else {
WARNING("asn1c is not yet able to parse arbitrary direct values; please convert %s at line %d to a reference.", p, arg->expr->_lineno);
free(p);
return 1;
}
} else {
ref = asn1p_ref_new(arg->expr->_lineno);
asn1p_ref_add_component(ref, p, RLT_UNKNOWN);
assert(ref);
expr = asn1f_lookup_symbol(arg, arg->mod, ref);
if(!expr) {
FATAL("Cannot find %s referenced by %s at line %d",
p, arg->expr->Identifier,
arg->expr->_lineno);
return -1;
}
}
DEBUG("Field %s assignment of %s got %s",
cell->field->Identifier, p, expr->Identifier);
cell->value = expr;
if(row->max_identifier_length < strlen(expr->Identifier))
row->max_identifier_length = strlen(expr->Identifier);
return 0;
}
......@@ -2,9 +2,8 @@
#define _ASN1FIX_CLASS_WITH_SYNTAX_H_
/*
* CLASS may contain the "WITH SYNTAX" clause, in which case we are
* going to parse it.
* Parse class objects
*/
int asn1f_parse_class_with_syntax(arg_t *arg);
int asn1f_parse_class_object(arg_t *arg);
#endif /* _ASN1FIX_CLASS_WITH_SYNTAX_H_ */
......@@ -6,6 +6,61 @@
#include "asn1parser.h"
asn1p_ioc_row_t *
asn1p_ioc_row_new(asn1p_expr_t *oclass) {
asn1p_ioc_row_t *row;
asn1p_expr_t *field;
int columns = 0;
assert(oclass->expr_type == A1TC_CLASSDEF);
row = calloc(1, sizeof *row);
if(!row) return NULL;
TQ_FOR(field, &oclass->members, next)
columns++;
row->column = calloc(columns, sizeof *row->column);
if(!row->column) {
free(row);
return NULL;
}
row->columns = columns;
columns = 0;
TQ_FOR(field, &oclass->members, next) {
int fieldIdLen = strlen(field->Identifier);
if(fieldIdLen > row->max_identifier_length)
row->max_identifier_length = fieldIdLen;
row->column[columns].field = field;
row->column[columns].value = NULL;
columns++;
}
return row;
}
void
asn1p_ioc_row_delete(asn1p_ioc_row_t *row) {
if(row) {
if(row->column) {
free(row->column);
}
free(row);
}
}
struct asn1p_ioc_cell_s *
asn1p_ioc_row_cell_fetch(asn1p_ioc_row_t *row, const char *fieldname) {
int i;
for(i = 0; i < row->columns; i++) {
if(strcmp(row->column[i].field->Identifier, fieldname) == 0)
return &row->column[i];
}
errno = ESRCH;
return NULL;
}
asn1p_wsyntx_chunk_t *
asn1p_wsyntx_chunk_new() {
asn1p_wsyntx_chunk_t *wc;
......@@ -21,8 +76,8 @@ asn1p_wsyntx_chunk_free(asn1p_wsyntx_chunk_t *wc) {
switch(wc->type) {
case WC_LITERAL:
case WC_WHITESPACE:
case WC_FIELD:
free(wc->content.token); break;
case WC_REFERENCE: asn1p_ref_free(wc->content.ref); break;
case WC_OPTIONALGROUP:
asn1p_wsyntx_free(wc->content.syntax);
break;
......@@ -41,12 +96,10 @@ asn1p_wsyntx_chunk_clone(asn1p_wsyntx_chunk_t *wc) {
switch(wc->type) {
case WC_LITERAL:
case WC_WHITESPACE:
case WC_FIELD:
nc->content.token = malloc(strlen(wc->content.token)+1);
strcpy(nc->content.token, wc->content.token);
break;
case WC_REFERENCE:
nc->content.ref = asn1p_ref_clone(wc->content.ref);
break;
case WC_OPTIONALGROUP:
nc->content.syntax = asn1p_wsyntx_clone(wc->content.syntax);
break;
......@@ -100,26 +153,6 @@ asn1p_wsyntx_clone(asn1p_wsyntx_t *wx) {
return nw;
}
asn1p_wsyntx_chunk_t *
asn1p_wsyntx_chunk_fromref(asn1p_ref_t *ref, int do_copy) {
asn1p_wsyntx_chunk_t *wc;
if(do_copy) {
static asn1p_wsyntx_chunk_t tmp;
tmp.type = WC_REFERENCE;
tmp.content.ref = ref;
wc = asn1p_wsyntx_chunk_clone(&tmp);
} else {
wc = asn1p_wsyntx_chunk_new();
if(wc) {
wc->type = WC_REFERENCE;
wc->content.ref = ref;
}
}
return wc;
}
asn1p_wsyntx_chunk_t *
asn1p_wsyntx_chunk_frombuf(char *buf, int len, int do_copy) {
asn1p_wsyntx_chunk_t *wc;
......
......@@ -6,6 +6,22 @@
#include "asn1p_ref.h"
struct asn1p_expr_s; /* Forward declaration */
typedef struct asn1p_ioc_row_s {
struct asn1p_ioc_cell_s {
struct asn1p_expr_s *field; /* may never be NULL */
struct asn1p_expr_s *value; /* may be left uninitialized */
} *column;
int columns;
int max_identifier_length;
} asn1p_ioc_row_t;
asn1p_ioc_row_t *asn1p_ioc_row_new(struct asn1p_expr_s *oclass);
void asn1p_ioc_row_delete(asn1p_ioc_row_t *);
struct asn1p_ioc_cell_s *asn1p_ioc_row_cell_fetch(asn1p_ioc_row_t *,
const char *fieldname);
/*
* WITH SYNTAX free-form chunks.
*/
......@@ -13,18 +29,17 @@ typedef struct asn1p_wsyntx_chunk_s {
enum {
WC_LITERAL,
WC_WHITESPACE,
WC_REFERENCE,
WC_FIELD,
WC_OPTIONALGROUP
} type;
/*
* WC_LITERAL -> {token}
* WC_WHITESPACE -> {token}
* WC_REFERENCE -> {ref}
* WC_FIELD -> {token}
* WC_OPTIONALGROUP -> {syntax}
*/
union {
char *token;
asn1p_ref_t *ref;
char *token;
struct asn1p_wsyntx_s *syntax;
} content;
......@@ -54,7 +69,6 @@ asn1p_wsyntx_t *asn1p_wsyntx_clone(asn1p_wsyntx_t *);
* 0: Component has been added
* -1: Failure to add component (refer to errno)
*/
asn1p_wsyntx_chunk_t *asn1p_wsyntx_chunk_fromref(asn1p_ref_t *ref, int do_copy);
asn1p_wsyntx_chunk_t *asn1p_wsyntx_chunk_frombuf(char *buf, int len, int _copy);
asn1p_wsyntx_chunk_t *asn1p_wsyntx_chunk_fromsyntax(asn1p_wsyntx_t *syntax);
......
......@@ -163,6 +163,13 @@ typedef struct asn1p_expr_s {
*/
asn1p_wsyntx_t *with_syntax;
/* Information Object Class matrix, specific for this class */
struct asn1p_ioc_matrix_s {
asn1p_ioc_row_t **row;
int rows;
int max_identifier_length;
} object_class_matrix;
/*
* A tag.
*/
......
This diff is collapsed.
......@@ -23,10 +23,11 @@ void asn1p_lexer_hack_push_encoding_control(void); /* Used in .y */
int asn1p_lexer_pedantic_1990 = 0;
int asn1p_lexer_types_year = 0;
int asn1p_lexer_constructs_year = 0;
static asn1c_integer_t asn1p_atoi(char *ptr); /* errno is either 0 or ERANGE */
int asn1p_as_pointer;
static asn1c_integer_t _lex_atoi(const char *ptr);
/*
* Check that the type is defined in the year of the standard choosen.
*/
......@@ -219,21 +220,21 @@ WSP [\t\r\v\f\n ]
-[1-9][0-9]* {
asn1p_lval.a_int = asn1p_atoi(yytext);
asn1p_lval.a_int = _lex_atoi(yytext);
if(errno == ERANGE)
return -1;
return TOK_number_negative;
}
[1-9][0-9]* {
asn1p_lval.a_int = asn1p_atoi(yytext);
asn1p_lval.a_int = _lex_atoi(yytext);
if(errno == ERANGE)
return -1;
return TOK_number;
}
"0" {
asn1p_lval.a_int = asn1p_atoi(yytext);
asn1p_lval.a_int = _lex_atoi(yytext);
if(errno == ERANGE)
return -1;
return TOK_number;
......@@ -437,10 +438,10 @@ WITH return TOK_WITH;
char *p;
for(p = yytext; *p; p++)
if(*p >= '0' && *p <= '9')
{ v1 = asn1p_atoi(p); break; }
{ v1 = _lex_atoi(p); break; }
while(*p >= '0' && *p <= '9') p++; /* Skip digits */
for(; *p; p++) if(*p >= '0' && *p <= '9')
{ v2 = asn1p_atoi(p); break; }
{ v2 = _lex_atoi(p); break; }
if(v1 < 0 || v1 > 7) {
fprintf(stderr, "%s at line %d: X.680:2003, #37.14 "
"mandates 0..7 range for Tuple's TableColumn\n",
......@@ -462,16 +463,16 @@ WITH return TOK_WITH;
char *p;
for(p = yytext; *p; p++)
if(*p >= '0' && *p <= '9')
{ v1 = asn1p_atoi(p); break; }
{ v1 = _lex_atoi(p); break; }
while(*p >= '0' && *p <= '9') p++; /* Skip digits */
for(; *p; p++) if(*p >= '0' && *p <= '9')
{ v2 = asn1p_atoi(p); break; }
{ v2 = _lex_atoi(p); break; }
while(*p >= '0' && *p <= '9') p++;
for(; *p; p++) if(*p >= '0' && *p <= '9')
{ v3 = asn1p_atoi(p); break; }
{ v3 = _lex_atoi(p); break; }
while(*p >= '0' && *p <= '9') p++;
for(; *p; p++) if(*p >= '0' && *p <= '9')
{ v4 = asn1p_atoi(p); break; }
{ v4 = _lex_atoi(p); break; }
if(v1 < 0 || v1 > 127) {
fprintf(stderr, "%s at line %d: X.680:2003, #37.12 "
"mandates 0..127 range for Quadruple's Group\n",
......@@ -552,30 +553,14 @@ void asn1p_lexer_hack_push_encoding_control() {
}
static asn1c_integer_t
asn1p_atoi(char *ptr) {
_lex_atoi(const char *ptr) {
asn1c_integer_t value;
errno = 0; /* Clear the error code */
if(sizeof(value) <= sizeof(int)) {
value = strtol(ptr, 0, 10);
} else {
#ifdef HAVE_STRTOIMAX
value = strtoimax(ptr, 0, 10);
#elif HAVE_STRTOLL
value = strtoll(ptr, 0, 10);
#else
value = strtol(ptr, 0, 10);
#endif
}
if(errno == ERANGE) {
if(asn1p_atoi(ptr, &value)) {
fprintf(stderr,
"Value \"%s\" at line %d is too large "
"for this compiler! Please contact the asn1c author.\n",
ptr, yylineno);
errno = ERANGE; /* Restore potentially clobbered errno */
errno = ERANGE;
}
return value;
}
This diff is collapsed.
......@@ -242,8 +242,7 @@ static void _fixup_anonymous_identifier(asn1p_expr_t *expr);
%type <a_ref> ComplexTypeReference
%type <a_ref> ComplexTypeReferenceAmpList
%type <a_refcomp> ComplexTypeReferenceElement
%type <a_refcomp> ClassFieldIdentifier
%type <a_refcomp> ClassFieldName
%type <a_refcomp> PrimitiveFieldReference
%type <a_expr> FieldSpec
%type <a_ref> FieldName
%type <a_ref> DefinedObjectClass
......@@ -1081,14 +1080,9 @@ WithSyntaxToken:
| TOK_Literal {
$$ = asn1p_wsyntx_chunk_frombuf($1, strlen($1), 0);
}
| ClassFieldIdentifier {
asn1p_ref_t *ref;
int ret;
ref = asn1p_ref_new(yylineno);
checkmem(ref);
ret = asn1p_ref_add_component(ref, $1.name, $1.lex_type);
checkmem(ret == 0);
$$ = asn1p_wsyntx_chunk_fromref(ref, 0);
| PrimitiveFieldReference {
$$ = asn1p_wsyntx_chunk_frombuf($1.name, strlen($1.name), 0);
$$->type = WC_FIELD;
}
| '[' WithSyntaxList ']' {
$$ = asn1p_wsyntx_chunk_fromsyntax($2);
......@@ -1365,10 +1359,9 @@ ComplexTypeReferenceAmpList: