diff options
Diffstat (limited to 'lib/ASN1.y')
-rw-r--r-- | lib/ASN1.y | 348 |
1 files changed, 174 insertions, 174 deletions
@@ -1,6 +1,6 @@ %{ /* - * Copyright (C) 2001-2014 Free Software Foundation, Inc. + * Copyright (C) 2001-2022 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * @@ -31,6 +31,7 @@ #include <parser_aux.h> #include <structure.h> #include <libtasn1.h> +#include "c-ctype.h" static list_type *e_list = NULL; static FILE *file_asn1; /* Pointer to file to parse */ @@ -53,6 +54,9 @@ static const char *file_name; /* file to parse */ static void _asn1_yyerror (const char *); static int _asn1_yylex(void); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +#define SAFE_COPY(dst, dst_size, fmt, ...) { snprintf(dst, dst_size, fmt, __VA_ARGS__); } +#else #define SAFE_COPY(dst, dst_size, fmt, ...) { \ int _ret = snprintf(dst, dst_size, fmt, __VA_ARGS__); \ if (_ret != (int)strlen(dst)) \ @@ -62,12 +66,13 @@ static int _asn1_yylex(void); exit(1); \ } \ } +#endif %} /* Prefix symbols and functions with _asn1_ */ /* %define parse.lac full */ -%error-verbose -%name-prefix "_asn1_yy" +%define parse.error verbose +%define api.prefix {_asn1_yy} %union { unsigned int constant; @@ -138,6 +143,7 @@ static int _asn1_yylex(void); %type <str> num_identifier %type <str> int_identifier %type <constant> class explicit_implicit +%type <str> known_string %% @@ -234,12 +240,9 @@ pos_neg_list: pos_neg_num integer_def: INTEGER {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_INTEGER);} | INTEGER'{'constant_list'}' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_INTEGER|CONST_LIST); _asn1_set_down($$,$3);} - | integer_def'(' pos_neg_list ')' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_INTEGER);} + | integer_def'(' pos_neg_list ')' {$$=$1;} | integer_def'('int_identifier'.''.'int_identifier')' - {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_INTEGER|CONST_MIN_MAX); - _asn1_set_down($$,_asn1_add_static_node(&e_list, ASN1_ETYPE_SIZE)); - _asn1_set_value(_asn1_get_down($$),$6,strlen($6)+1); - _asn1_set_name(_asn1_get_down($$),$3);} + {$$=$1;} ; boolean_def: BOOLEAN {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_BOOLEAN);} @@ -322,7 +325,8 @@ bit_element_list : bit_element {$$=$1;} ; bit_string_def : BIT STRING {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_BIT_STRING);} - | BIT STRING size_def {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_BIT_STRING|CONST_SIZE);} + | BIT STRING size_def {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_BIT_STRING|CONST_SIZE); + _asn1_set_down($$,$3);} | BIT STRING'{'bit_element_list'}' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_BIT_STRING|CONST_LIST); _asn1_set_down($$,$4);} @@ -414,9 +418,24 @@ any_def : ANY {$$=_asn1_add_static_node(&e_list, ASN1_E _asn1_set_name(_asn1_get_down($$),$4);} ; -type_def : IDENTIFIER "::=" type_assig_right_tag {$$=_asn1_set_name($3,$1);} - /* below should match: BMPString ::= [UNIVERSAL 30] IMPLICIT OCTET STRING etc*/ - | error "::=" type_assig_right_tag {$$=_asn1_set_name($3, last_error_token);} +known_string: UTF8String { SAFE_COPY($$,sizeof($$),"%s",last_token); } + | VisibleString { SAFE_COPY($$,sizeof($$),"%s",last_token); } + | PrintableString { SAFE_COPY($$,sizeof($$),"%s",last_token); } + | UniversalString { SAFE_COPY($$,sizeof($$),"%s",last_token); } + | IA5String { SAFE_COPY($$,sizeof($$),"%s",last_token); } + | NumericString { SAFE_COPY($$,sizeof($$),"%s",last_token); } + | TeletexString { SAFE_COPY($$,sizeof($$),"%s",last_token); } + | BMPString { SAFE_COPY($$,sizeof($$),"%s",last_token); } + +/* This matches build-in types which are redefined */ +type_invalid : known_string "::=" '[' class NUM ']' IMPLICIT OCTET STRING { +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + fprintf(stderr, "%s:%u: Warning: %s is a built-in ASN.1 type.\n", file_name, line_number, $1); +#endif +} +; + +type_def : IDENTIFIER "::=" type_assig_right_tag { $$=_asn1_set_name($3,$1);} ; constant_def : IDENTIFIER OBJECT STR_IDENTIFIER "::=" '{'obj_constant_list'}' @@ -435,12 +454,20 @@ constant_def : IDENTIFIER OBJECT STR_IDENTIFIER "::=" '{'obj_constant_list'}' ; type_constant: type_def {$$=$1;} + | type_invalid {$$=NULL;} | constant_def {$$=$1;} ; type_constant_list : type_constant {$$=$1;} - | type_constant_list type_constant {$$=$1; - _asn1_set_right(_asn1_get_last_right($1),$2);} + | type_constant_list type_constant {if (!$1) + { + $$ = $2; + } + else + { + $$=$1; + if ($2) _asn1_set_right(_asn1_get_last_right($1),$2); + }} ; definitions_id : IDENTIFIER '{' obj_constant_list '}' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_OBJECT_ID); @@ -509,7 +536,7 @@ static const int key_word_token[] = { /* Token identifier or ASCII code or 0(zero: End Of File) */ /*************************************************************/ static int -_asn1_yylex () +_asn1_yylex (void) { int c, counter = 0, k, lastc; char string[ASN1_MAX_NAME_SIZE + 1]; /* will contain the next token */ @@ -565,7 +592,7 @@ _asn1_yylex () } } } - string[counter++] = c; + string[counter++] = (char) c; /* Till the end of the token */ while (! ((c = fgetc (file_asn1)) == EOF || c == ' ' || c == '\t' @@ -577,7 +604,7 @@ _asn1_yylex () result_parse = ASN1_NAME_TOO_LONG; return 0; } - string[counter++] = c; + string[counter++] = (char) c; } ungetc (c, file_asn1); string[counter] = 0; @@ -585,7 +612,7 @@ _asn1_yylex () /* Is STRING a number? */ for (k = 0; k < counter; k++) - if (!isdigit ((int)string[k])) + if (!c_isdigit ((int)string[k])) break; if (k >= counter) { @@ -663,20 +690,18 @@ _asn1_create_errorDescription (int error, char *error_desc) * opening @file, %ASN1_SYNTAX_ERROR if the syntax is not * correct, %ASN1_IDENTIFIER_NOT_FOUND if in the file there is an * identifier that is not defined, %ASN1_NAME_TOO_LONG if in the - * file there is an identifier whith more than %ASN1_MAX_NAME_SIZE + * file there is an identifier with more than %ASN1_MAX_NAME_SIZE * characters. **/ int asn1_parser2tree (const char *file, asn1_node * definitions, char *error_desc) { - - p_tree = NULL; - if (*definitions != NULL) - return ASN1_ELEMENT_NOT_EMPTY; - - *definitions = NULL; + { + result_parse = ASN1_ELEMENT_NOT_EMPTY; + goto error; + } file_name = file; @@ -686,54 +711,48 @@ asn1_parser2tree (const char *file, asn1_node * definitions, if (file_asn1 == NULL) { result_parse = ASN1_FILE_NOT_FOUND; - } - else - { - result_parse = ASN1_SUCCESS; - - line_number = 1; - yyparse (); - - fclose (file_asn1); - - if (result_parse == ASN1_SUCCESS) - { /* syntax OK */ - /* set IMPLICIT or EXPLICIT property */ - _asn1_set_default_tag (p_tree); - /* set CONST_SET and CONST_NOT_USED */ - _asn1_type_set_config (p_tree); - /* check the identifier definitions */ - result_parse = _asn1_check_identifier (p_tree); - if (result_parse == ASN1_SUCCESS) - { /* all identifier defined */ - /* Delete the list and keep the ASN1 structure */ - _asn1_delete_list (e_list); - e_list = NULL; - /* Convert into DER coding the value assign to INTEGER constants */ - _asn1_change_integer_value (p_tree); - /* Expand the IDs of OBJECT IDENTIFIER constants */ - result_parse = _asn1_expand_object_id (e_list, p_tree); - if (result_parse != ASN1_SUCCESS) - goto error; - - *definitions = p_tree; - } - else /* some identifiers not defined */ - { - /* Delete the list and the ASN1 structure */ - _asn1_delete_list_and_nodes (e_list); - e_list = NULL; - } - } - else /* syntax error */ - { - /* Delete the list and the ASN1 structure */ - _asn1_delete_list_and_nodes (e_list); - e_list = NULL; - } + goto error; } - error: + result_parse = ASN1_SUCCESS; + + line_number = 1; + yyparse (); + + fclose (file_asn1); + + if (result_parse != ASN1_SUCCESS) + goto error; + + /* set IMPLICIT or EXPLICIT property */ + _asn1_set_default_tag (p_tree); + /* set CONST_SET and CONST_NOT_USED */ + _asn1_type_set_config (p_tree); + /* check the identifier definitions */ + result_parse = _asn1_check_identifier (p_tree); + if (result_parse != ASN1_SUCCESS) + goto error; + + /* Convert into DER coding the value assign to INTEGER constants */ + _asn1_change_integer_value (p_tree); + /* Expand the IDs of OBJECT IDENTIFIER constants */ + result_parse = _asn1_expand_object_id (&e_list, p_tree); + if (result_parse != ASN1_SUCCESS) + goto error; + + /* success */ + *definitions = p_tree; + _asn1_delete_list (e_list); + e_list = NULL; + p_tree = NULL; + *error_desc = 0; + return result_parse; + +error: + _asn1_delete_list_and_nodes (e_list); + e_list = NULL; + p_tree = NULL; + _asn1_create_errorDescription (result_parse, error_desc); return result_parse; @@ -761,7 +780,7 @@ asn1_parser2tree (const char *file, asn1_node * definitions, * while opening @inputFileName, %ASN1_SYNTAX_ERROR if the syntax is * not correct, %ASN1_IDENTIFIER_NOT_FOUND if in the file there is * an identifier that is not defined, %ASN1_NAME_TOO_LONG if in the - * file there is an identifier whith more than %ASN1_MAX_NAME_SIZE + * file there is an identifier with more than %ASN1_MAX_NAME_SIZE * characters. **/ int @@ -780,102 +799,99 @@ asn1_parser2array (const char *inputFileName, const char *outputFileName, file_asn1 = fopen (inputFileName, "r"); if (file_asn1 == NULL) - result_parse = ASN1_FILE_NOT_FOUND; - else { - result_parse = ASN1_SUCCESS; - - line_number = 1; - yyparse (); - - fclose (file_asn1); - - if (result_parse == ASN1_SUCCESS) - { /* syntax OK */ - /* set IMPLICIT or EXPLICIT property */ - _asn1_set_default_tag (p_tree); - /* set CONST_SET and CONST_NOT_USED */ - _asn1_type_set_config (p_tree); - /* check the identifier definitions */ - result_parse = _asn1_check_identifier (p_tree); - - if (result_parse == ASN1_SUCCESS) - { /* all identifier defined */ + result_parse = ASN1_FILE_NOT_FOUND; + goto error2; + } - /* searching the last '/' and '.' in inputFileName */ - char_p = inputFileName; - slash_p = inputFileName; - while ((char_p = strchr (char_p, '/'))) - { - char_p++; - slash_p = char_p; - } + result_parse = ASN1_SUCCESS; + + line_number = 1; + yyparse (); + + fclose (file_asn1); + if (result_parse != ASN1_SUCCESS) + goto error1; + + /* set IMPLICIT or EXPLICIT property */ + _asn1_set_default_tag (p_tree); + /* set CONST_SET and CONST_NOT_USED */ + _asn1_type_set_config (p_tree); + /* check the identifier definitions */ + result_parse = _asn1_check_identifier (p_tree); + if (result_parse != ASN1_SUCCESS) + goto error2; + + /* all identifier defined */ + /* searching the last '/' and '.' in inputFileName */ + char_p = inputFileName; + slash_p = inputFileName; + while ((char_p = strchr (char_p, '/'))) + { + char_p++; + slash_p = char_p; + } - char_p = slash_p; - dot_p = inputFileName + strlen (inputFileName); + char_p = slash_p; + dot_p = inputFileName + strlen (inputFileName); - while ((char_p = strchr (char_p, '.'))) - { - dot_p = char_p; - char_p++; - } + while ((char_p = strchr (char_p, '.'))) + { + dot_p = char_p; + char_p++; + } - if (outputFileName == NULL) - { - /* file_out_name = inputFileName + _asn1_tab.c */ - file_out_name = malloc (dot_p - inputFileName + 1 + - sizeof ("_asn1_tab.c")-1); - memcpy (file_out_name, inputFileName, - dot_p - inputFileName); - file_out_name[dot_p - inputFileName] = 0; - strcat (file_out_name, "_asn1_tab.c"); - } - else - { - /* file_out_name = inputFileName */ - file_out_name = - (char *) malloc (strlen (outputFileName) + 1); - strcpy (file_out_name, outputFileName); - } + if (outputFileName == NULL) + { + /* file_out_name = inputFileName + _asn1_tab.c */ + file_out_name = malloc (dot_p - inputFileName + 1 + + sizeof ("_asn1_tab.c")-1); + memcpy (file_out_name, inputFileName, + dot_p - inputFileName); + file_out_name[dot_p - inputFileName] = 0; + strcat (file_out_name, "_asn1_tab.c"); + } + else + { + /* file_out_name = inputFileName */ + file_out_name = strdup(outputFileName); + } - if (vectorName == NULL) - { - unsigned len, i; - /* vector_name = file name + _asn1_tab */ - vector_name = malloc (dot_p - slash_p + 1 + - sizeof("_asn1_tab") - 1); - memcpy (vector_name, slash_p, dot_p - slash_p); - vector_name[dot_p - slash_p] = 0; - strcat (vector_name, "_asn1_tab"); - - len = strlen(vector_name); - for (i=0;i<len;i++) - { - if (vector_name[i] == '-') - vector_name[i] = '_'; - } - } - else - { - /* vector_name = vectorName */ - vector_name = (char *) malloc (strlen (vectorName) + 1); - strcpy (vector_name, vectorName); - } + if (vectorName == NULL) + { + unsigned len, i; + /* vector_name = file name + _asn1_tab */ + vector_name = malloc (dot_p - slash_p + 1 + + sizeof("_asn1_tab") - 1); + memcpy (vector_name, slash_p, dot_p - slash_p); + vector_name[dot_p - slash_p] = 0; + strcat (vector_name, "_asn1_tab"); + + len = strlen(vector_name); + for (i=0;i<len;i++) + { + if (vector_name[i] == '-') + vector_name[i] = '_'; + } + } + else + { + /* vector_name = vectorName */ + vector_name = strdup(vectorName); + } - /* Save structure in a file */ - _asn1_create_static_structure (p_tree, - file_out_name, vector_name); + /* Save structure in a file */ + _asn1_create_static_structure (p_tree, + file_out_name, vector_name); - free (file_out_name); - free (vector_name); - } /* result == OK */ - } /* result == OK */ + free (file_out_name); + free (vector_name); - /* Delete the list and the ASN1 structure */ - _asn1_delete_list_and_nodes (e_list); - e_list = NULL; - } /* inputFile exist */ + error1: + _asn1_delete_list_and_nodes (e_list); + e_list = NULL; + error2: _asn1_create_errorDescription (result_parse, error_desc); return result_parse; @@ -893,22 +909,6 @@ static void _asn1_yyerror (const char *s) { /* Sends the error description to the std_out */ - - if (strcmp (last_token, "VisibleString") == 0 || - strcmp (last_token, "PrintableString") == 0 || - strcmp (last_token, "UniversalString") == 0 || - strcmp (last_token, "IA5String") == 0 || - strcmp (last_token, "UTF8String") == 0 || - strcmp (last_token, "NumericString") == 0 || - strcmp (last_token, "TeletexString") == 0 || - strcmp (last_token, "BMPString") == 0) - { - snprintf (last_error_token, sizeof(last_error_token), - "%s", last_token); - fprintf(stderr, "%s:%u: Warning: %s is a built-in ASN.1 type.\n", - file_name, line_number, last_token); - return; - } last_error_token[0] = 0; if (result_parse != ASN1_NAME_TOO_LONG) |