Have forgotten to attach the patch in my previous message :(
From 5e9cf4df6e5f8c98b621c4e1a862ccb8e1e28e14 Mon Sep 17 00:00:00 2001
From: ysnegirev <[email protected]>
Date: Mon, 18 Jun 2012 18:35:11 +0600
Subject: [PATCH 1/5] Implemented parsing ASN.1 descriptions from string

---
 lib/ASN1.y     |  131 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 lib/libtasn1.h |    4 ++
 2 files changed, 128 insertions(+), 7 deletions(-)

diff --git a/lib/ASN1.y b/lib/ASN1.y
index 80a68cc..de83979 100644
--- a/lib/ASN1.y
+++ b/lib/ASN1.y
@@ -46,9 +46,35 @@ static char lastToken[ASN1_MAX_NAME_SIZE+1];	/* last token find in the file
 extern char _asn1_identifierMissing[];
 static const char *fileName;		/* file to parse */
 
+
+enum _Mode 
+{
+    MODE_FILE,
+    MODE_BUF
+};
+
+struct _InputHandler
+{
+    int (*get) (void *From);
+    int (*unget) (int c, void *From);
+    const char *buf;
+    unsigned long pos;
+    unsigned long capacity;
+    enum _Mode mode;
+};
+typedef struct _InputHandler InputHandler;
+static InputHandler handler;
+
+static int get(void);
+static int unget(int c);
+
+static int str_get(void);
+static int str_unget(int c);
+
 static int _asn1_yyerror (const char *);
 static int _asn1_yylex(void);
 
+
 %}
 
 /* Prefix symbols and functions with _asn1_ */
