libtasn1-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU libtasn1 branch, master, updated. libtasn1_3_5-31-gcd9876a


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU libtasn1 branch, master, updated. libtasn1_3_5-31-gcd9876a
Date: Sat, 17 May 2014 06:17:30 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU libtasn1".

http://git.savannah.gnu.org/cgit/libtasn1.git/commit/?id=cd9876aafe51081022f39407201d83a954750aa5

The branch, master has been updated
       via  cd9876aafe51081022f39407201d83a954750aa5 (commit)
       via  44a4680d83fe4ff732e4e1b826c987bc5d67bd1c (commit)
       via  02d59b37540609c0be510642a8eb0f72799ca6c6 (commit)
       via  03fd1d469a5f9ee27ab7466c2b33a92e7b991260 (commit)
       via  07a5adb87880f3fce80aa12121409bbf652f1b6d (commit)
       via  3d6a02f19ff15a38dae9686033e37499b3968256 (commit)
       via  51612fca32dda445056ca9a7533bae258acd3ecb (commit)
       via  f245088c5bd6c7e9bea18e5601ee24d431531558 (commit)
       via  f93acf7f0a3f19692c71fc9022981b6f64ffdbc1 (commit)
       via  3d577dd07e6f8229cc0785e270908bd0d970e890 (commit)
      from  1c3ccb3e040bf13e342ee60bc23b21b97b11923f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit cd9876aafe51081022f39407201d83a954750aa5
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat May 17 08:15:53 2014 +0200

    doc update

commit 44a4680d83fe4ff732e4e1b826c987bc5d67bd1c
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat May 17 08:15:00 2014 +0200

    Marked asn1_der_decoding_element() as deprecated.

commit 02d59b37540609c0be510642a8eb0f72799ca6c6
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat May 17 08:10:32 2014 +0200

    Use the new functions in asn1_decoding_element()

commit 03fd1d469a5f9ee27ab7466c2b33a92e7b991260
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat May 17 08:08:25 2014 +0200

    Revert "asn1_der_decoding_element is just an alias of asn1_der_decoding()."
    
    This reverts commit a8866ebf9a62386bd24f107e8384bbbf032baa52.

commit 07a5adb87880f3fce80aa12121409bbf652f1b6d
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat May 17 08:08:15 2014 +0200

    made _asn1_ltostr() safer.

commit 3d6a02f19ff15a38dae9686033e37499b3968256
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat May 17 00:21:25 2014 +0200

    safer usage of memcpy().

commit 51612fca32dda445056ca9a7533bae258acd3ecb
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat May 17 00:06:01 2014 +0200

    check for zero size in time and object ids.

commit f245088c5bd6c7e9bea18e5601ee24d431531558
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat May 17 00:03:58 2014 +0200

    Allow for zero strings.

commit f93acf7f0a3f19692c71fc9022981b6f64ffdbc1
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri May 16 23:48:27 2014 +0200

    simplify ltostr()

commit 3d577dd07e6f8229cc0785e270908bd0d970e890
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri May 16 22:39:49 2014 +0200

    doc update

-----------------------------------------------------------------------

Summary of changes:
 NEWS                |    3 +
 lib/coding.c        |    6 +-
 lib/decoding.c      |  796 +++++++++++++++++++++++++++++++++++++++++++++++++-
 lib/element.c       |   13 +-
 lib/libtasn1.h      |   14 +-
 lib/parser_aux.c    |   35 ---
 lib/parser_aux.h    |   10 +-
 tests/Test_simple.c |    2 +-
 tests/Test_tree.c   |    2 +
 9 files changed, 818 insertions(+), 63 deletions(-)

diff --git a/NEWS b/NEWS
index 1e62c5d..11d6c27 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,9 @@ GNU Libtasn1 NEWS                                     -*- 
outline -*-
 * Noteworthy changes in release 3.6 (unreleased) [stable]
 - Corrected an off-by-one error in ASN.1 DER tag decoding.
 - Several improvements and new safety checks on DER decoding.
+- Marked asn1_der_decoding_element() as deprecated. Use
+  asn1_der_decoding() instead.
+
 
 * Noteworthy changes in release 3.5 (released 2014-05-01) [stable]
 - Correctly handle decoding of recursive CHOICE options.