@@ -422,7 +448,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 */
@@ -430,7 +456,7 @@ _asn1_yylex()
 
   while(1)
     {
-    while((c=fgetc(file_asn1))==' ' || c=='\t' || c=='\n')
+    while((c=get())==' ' || c=='\t' || c=='\n')
       if(c=='\n') lineNumber++;
 
     if(c==EOF){
@@ -445,8 +471,8 @@ _asn1_yylex()
       return c;
     }
     if(c=='-'){  /* Maybe the first '-' of a comment */
-      if((c=fgetc(file_asn1))!='-'){
-	ungetc(c,file_asn1);
+      if((c=get())!='-'){
+	unget(c);
 	lastToken[0]='-';lastToken[1]=0;
 	return '-';
       }
@@ -454,7 +480,7 @@ _asn1_yylex()
 	lastc=0;
 	counter=0;
 	/* A comment finishes at the next double hypen or the end of line */
-	while((c=fgetc(file_asn1))!=EOF && c!='\n' &&
+	while((c=get())!=EOF && c!='\n' &&
 	      (lastc!='-' || (lastc=='-' && c!='-')))
 	  lastc=c;
 	if(c==EOF){
@@ -469,7 +495,7 @@ _asn1_yylex()
     }
     string[counter++]=c;
     /* Till the end of the token */
-    while(!((c=fgetc(file_asn1))==EOF || c==' '|| c=='\t' || c=='\n' ||
+    while(!((c=get())==EOF || c==' '|| c=='\t' || c=='\n' ||
 	     c=='(' || c==')' || c=='[' || c==']' ||
 	     c=='{' || c=='}' || c==',' || c=='.'))
       {
@@ -479,7 +505,7 @@ _asn1_yylex()
 	}
 	string[counter++]=c;
       }
-    ungetc(c,file_asn1);
+    unget(c);
     string[counter]=0;
     strcpy(lastToken,string);
 
@@ -596,6 +622,9 @@ asn1_parser2tree(const char *file_name, ASN1_TYPE *definitions,
   }
   else{
     result_parse=ASN1_SUCCESS;
+    /*handler.get = getc;
+    handler.unget = ungetc;*/
+    handler.mode = MODE_FILE;
 
     lineNumber=1;
     yyparse();
@@ -676,6 +705,7 @@ int asn1_parser2array(const char *inputFileName,const char *outputFileName,
     result_parse=ASN1_FILE_NOT_FOUND;
   else{
     result_parse=ASN1_SUCCESS;
+    handler.mode = MODE_FILE;
 
     lineNumber=1;
     yyparse();
@@ -777,3 +807,90 @@ static int _asn1_yyerror (const char *s)
 
   return 0;
 }
+
+static int str_get(void)
+{
+    int ret = EOF;
+    if(handler.pos < handler.capacity)
+        ret = (int)handler.buf[handler.pos++];
+    return ret;
+}
+
+static int str_unget(int c)
+{
+    handler.pos--;
+    return c;
+}
+
+static int get(void)
+{
+    switch (handler.mode) {
+        case MODE_FILE:
+            return getc(file_asn1);
+        case MODE_BUF:
+        default:
+            return str_get();
+    }
+}
+
+static int unget(int c)
+{
+    switch (handler.mode) {
+        case MODE_FILE:
+            return ungetc(c, file_asn1);
+        case MODE_BUF:
+        default:
+            return str_unget(c);
+    }
+}
+
+asn1_retCode
+asn1_parser_from_buf(const char *buf, unsigned long capacity, ASN1_TYPE *definitions, char *errorDescription)
+{
+    p_tree=ASN1_TYPE_EMPTY;
+    
+    if(*definitions != ASN1_TYPE_EMPTY)
+      return ASN1_ELEMENT_NOT_EMPTY;
+    
+    result_parse = ASN1_SUCCESS;
+    handler.buf = buf;
+    handler.capacity = capacity;
+    /*bufPos = 0;*/
+    handler.pos = 0;
+
+
+    handler.mode = MODE_BUF;
+
+    lineNumber = 1;
+    yyparse();
+
+    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();
+	        /* Convert into DER coding the value assign to INTEGER constants */
+	        _asn1_change_integer_value(p_tree);
+	        /* Expand the IDs of OBJECT IDENTIFIER constants */
+	        _asn1_expand_object_id(p_tree);
+
+	        *definitions=p_tree;
+      }
+      else /* some identifiers not defined */
+	/* Delete the list and the ASN1 structure */
+	_asn1_delete_list_and_nodes();
+    }
+    else  /* syntax error */
+      /* Delete the list and the ASN1 structure */
+      _asn1_delete_list_and_nodes();
+
+  if (errorDescription!=NULL)
+	_asn1_create_errorDescription(result_parse,errorDescription);
+
+  return result_parse;
+}
diff --git a/lib/libtasn1.h b/lib/libtasn1.h
index 784a67e..b46b382 100644
--- a/lib/libtasn1.h
+++ b/lib/libtasn1.h
@@ -171,6 +171,10 @@ extern "C"
     asn1_array2tree (const ASN1_ARRAY_TYPE * array,
 		     ASN1_TYPE * definitions, char *errorDescription);
 
+  
+  extern ASN1_API asn1_retCode
+      asn1_parser_from_buf(const char *buf, unsigned long capacity, ASN1_TYPE *definitions, char *errorDescription);
+
   extern ASN1_API void
     asn1_print_structure (FILE * out, ASN1_TYPE structure,
 			  const char *name, int mode);
-- 
1.7.0.4


From ef602dc08b78a2285b0904ee335fbb0323a2462a Mon Sep 17 00:00:00 2001
From: ysnegirev <[email protected]>
Date: Mon, 18 Jun 2012 18:39:31 +0600
Subject: [PATCH 2/5] Forgot to add exports in previous commit

---
 lib/libtasn1.map |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/lib/libtasn1.map b/lib/libtasn1.map
index 1906cd5..2c9dc88 100644
--- a/lib/libtasn1.map
+++ b/lib/libtasn1.map
@@ -18,6 +18,7 @@
 LIBTASN1_0_3
 {
   global:
+    asn1_parser_from_buf;
     asn1_array2tree;
     asn1_bit_der;
     asn1_check_version;
-- 
1.7.0.4


From b5da0c108e1124fac554022a1aa06ea8c1d4d943 Mon Sep 17 00:00:00 2001
From: ysnegirev <[email protected]>
Date: Tue, 19 Jun 2012 10:15:17 +0600
Subject: [PATCH 3/5] Changed function name a bit and slightly adopted documentation from asn1_parser2tree

---
 lib/ASN1.y       |   21 ++++++++++++++++++++-
 lib/libtasn1.h   |    2 +-
 lib/libtasn1.map |    2 +-
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/lib/ASN1.y b/lib/ASN1.y
index de83979..b932ad9 100644
--- a/lib/ASN1.y
+++ b/lib/ASN1.y
@@ -844,8 +844,27 @@ static int unget(int c)
     }
 }
 
+/**
+ * asn1_tree_from_buf:
+ * @buf: Char array, containing ASN.1 description
+ * @capacity: Array length
+ * @definitions: return the pointer to the structure created from
+ *   buffer contents ASN.1 declarations.
+ * @errorDescription : return the error description or an empty
+ *   string if success.
+ *
+ * Parse ASN.1 definitions, contained in buffer, in order to create
+ * structures, necessary for managing those definitions. Does exactly what
+ * asn1_parser2tree does with the file.
+ *
+ * Returns: %ASN1_SUCCESS if the file buffer has correct syntax and every
+ *   identifier is known, %ASN1_ELEMENT_NOT_EMPTY if @definitions not
+ *   %ASN1_TYPE_EMPTY, %ASN1_SYNTAX_ERROR if the syntax is not
+ *   correct, %ASN1_IDENTIFIER_NOT_FOUND if buffer contains an
+ *   identifier that is not defined.
+ **/
 asn1_retCode
-asn1_parser_from_buf(const char *buf, unsigned long capacity, ASN1_TYPE *definitions, char *errorDescription)
+asn1_tree_from_buf(const char *buf, unsigned long capacity, ASN1_TYPE *definitions, char *errorDescription)
 {
     p_tree=ASN1_TYPE_EMPTY;
     
diff --git a/lib/libtasn1.h b/lib/libtasn1.h
index b46b382..91f26ac 100644
--- a/lib/libtasn1.h
+++ b/lib/libtasn1.h
@@ -173,7 +173,7 @@ extern "C"
 
   
   extern ASN1_API asn1_retCode
-      asn1_parser_from_buf(const char *buf, unsigned long capacity, ASN1_TYPE *definitions, char *errorDescription);
+      asn1_tree_from_buf(const char *buf, unsigned long capacity, ASN1_TYPE *definitions, char *errorDescription);
 
   extern ASN1_API void
     asn1_print_structure (FILE * out, ASN1_TYPE structure,
diff --git a/lib/libtasn1.map b/lib/libtasn1.map
index 2c9dc88..abb16d1 100644
--- a/lib/libtasn1.map
+++ b/lib/libtasn1.map
@@ -18,7 +18,7 @@
 LIBTASN1_0_3
 {
   global:
-    asn1_parser_from_buf;
+    asn1_tree_from_buf;
     asn1_array2tree;
     asn1_bit_der;
     asn1_check_version;
-- 
1.7.0.4


From 30b12a75d3fc1d408033b7a8dab445d373eca08f Mon Sep 17 00:00:00 2001
From: ysnegirev <[email protected]>
Date: Tue, 19 Jun 2012 10:19:00 +0600
Subject: [PATCH 4/5] Removed unnecessary comments and reformated code a bit

---
 lib/ASN1.y |   10 +++-------
 1 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/lib/ASN1.y b/lib/ASN1.y
index b932ad9..2a816f2 100644
--- a/lib/ASN1.y
+++ b/lib/ASN1.y
@@ -55,8 +55,6 @@ enum _Mode
 
 struct _InputHandler
 {
-    int (*get) (void *From);
-    int (*unget) (int c, void *From);
     const char *buf;
     unsigned long pos;
     unsigned long capacity;
@@ -622,8 +620,7 @@ asn1_parser2tree(const char *file_name, ASN1_TYPE *definitions,
   }
   else{
     result_parse=ASN1_SUCCESS;
-    /*handler.get = getc;
-    handler.unget = ungetc;*/
+    
     handler.mode = MODE_FILE;
 
     lineNumber=1;
@@ -705,6 +702,7 @@ int asn1_parser2array(const char *inputFileName,const char *outputFileName,
     result_parse=ASN1_FILE_NOT_FOUND;
   else{
     result_parse=ASN1_SUCCESS;
+    
     handler.mode = MODE_FILE;
 
     lineNumber=1;
@@ -874,10 +872,7 @@ asn1_tree_from_buf(const char *buf, unsigned long capacity, ASN1_TYPE *definitio
     result_parse = ASN1_SUCCESS;
     handler.buf = buf;
     handler.capacity = capacity;
-    /*bufPos = 0;*/
     handler.pos = 0;
-
-
     handler.mode = MODE_BUF;
 
     lineNumber = 1;
@@ -913,3 +908,4 @@ asn1_tree_from_buf(const char *buf, unsigned long capacity, ASN1_TYPE *definitio
 
   return result_parse;
 }
+
-- 
1.7.0.4


From dfb7d3d70ac92ef8226a981bc93e80085b0f6f0c Mon Sep 17 00:00:00 2001
From: ysnegirev <[email protected]>
Date: Tue, 19 Jun 2012 17:35:19 +0600
Subject: [PATCH 5/5] Added asn1_tree_from_buf test to Test_parser.c

---
 tests/Test_parser.c |  181 +++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 147 insertions(+), 34 deletions(-)

diff --git a/tests/Test_parser.c b/tests/Test_parser.c
index 76daf09..923f10e 100644
--- a/tests/Test_parser.c
+++ b/tests/Test_parser.c
@@ -30,6 +30,8 @@
 #include <stdlib.h>
 #include "libtasn1.h"
 
+#include <sys/stat.h>
+
 typedef struct
 {
   int lineNumber;
@@ -106,6 +108,26 @@ test_type test_array[] = {
   {0}
 };
 
+typedef struct {
+    char *buf;
+    size_t buf_size; /* current size */
+    size_t capacity; /* maximum size */
+} buffer_ctx;
+
+static int
+resize_buffer(buffer_ctx *ctx, size_t new_capacity)
+{
+    int ret = 0;
+    if(!ctx)
+        ret = -1;
+    else if(ctx->capacity < new_capacity) {
+        ctx->capacity = ctx->buf_size = new_capacity;
+        if(!(ctx->buf = realloc(ctx->buf, ctx->capacity * sizeof(char))))
+            ret = -2;
+    }
+    return ret;
+}
+
 static int
 readLine (FILE * file, char *line)
 {
@@ -145,6 +167,46 @@ createFile (int lineNumber, const char *line)
   fclose (fileIn);
 }
 
+static int
+bufferize_file(const char *fname, buffer_ctx *ctx)
+{
+#define CLEANUP(CODE) {\
+    ret = CODE;        \
+    goto cleanup;      \
+}
+
+    int ret = 0;
+    FILE *in = fopen(fname, "r");
+    
+    if(!in) 
+        return -1;
+    
+    struct stat st;
+    if(fstat(fileno(in), &st) < 0) {
+        printf("stat failed\n");
+        fclose(in);
+        perror("stat");
+        CLEANUP(-2);
+    }
+    memset(ctx->buf, 0, ctx->capacity);
+    if(ctx->capacity < st.st_size) {
+        if( (ret=resize_buffer(ctx, st.st_size)) < 0) {
+            CLEANUP(-3);
+        }
+    }
+    ctx->buf_size = st.st_size;
+    
+    if(fread((void*)ctx->buf, sizeof(char), st.st_size / sizeof(char), in) < st.st_size) {
+        printf("Read error occured\n");
+        CLEANUP(-4);
+    }
+
+cleanup:
+    if(in)
+        fclose(in);
+
+    return ret;
+}
 
 int
 main (int argc, char *argv[])
@@ -180,40 +242,91 @@ main (int argc, char *argv[])
   /* Clear the definitions structures */
   asn1_delete_structure (&definitions);
 
-
-  test = test_array;
-
-  while (test->lineNumber != 0)
-    {
-      testCounter++;
-
-      createFile (test->lineNumber, test->line);
-
-      result =
-	asn1_parser2tree (fileErroredName, &definitions, errorDescription);
-      asn1_delete_structure (&definitions);
-
-      if ((result != test->errorNumber) ||
-	  (strcmp (errorDescription, test->errorDescription)))
-	{
-	  errorCounter++;
-	  printf ("ERROR N. %d:\n", errorCounter);
-	  printf ("  Line %d - %s\n", test->lineNumber, test->line);
-	  printf ("  Error expected: %s - %s\n",
-		  asn1_strerror (test->errorNumber), test->errorDescription);
-	  printf ("  Error detected: %s - %s\n\n", asn1_strerror (result),
-		  errorDescription);
-	}
-
-      test++;
-    }
-
-
-  printf ("Total tests : %d\n", testCounter);
-  printf ("Total errors: %d\n", errorCounter);
-
-  if (errorCounter > 0)
-    return 1;
+  {
+      test = test_array;
+      testCounter = errorCounter = 0;
+
+      while (test->lineNumber != 0)
+        {
+          testCounter++;
+
+          createFile (test->lineNumber, test->line);
+
+          result =
+        asn1_parser2tree (fileErroredName, &definitions, errorDescription);
+          asn1_delete_structure (&definitions);
+
+          if ((result != test->errorNumber) ||
+          (strcmp (errorDescription, test->errorDescription)))
+        {
+          errorCounter++;
+          printf ("ERROR N. %d:\n", errorCounter);
+          printf ("  Line %d - %s\n", test->lineNumber, test->line);
+          printf ("  Error expected: %s - %s\n",
+              asn1_strerror (test->errorNumber), test->errorDescription);
+          printf ("  Error detected: %s - %s\n\n", asn1_strerror (result),
+              errorDescription);
+        }
+
+          test++;
+        }
+
+      printf ("Parsing files:\n");
+      printf ("  Total tests : %d\n", testCounter);
+      printf ("  Total errors: %d\n", errorCounter);
+
+      if (errorCounter > 0)
+        return 1;
+  }
+    
+  /* Now do the same, but dealing with memory buffered ANS.1 
+   * descriptions */
+  {
+      printf("------------------------------\n");
+      test = test_array;
+      testCounter = errorCounter = 0;
+      buffer_ctx ctx;
+      ctx.capacity = ctx.buf_size = 200;
+      if(!(ctx.buf = calloc(ctx.capacity, sizeof(char)))) {
+          printf("Buffer allocation failed\n");
+          exit(-1);
+      }
+      int res = 0;
+
+      while (test->lineNumber != 0) {
+          testCounter++;
+
+          createFile (test->lineNumber, test->line);
+          
+          if( (res = bufferize_file(fileErroredName, &ctx)) < 0) {
+              printf("Failed to bufferize %s contents with code: %d\n", fileErroredName, res);
+              exit(res);
+          }
+
+          result = asn1_tree_from_buf(ctx.buf, ctx.buf_size, &definitions, errorDescription);
+          asn1_delete_structure (&definitions);
+
+          if ((result != test->errorNumber) || 
+                  (strcmp (errorDescription, test->errorDescription))) {
+              errorCounter++;
+              printf ("ERROR N. %d:\n", errorCounter);
+              printf ("  Line %d - %s\n", test->lineNumber, test->line);
+              printf ("  Error expected: %s - %s\n",
+                  asn1_strerror (test->errorNumber), test->errorDescription);
+              printf ("  Error detected: %s - %s\n\n", asn1_strerror (result),
+                  errorDescription);
+          }
+          
+          test++;
+      }
+      
+      printf ("Parsing strings:\n");
+      printf ("  Total tests : %d\n", testCounter);
+      printf ("  Total errors: %d\n", errorCounter);
+
+      if (errorCounter > 0)
+        return 1;
+  }
 
   exit (0);
 }
-- 
1.7.0.4

Reply via email to