diff --git a/lib/coding.c b/lib/coding.c
index e4eb060..c560ebf 100644
--- a/lib/coding.c
+++ b/lib/coding.c
@@ -631,7 +631,7 @@ _asn1_insert_tag_der (asn1_node node, unsigned char *der, 
int *counter,
                    memcpy (der + *counter, tag_der, tag_len);
                  *counter += tag_len;
 
-                 _asn1_ltostr (*counter, (char *) temp);
+                 _asn1_ltostr (*counter, (char *) temp, sizeof(temp));
                  _asn1_set_name (p, (const char *) temp);
 
                  is_tag_implicit = 0;
@@ -1187,7 +1187,7 @@ asn1_der_coding (asn1_node element, const char *name, 
void *ider, int *len,
        case ASN1_ETYPE_SET:
          if (move != UP)
            {
-             _asn1_ltostr (counter, (char *) temp);
+             _asn1_ltostr (counter, (char *) temp, sizeof(temp));
              tlen = _asn1_strlen (temp);
              if (tlen > 0)
                _asn1_set_value (p, temp, tlen + 1);
@@ -1236,7 +1236,7 @@ asn1_der_coding (asn1_node element, const char *name, 
void *ider, int *len,
        case ASN1_ETYPE_SET_OF:
          if (move != UP)
            {
-             _asn1_ltostr (counter, (char *) temp);
+             _asn1_ltostr (counter, (char *) temp, sizeof(temp));
              tlen = _asn1_strlen (temp);
 
              if (tlen > 0)
diff --git a/lib/decoding.c b/lib/decoding.c
index 894be79..bd96d90 100644
--- a/lib/decoding.c
+++ b/lib/decoding.c
@@ -262,7 +262,10 @@ asn1_get_octet_der (const unsigned char *der, int der_len,
 
   *ret_len = *str_len + len_len;
   if (str_size >= *str_len)
-    memcpy (str, der + len_len, *str_len);
+    {
+      if (*str_len > 0)
+        memcpy (str, der + len_len, *str_len);
+    }
   else
     {
       return ASN1_MEM_ERROR;
@@ -281,9 +284,11 @@ _asn1_get_time_der (const unsigned char *der, int der_len, 
int *ret_len,
 
   if (der_len <= 0 || str == NULL)
     return ASN1_DER_ERROR;
+
   str_len = asn1_get_length_der (der, der_len, &len_len);
-  if (str_len < 0 || str_size < str_len)
+  if (str_len <= 0 || str_size < str_len)
     return ASN1_DER_ERROR;
+
   memcpy (str, der + len_len, str_len);
   str[str_len] = 0;
   *ret_len = str_len + len_len;
@@ -309,15 +314,15 @@ _asn1_get_objectid_der (const unsigned char *der, int 
der_len, int *ret_len,
 
   len = asn1_get_length_der (der, der_len, &len_len);
 
-  if (len < 0 || len > der_len || len_len > der_len)
+  if (len <= 0 || len + len_len > der_len)
     return ASN1_DER_ERROR;
 
   val1 = der[len_len] / 40;
   val = der[len_len] - val1 * 40;
 
-  _asn1_str_cpy (str, str_size, _asn1_ltostr (val1, temp));
+  _asn1_str_cpy (str, str_size, _asn1_ltostr (val1, temp, sizeof(temp)));
   _asn1_str_cat (str, str_size, ".");
-  _asn1_str_cat (str, str_size, _asn1_ltostr (val, temp));
+  _asn1_str_cat (str, str_size, _asn1_ltostr (val, temp, sizeof(temp)));
 
   val = 0;
   leading = 1;
@@ -339,7 +344,7 @@ _asn1_get_objectid_der (const unsigned char *der, int 
der_len, int *ret_len,
       if (!(der[len_len + k] & 0x80))
        {
          _asn1_str_cat (str, str_size, ".");
-         _asn1_str_cat (str, str_size, _asn1_ltostr (val, temp));
+         _asn1_str_cat (str, str_size, _asn1_ltostr (val, temp, sizeof(temp)));
          val = 0;
          leading = 1;
        }
@@ -381,12 +386,15 @@ asn1_get_bit_der (const unsigned char *der, int der_len,
 
   *ret_len = len_byte + len_len + 1;
   *bit_len = len_byte * 8 - der[len_len];
-  
-  if (*bit_len <= 0)
+
+  if (*bit_len < 0)
     return ASN1_DER_ERROR;
 
   if (str_size >= len_byte)
-    memcpy (str, der + len_len + 1, len_byte);
+    {
+      if (len_byte > 0)
+        memcpy (str, der + len_len + 1, len_byte);
+    }
   else
     {
       return ASN1_MEM_ERROR;
@@ -1243,7 +1251,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int ider_len,
 
                  if (len3 > 0)
                    {
-                     _asn1_ltostr (counter + len3, temp);
+                     _asn1_ltostr (counter + len3, temp, sizeof(temp));
                      tlen = strlen (temp);
                      if (tlen > 0)
                        _asn1_set_value (p, temp, tlen + 1);
@@ -1331,7 +1339,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int ider_len,
                    {
                      if (len3 > 0)
                        {       /* definite length method */
-                         _asn1_ltostr (counter + len3, temp);
+                         _asn1_ltostr (counter + len3, temp, sizeof(temp));
                          tlen = strlen (temp);
 
                          if (tlen > 0)
@@ -1472,6 +1480,11 @@ cleanup:
   return result;
 }
 
+#define FOUND        1
+#define SAME_BRANCH  2
+#define OTHER_BRANCH 3
+#define EXIT         4
+
 /**
  * asn1_der_decoding_element:
  * @structure: pointer to an ASN1 structure
@@ -1481,14 +1494,15 @@ cleanup:
  * @errorDescription: null-terminated string contains details when an
  *   error occurred.
  *
- * Fill the element named @elementName with values of a DER encoding
+ * Fill the element named @ELEMENTNAME with values of a DER encoding
  * string.  The structure must just be created with function
  * asn1_create_element().  The DER vector must contain the encoding
- * string of the whole @structure.  If an error occurs during the
- * decoding procedure, the address@hidden is deleted and set equal to
+ * string of the whole @STRUCTURE.  If an error occurs during the
+ * decoding procedure, the address@hidden is deleted and set equal to
  * %NULL.
  *
- * As of libtasn1 3.6 this function is an alias of asn1_der_decoding().
+ * This function is deprecated and may just be an alias to asn1_der_decoding
+ * in future versions. Use asn1_der_decoding() instead.
  *
  * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
  *   if ELEMENT is %NULL or @elementName == NULL, and
@@ -1499,7 +1513,757 @@ int
 asn1_der_decoding_element (asn1_node * structure, const char *elementName,
                           const void *ider, int len, char *errorDescription)
 {
-  return asn1_der_decoding(structure, ider, len, errorDescription);
+  asn1_node node, p, p2, p3, nodeFound = NULL;
+  char temp[128], currentName[ASN1_MAX_NAME_SIZE * 10], *dot_p, *char_p;
+  int nameLen = ASN1_MAX_NAME_SIZE * 10 - 1, state;
+  int counter, len2, len3, len4, move, ris, tlen;
+  unsigned char class;
+  unsigned long tag;
+  int indefinite, result;
+  const unsigned char *der = ider;
+
+  node = *structure;
+
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  if (elementName == NULL)
+    {
+      result = ASN1_ELEMENT_NOT_FOUND;
+      goto cleanup;
+    }
+
+  if (node->type & CONST_OPTION)
+    {
+      result = ASN1_GENERIC_ERROR;
+      goto cleanup;
+    }
+
+  if ((*structure)->name[0] != 0)
+    {                          /* Has *structure got a name? */
+      nameLen -= strlen ((*structure)->name);
+      if (nameLen > 0)
+       strcpy (currentName, (*structure)->name);
+      else
+       {
+         result = ASN1_MEM_ERROR;
+         goto cleanup;
+       }
+      if (!(strcmp (currentName, elementName)))
+       {
+         state = FOUND;
+         nodeFound = *structure;
+       }
+      else if (!memcmp (currentName, elementName, strlen (currentName)))
+       state = SAME_BRANCH;
+      else
+       state = OTHER_BRANCH;
+    }
+  else
+    {                          /* *structure doesn't have a name? */
+      currentName[0] = 0;
+      if (elementName[0] == 0)
+       {
+         state = FOUND;
+         nodeFound = *structure;
+       }
+      else
+       {
+         state = SAME_BRANCH;
+       }
+    }
+
+  counter = 0;
+  move = DOWN;
+  p = node;
+  while (1)
+    {
+
+      ris = ASN1_SUCCESS;
+
+      if (move != UP)
+       {
+         if (p->type & CONST_SET)
+           {
+             p2 = _asn1_find_up (p);
+             len2 = _asn1_strtol (p2->value, NULL, 10);
+             if (counter == len2)
+               {
+                 p = p2;
+                 move = UP;
+                 continue;
+               }
+             else if (counter > len2)
+               {
+                 result = ASN1_DER_ERROR;
+                 goto cleanup;
+               }
+             p2 = p2->down;
+             while (p2)
+               {
+                 if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
+                   {
+                     ris =
+                         extract_tag_der_recursive (p2, der + counter,
+                                                len - counter, &len2);
+                     if (ris == ASN1_SUCCESS)
+                       {
+                         p2->type &= ~CONST_NOT_USED;
+                         p = p2;
+                         break;
+                       }
+                   }
+                 p2 = p2->right;
+               }
+             if (p2 == NULL)
+               {
+                 result = ASN1_DER_ERROR;
+                 goto cleanup;
+               }
+           }
+
+         if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
+           {
+             p2 = _asn1_find_up (p);
+             len2 = _asn1_strtol (p2->value, NULL, 10);
+             if (counter == len2)
+               {
+                 if (p->right)
+                   {
+                     p2 = p->right;
+                     move = RIGHT;
+                   }
+                 else
+                   move = UP;
+
+                 if (p->type & CONST_OPTION)
+                   asn1_delete_structure (&p);
+
+                 p = p2;
+                 continue;
+               }
+           }
+
+         if (type_field (p->type) == ASN1_ETYPE_CHOICE)
+           {
+             while (p->down)
+               {
+                 if (counter < len)
+                   ris =
+                     _asn1_extract_tag_der (p->down, der + counter,
+                                            len - counter, &len2);
+                 else
+                   ris = ASN1_DER_ERROR;
+                 if (ris == ASN1_SUCCESS)
+                   {
+                     delete_unneeded_choice_fields(p->down);
+                     break;
+                   }
+                 else if (ris == ASN1_ERROR_TYPE_ANY)
+                   {
+                     result = ASN1_ERROR_TYPE_ANY;
+                     goto cleanup;
+                   }
+                 else
+                   {
+                     p2 = p->down;
+                     asn1_delete_structure (&p2);
+                   }
+               }
+
+             if (p->down == NULL)
+               {
+                 if (!(p->type & CONST_OPTION))
+                   {
+                     result = ASN1_DER_ERROR;
+                     goto cleanup;
+                   }
+               }
+             else if (type_field (p->type) != ASN1_ETYPE_CHOICE)
+               p = p->down;
+           }
+
+         if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
+           {
+             p2 = _asn1_find_up (p);
+             len2 = _asn1_strtol (p2->value, NULL, 10);
+             if (counter > len2)
+               ris = ASN1_TAG_ERROR;
+           }
+
+         if (ris == ASN1_SUCCESS)
+           ris =
+             _asn1_extract_tag_der (p, der + counter, len - counter, &len2);
+         if (ris != ASN1_SUCCESS)
+           {
+             if (p->type & CONST_OPTION)
+               {
+                 p->type |= CONST_NOT_USED;
+                 move = RIGHT;
+               }
+             else if (p->type & CONST_DEFAULT)
+               {
+                 _asn1_set_value (p, NULL, 0);
+                 move = RIGHT;
+               }
+             else
+               {
+                 if (errorDescription != NULL)
+                   _asn1_error_description_tag_error (p, errorDescription);
+
+                 result = ASN1_TAG_ERROR;
+                 goto cleanup;
+               }
+           }
+         else
+           counter += len2;
+       }
+
+      if (ris == ASN1_SUCCESS)
+       {
+         switch (type_field (p->type))
+           {
+           case ASN1_ETYPE_NULL:
+             if (der[counter])
+               {
+                 result = ASN1_DER_ERROR;
+                 goto cleanup;
+               }
+
+             if (p == nodeFound)
+               state = EXIT;
+
+             counter++;
+             move = RIGHT;
+             break;
+           case ASN1_ETYPE_BOOLEAN:
+             if (der[counter++] != 1)
+               {
+                 result = ASN1_DER_ERROR;
+                 goto cleanup;
+               }
+
+             if (state == FOUND)
+               {
+                 if (der[counter++] == 0)
+                   _asn1_set_value (p, "F", 1);
+                 else
+                   _asn1_set_value (p, "T", 1);
+
+                 if (p == nodeFound)
+                   state = EXIT;
+
+               }
+             else
+               counter++;
+
+             move = RIGHT;
+             break;
+           case ASN1_ETYPE_INTEGER:
+           case ASN1_ETYPE_ENUMERATED:
+             len2 =
+               asn1_get_length_der (der + counter, len - counter, &len3);
+             if (len2 < 0)
+               {
+                 result = ASN1_DER_ERROR;
+                 goto cleanup;
+               }
+
+             if (state == FOUND)
+               {
+                 if (len3 + len2 > len - counter)
+                   {
+                     result = ASN1_DER_ERROR;
+                     goto cleanup;
+                   }
+                 _asn1_set_value (p, der + counter, len3 + len2);
+
+                 if (p == nodeFound)
+                   state = EXIT;
+               }
+             counter += len3 + len2;
+             move = RIGHT;
+             break;
+           case ASN1_ETYPE_OBJECT_ID:
+             if (state == FOUND)
+               {
+                 result =
+                   _asn1_get_objectid_der (der + counter, len - counter,
+                                           &len2, temp, sizeof (temp));
+                 if (result != ASN1_SUCCESS)
+                   goto cleanup;
+
+                 tlen = strlen (temp);
+
+                 if (tlen > 0)
+                   _asn1_set_value (p, temp, tlen + 1);
+
+                 if (p == nodeFound)
+                   state = EXIT;
+               }
+             else
+               {
+                 len2 =
+                   asn1_get_length_der (der + counter, len - counter, &len3);
+                 if (len2 < 0)
+                   {
+                     result = ASN1_DER_ERROR;
+                     goto cleanup;
+                   }
+                 len2 += len3;
+               }
+
+             counter += len2;
+             move = RIGHT;
+             break;
+           case ASN1_ETYPE_GENERALIZED_TIME:
+           case ASN1_ETYPE_UTC_TIME:
+             if (state == FOUND)
+               {
+                 result =
+                   _asn1_get_time_der (der + counter, len - counter, &len2,
+                                       temp, sizeof (temp) - 1);
+                 if (result != ASN1_SUCCESS)
+                   goto cleanup;
+
+                 tlen = strlen (temp);
+                 if (tlen > 0)
+                   _asn1_set_value (p, temp, tlen + 1);
+
+                 if (p == nodeFound)
+                   state = EXIT;
+               }
+             else
+               {
+                 len2 =
+                   asn1_get_length_der (der + counter, len - counter, &len3);
+                 if (len2 < 0)
+                   {
+                     result = ASN1_DER_ERROR;
+                     goto cleanup;
+                   }
+                 len2 += len3;
+               }
+
+             counter += len2;
+             move = RIGHT;
+             break;
+           case ASN1_ETYPE_OCTET_STRING:
+             if (state == FOUND)
+               {
+                 result = _asn1_get_octet_string (p, der + counter, 
len-counter, &len3);
+                 if (p == nodeFound)
+                   state = EXIT;
+               }
+             else
+               result = _asn1_get_octet_string (NULL, der + counter, 
len-counter, &len3);
+
+             if (result != ASN1_SUCCESS)
+               goto cleanup;
+
+             counter += len3;
+             move = RIGHT;
+             break;
+           case ASN1_ETYPE_GENERALSTRING:
+           case ASN1_ETYPE_NUMERIC_STRING:
+           case ASN1_ETYPE_IA5_STRING:
+           case ASN1_ETYPE_TELETEX_STRING:
+           case ASN1_ETYPE_PRINTABLE_STRING:
+           case ASN1_ETYPE_UNIVERSAL_STRING:
+           case ASN1_ETYPE_BMP_STRING:
+           case ASN1_ETYPE_UTF8_STRING:
+           case ASN1_ETYPE_VISIBLE_STRING:
+           case ASN1_ETYPE_BIT_STRING:
+             len2 =
+               asn1_get_length_der (der + counter, len - counter, &len3);
+             if (len2 < 0)
+               {
+                 result = ASN1_DER_ERROR;
+                 goto cleanup;
+               }
+
+             if (state == FOUND)
+               {
+                 if (len3 + len2 > len - counter)
+                   {
+                     result = ASN1_DER_ERROR;
+                     goto cleanup;
+                   }
+                 _asn1_set_value (p, der + counter, len3 + len2);
+
+                 if (p == nodeFound)
+                   state = EXIT;
+               }
+             counter += len3 + len2;
+             move = RIGHT;
+             break;
+           case ASN1_ETYPE_SEQUENCE:
+           case ASN1_ETYPE_SET:
+             if (move == UP)
+               {
+                 len2 = _asn1_strtol (p->value, NULL, 10);
+                 _asn1_set_value (p, NULL, 0);
+                 if (len2 == -1)
+                   {           /* indefinite length method */
+                     if ((der[counter]) || der[counter + 1])
+                       {
+                         result = ASN1_DER_ERROR;
+                         goto cleanup;
+                       }
+                     counter += 2;
+                   }
+                 else
+                   {           /* definite length method */
+                     if (len2 != counter)
+                       {
+                         result = ASN1_DER_ERROR;
+                         goto cleanup;
+                       }
+                   }
+                 if (p == nodeFound)
+                   state = EXIT;
+                 move = RIGHT;
+               }
+             else
+               {               /* move==DOWN || move==RIGHT */
+                 if (state == OTHER_BRANCH)
+                   {
+                     len3 =
+                       asn1_get_length_der (der + counter, len - counter,
+                                            &len2);
+                     if (len3 < 0)
+                       {
+                         result = ASN1_DER_ERROR;
+                         goto cleanup;
+                       }
+                     counter += len2 + len3;
+                     move = RIGHT;
+                   }
+                 else
+                   {           /*  state==SAME_BRANCH or state==FOUND */
+                     len3 =
+                       asn1_get_length_der (der + counter, len - counter,
+                                            &len2);
+                     if (len3 < 0)
+                       {
+                         result = ASN1_DER_ERROR;
+                         goto cleanup;
+                       }
+                     counter += len2;
+                     if (len3 > 0)
+                       {
+                         _asn1_ltostr (counter + len3, temp, sizeof(temp));
+                         tlen = strlen (temp);
+
+                         if (tlen > 0)
+                           _asn1_set_value (p, temp, tlen + 1);
+                         move = DOWN;
+                       }
+                     else if (len3 == 0)
+                       {
+                         p2 = p->down;
+                         while (p2)
+                           {
+                             if (type_field (p2->type) != ASN1_ETYPE_TAG)
+                               {
+                                 p3 = p2->right;
+                                 asn1_delete_structure (&p2);
+                                 p2 = p3;
+                               }
+                             else
+                               p2 = p2->right;
+                           }
+                         move = RIGHT;
+                       }
+                     else
+                       {       /* indefinite length method */
+                         _asn1_set_value (p, "-1", 3);
+                         move = DOWN;
+                       }
+                   }
+               }
+             break;
+           case ASN1_ETYPE_SEQUENCE_OF:
+           case ASN1_ETYPE_SET_OF:
+             if (move == UP)
+               {
+                 len2 = _asn1_strtol (p->value, NULL, 10);
+                 if (len2 > counter)
+                   {
+                     _asn1_append_sequence_set (p);
+                     p = p->down;
+                     while (p->right)
+                       p = p->right;
+                     move = RIGHT;
+                     continue;
+                   }
+                 _asn1_set_value (p, NULL, 0);
+                 if (len2 != counter)
+                   {
+                     result = ASN1_DER_ERROR;
+                     goto cleanup;
+                   }
+
+                 if (p == nodeFound)
+                   state = EXIT;
+               }
+             else
+               {               /* move==DOWN || move==RIGHT */
+                 if (state == OTHER_BRANCH)
+                   {
+                     len3 =
+                       asn1_get_length_der (der + counter, len - counter,
+                                            &len2);
+                     if (len3 < 0)
+                       {
+                         result = ASN1_DER_ERROR;
+                         goto cleanup;
+                       }
+                     counter += len2 + len3;
+                     move = RIGHT;
+                   }
+                 else
+                   {           /* state==FOUND or state==SAME_BRANCH */
+                     len3 =
+                       asn1_get_length_der (der + counter, len - counter,
+                                            &len2);
+                     if (len3 < 0)
+                       {
+                         result = ASN1_DER_ERROR;
+                         goto cleanup;
+                       }
+                     counter += len2;
+                     if (len3)
+                       {
+                         _asn1_ltostr (counter + len3, temp, sizeof(temp));
+                         tlen = strlen (temp);
+
+                         if (tlen > 0)
+                           _asn1_set_value (p, temp, tlen + 1);
+                         p2 = p->down;
+                         while ((type_field (p2->type) == ASN1_ETYPE_TAG)
+                                || (type_field (p2->type) ==
+                                    ASN1_ETYPE_SIZE))
+                           p2 = p2->right;
+                         if (p2->right == NULL)
+                           _asn1_append_sequence_set (p);
+                         p = p2;
+                         state = FOUND;
+                       }
+                   }
+               }
+
+             break;
+           case ASN1_ETYPE_ANY:
+             if (asn1_get_tag_der
+                 (der + counter, len - counter, &class, &len2,
+                  &tag) != ASN1_SUCCESS)
+               {
+                 result = ASN1_DER_ERROR;
+                 goto cleanup;
+               }
+
+             if (counter + len2 > len)
+               {
+                 result = ASN1_DER_ERROR;
+                 goto cleanup;
+               }
+
+             len4 =
+               asn1_get_length_der (der + counter + len2,
+                                    len - counter - len2, &len3);
+             if (len4 < -1)
+               {
+                 result = ASN1_DER_ERROR;
+                 goto cleanup;
+               }
+
+             if (len4 != -1)
+               {
+                 len2 += len4;
+                 if (state == FOUND)
+                   {
+                     _asn1_set_value_lv (p, der + counter, len2 + len3);
+
+                     if (p == nodeFound)
+                       state = EXIT;
+                   }
+                 counter += len2 + len3;
+               }
+             else
+               {               /* indefinite length */
+                 /* Check indefinite lenth method in an EXPLICIT TAG */
+                 if ((p->type & CONST_TAG) && (der[counter - 1] == 0x80))
+                   indefinite = 1;
+                 else
+                   indefinite = 0;
+
+                 result =
+                   _asn1_get_indefinite_length_string (der + counter, 
len-counter, &len2);
+                 if (result != ASN1_SUCCESS)
+                   goto cleanup;
+
+                 if (state == FOUND)
+                   {
+                     _asn1_set_value_lv (p, der + counter, len2);
+
+                     if (p == nodeFound)
+                       state = EXIT;
+                   }
+
+                 counter += len2;
+
+                 /* Check if a couple of 0x00 are present due to an EXPLICIT 
TAG with
+                    an indefinite length method. */
+                 if (indefinite)
+                   {
+                     if (!der[counter] && !der[counter + 1])
+                       {
+                         counter += 2;
+                       }
+                     else
+                       {
+                         result = ASN1_DER_ERROR;
+                         goto cleanup;
+                       }
+                   }
+               }
+             move = RIGHT;
+             break;
+
+           default:
+             move = (move == UP) ? RIGHT : DOWN;
+             break;
+           }
+       }
+
+      if ((p == node && move != DOWN) || (state == EXIT))
+       break;
+
+      if (move == DOWN)
+       {
+         if (p->down)
+           {
+             p = p->down;
+
+             if (state != FOUND)
+               {
+                 nameLen -= strlen (p->name) + 1;
+                 if (nameLen > 0)
+                   {
+                     if (currentName[0])
+                       strcat (currentName, ".");
+                     strcat (currentName, p->name);
+                   }
+                 else
+                   {
+                     result = ASN1_MEM_ERROR;
+                     goto cleanup;
+                   }
+                 if (!(strcmp (currentName, elementName)))
+                   {
+                     state = FOUND;
+                     nodeFound = p;
+                   }
+                 else
+                   if (!memcmp
+                       (currentName, elementName, strlen (currentName)))
+                   state = SAME_BRANCH;
+                 else
+                   state = OTHER_BRANCH;
+               }
+           }
+         else
+           move = RIGHT;
+       }
+
+      if ((move == RIGHT) && !(p->type & CONST_SET))
+       {
+         if (p->right)
+           {
+             p = p->right;
+
+             if (state != FOUND)
+               {
+                 dot_p = char_p = currentName;
+                 while ((char_p = strchr (char_p, '.')))
+                   {
+                     dot_p = char_p++;
+                     dot_p++;
+                   }
+
+                 nameLen += strlen (currentName) - (dot_p - currentName);
+                 *dot_p = 0;
+
+                 nameLen -= strlen (p->name);
+                 if (nameLen > 0)
+                   strcat (currentName, p->name);
+                 else
+                   {
+                     result = ASN1_MEM_ERROR;
+                     goto cleanup;
+                   }
+
+                 if (!(strcmp (currentName, elementName)))
+                   {
+                     state = FOUND;
+                     nodeFound = p;
+                   }
+                 else
+                   if (!memcmp
+                       (currentName, elementName, strlen (currentName)))
+                   state = SAME_BRANCH;
+                 else
+                   state = OTHER_BRANCH;
+               }
+           }
+         else
+           move = UP;
+       }
+
+      if (move == UP)
+       {
+         p = _asn1_find_up (p);
+
+         if (state != FOUND)
+           {
+             dot_p = char_p = currentName;
+             while ((char_p = strchr (char_p, '.')))
+               {
+                 dot_p = char_p++;
+                 dot_p++;
+               }
+
+             nameLen += strlen (currentName) - (dot_p - currentName);
+             *dot_p = 0;
+
+             if (!(strcmp (currentName, elementName)))
+               {
+                 state = FOUND;
+                 nodeFound = p;
+               }
+             else
+               if (!memcmp (currentName, elementName, strlen (currentName)))
+               state = SAME_BRANCH;
+             else
+               state = OTHER_BRANCH;
+           }
+       }
+    }
+
+  _asn1_delete_not_used (*structure);
+
+  if (counter > len)
+    {
+      result = ASN1_DER_ERROR;
+      goto cleanup;
+    }
+
+  return ASN1_SUCCESS;
+
+cleanup:
+  asn1_delete_structure (structure);
+  return result;
 }
 
 /**
diff --git a/lib/element.c b/lib/element.c
index 8062bce..d748f46 100644
--- a/lib/element.c
+++ b/lib/element.c
@@ -152,7 +152,7 @@ _asn1_append_sequence_set (asn1_node node)
       n = strtol (p->name + 1, NULL, 0);
       n++;
       temp[0] = '?';
-      _asn1_ltostr (n, temp + 1);
+      _asn1_ltostr (n, temp + 1, sizeof(temp)-1);
     }
   _asn1_set_name (p2, temp);
   /*  p2->type |= CONST_OPTION; */
@@ -621,7 +621,7 @@ asn1_write_value (asn1_node node_root, const char *name,
        if (ptr_size < data_size) { \
                return ASN1_MEM_ERROR; \
        } else { \
-               if (ptr) \
+               if (ptr && data_size > 0) \
                  memcpy (ptr, data, data_size); \
        }
 
@@ -631,8 +631,9 @@ asn1_write_value (asn1_node node_root, const char *name,
                return ASN1_MEM_ERROR; \
        } else { \
                /* this strcpy is checked */ \
-               if (ptr) \
+               if (ptr) { \
                  _asn1_strcpy (ptr, data); \
+               } \
        }
 
 #define PUT_AS_STR_VALUE( ptr, ptr_size, data, data_size) \
@@ -642,7 +643,8 @@ asn1_write_value (asn1_node node_root, const char *name,
        } else { \
                /* this strcpy is checked */ \
                if (ptr) { \
-                 memcpy (ptr, data, data_size); \
+                 if (data_size > 0) \
+                   memcpy (ptr, data, data_size); \
                  ptr[data_size] = 0; \
                } \
        }
@@ -887,7 +889,8 @@ asn1_read_value_type (asn1_node root, const char *name, 
void *ivalue,
     case ASN1_ETYPE_OBJECT_ID:
       if (node->type & CONST_ASSIGN)
        {
-         value[0] = 0;
+         if (value)
+               value[0] = 0;
          p = node->down;
          while (p)
            {
diff --git a/lib/libtasn1.h b/lib/libtasn1.h
index 92ae54e..92ef0ef 100644
--- a/lib/libtasn1.h
+++ b/lib/libtasn1.h
@@ -46,6 +46,17 @@ extern "C"
 
 #define ASN1_VERSION "3.5"
 
+#if defined(__GNUC__) && !defined(ASN1_INTERNAL_BUILD)
+# define _ASN1_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + 
__GNUC_PATCHLEVEL__)
+# if _ASN1_GCC_VERSION >= 30100
+#  define _ASN1_GCC_ATTR_DEPRECATED __attribute__ ((__deprecated__))
+# endif
+#endif
+
+#ifndef _ASN1_GCC_ATTR_DEPRECATED
+#define _ASN1_GCC_ATTR_DEPRECATED
+#endif
+
   /*****************************************/
   /* Errors returned by libtasn1 functions */
   /*****************************************/
@@ -251,11 +262,12 @@ extern "C"
     asn1_der_decoding (asn1_node * element, const void *ider,
                       int len, char *errorDescription);
 
+  /* Do not use. Use asn1_der_decoding() instead. */
   extern ASN1_API int
     asn1_der_decoding_element (asn1_node * structure,
                               const char *elementName,
                               const void *ider, int len,
-                              char *errorDescription);
+                              char *errorDescription) 
_ASN1_GCC_ATTR_DEPRECATED;
 
   extern ASN1_API int
     asn1_der_decoding_startEnd (asn1_node element,
diff --git a/lib/parser_aux.c b/lib/parser_aux.c
index 31d1770..2ca4e61 100644
--- a/lib/parser_aux.c
+++ b/lib/parser_aux.c
@@ -531,41 +531,6 @@ _asn1_delete_list_and_nodes (void)
     }
 }
 
-
-char *
-_asn1_ltostr (long v, char *str)
-{
-  long d, r;
-  char temp[20];
-  int count, k, start;
-
-  if (v < 0)
-    {
-      str[0] = '-';
-      start = 1;
-      v = -v;
-    }
-  else
-    start = 0;
-
-  count = 0;
-  do
-    {
-      d = v / 10;
-      r = v - d * 10;
-      temp[start + count] = '0' + (char) r;
-      count++;
-      v = d;
-    }
-  while (v);
-
-  for (k = 0; k < count; k++)
-    str[k + start] = temp[start + count - k - 1];
-  str[count + start] = 0;
-  return str;
-}
-
-
 /******************************************************************/
 /* Function : _asn1_change_integer_value                          */
 /* Description: converts into DER coding the value assign to an   */
diff --git a/lib/parser_aux.h b/lib/parser_aux.h
index f1e9a07..8ef105b 100644
--- a/lib/parser_aux.h
+++ b/lib/parser_aux.h
@@ -25,6 +25,14 @@
 /***************************************/
 /*  Functions used by ASN.1 parser     */
 /***************************************/
+
+inline static char *
+_asn1_ltostr (long v, char *str, size_t str_size)
+{
+  snprintf(str, str_size, "%ld", v);
+  return str;
+}
+
 asn1_node _asn1_add_static_node (unsigned int type);
 
 asn1_node
@@ -52,8 +60,6 @@ void _asn1_delete_list (void);
 
 void _asn1_delete_list_and_nodes (void);
 
-char *_asn1_ltostr (long v, char *str);
-
 asn1_node _asn1_find_up (asn1_node node);
 
 int _asn1_change_integer_value (asn1_node node);
diff --git a/tests/Test_simple.c b/tests/Test_simple.c
index a8ddf8d..a846958 100644
--- a/tests/Test_simple.c
+++ b/tests/Test_simple.c
@@ -128,7 +128,7 @@ main (int argc, char *argv[])
       if (result != ASN1_SUCCESS || ret_len != tv[i].derlen
          || bit_len != tv[i].bitlen)
        {
-         fprintf (stderr, "asn1_get_bit_der iter %lu\n", (unsigned long) i);
+         fprintf (stderr, "asn1_get_bit_der iter %lu, err: %d\n", (unsigned 
long) i, result);
          return 1;
        }
     }
diff --git a/tests/Test_tree.c b/tests/Test_tree.c
index fce392e..0b6a7df 100644
--- a/tests/Test_tree.c
+++ b/tests/Test_tree.c
@@ -33,6 +33,8 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+
+#define ASN1_INTERNAL_BUILD
 #include "libtasn1.h"
 
 #include "Test_tree_asn1_tab.c"


hooks/post-receive
-- 
GNU libtasn1



reply via email to

[Prev in Thread] Current Thread [Next in Thread]