Description: fix denial of service via NULL value
Origin: backport, http://git.savannah.gnu.org/cgit/libtasn1.git/commit/lib/element.c?id=a8b3e14f84174e01755bfd1be5448fffce7c9ffa
Origin: backport, http://git.savannah.gnu.org/cgit/libtasn1.git/commit/lib/element.c?id=3d6a02f19ff15a38dae9686033e37499b3968256
Origin: backport, http://git.savannah.gnu.org/cgit/libtasn1.git/commit/lib/element.c?id=53958290ab731c8486531a3bdef54a933533579d

Index: libtasn1-6-3.4/lib/element.c
===================================================================
--- libtasn1-6-3.4.orig/lib/element.c	2013-11-25 14:14:32.000000000 -0500
+++ libtasn1-6-3.4/lib/element.c	2014-07-18 11:49:02.037904674 -0400
@@ -112,8 +112,11 @@
     /* VALUE_OUT is too short to contain the value conversion */
     return ASN1_MEM_ERROR;
 
-  for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++)
-    value_out[k2 - k] = val[k2];
+  if (value_out != NULL)
+    {
+      for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++)
+        value_out[k2 - k] = val[k2];
+    }
 
 #if 0
   printf ("_asn1_convert_integer: valueIn=%s, lenOut=%d", value, *len);
@@ -615,7 +618,8 @@
 	if (ptr_size < data_size) { \
 		return ASN1_MEM_ERROR; \
 	} else { \
-		memcpy( ptr, data, data_size); \
+		if (ptr && data_size > 0) \
+	 	  memcpy( ptr, data, data_size); \
 	}
 
 #define PUT_STR_VALUE( ptr, ptr_size, data) \
@@ -624,7 +628,9 @@
 		return ASN1_MEM_ERROR; \
 	} else { \
 		/* this strcpy is checked */ \
-		_asn1_strcpy(ptr, data); \
+		if (ptr) { \
+		  _asn1_strcpy(ptr, data); \
+		} \
 	}
 
 #define PUT_AS_STR_VALUE( ptr, ptr_size, data, data_size) \
@@ -633,36 +639,42 @@
 		return ASN1_MEM_ERROR; \
 	} else { \
 		/* this strcpy is checked */ \
-		memcpy(ptr, data, data_size); \
-		ptr[data_size] = 0; \
+		if (ptr) { \
+		  if (data_size > 0) \
+		    memcpy (ptr, data, data_size); \
+		  ptr[data_size] = 0; \
+		} \
 	}
 
 #define ADD_STR_VALUE( ptr, ptr_size, data) \
-	*len = (int) _asn1_strlen(data) + 1; \
-	if (ptr_size < (int) _asn1_strlen(ptr)+(*len)) { \
-		return ASN1_MEM_ERROR; \
-	} else { \
-		/* this strcat is checked */ \
-		_asn1_strcat(ptr, data); \
-	}
+        *len += _asn1_strlen(data); \
+        if (ptr_size < (int) *len) { \
+                (*len)++; \
+                return ASN1_MEM_ERROR; \
+        } else { \
+                /* this strcat is checked */ \
+                if (ptr) _asn1_strcat (ptr, data); \
+        }
 
 /**
  * asn1_read_value:
  * @root: pointer to a structure.
  * @name: the name of the element inside a structure that you want to read.
  * @ivalue: vector that will contain the element's content, must be a
- *   pointer to memory cells already allocated.
+ *   pointer to memory cells already allocated (may be %NULL).
  * @len: number of bytes of *value: value[0]..value[len-1]. Initialy
  *   holds the sizeof value.
  *
- * Returns the value of one element inside a structure.
- *
- * If an element is OPTIONAL and the function "read_value" returns
+ * Returns the value of one element inside a structure. 
+ * If an element is OPTIONAL and this returns
  * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
  * in the der encoding that created the structure.  The first element
  * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and
  * so on.
  *
+ * Note that there can be valid values with length zero. In these case
+ * this function will succeed and @len will be zero.
+ *
  * INTEGER: VALUE will contain a two's complement form integer.
  *
  *            integer=-1  -> value[0]=0xFF , len=1.
@@ -718,19 +730,22 @@
  * @root: pointer to a structure.
  * @name: the name of the element inside a structure that you want to read.
  * @ivalue: vector that will contain the element's content, must be a
- *   pointer to memory cells already allocated.
+ *   pointer to memory cells already allocated (may be %NULL).
  * @len: number of bytes of *value: value[0]..value[len-1]. Initialy
  *   holds the sizeof value.
  * @etype: The type of the value read (ASN1_ETYPE)
  *
- * Returns the value of one element inside a structure.
- *
- * If an element is OPTIONAL and the function "read_value" returns
+ * Returns the value of one element inside a structure. 
+ * If an element is OPTIONAL and this returns
  * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
  * in the der encoding that created the structure.  The first element
  * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and
  * so on.
  *
+ * Note that there can be valid values with length zero. In these case
+ * this function will succeed and @len will be zero.
+ *
+ *
  * INTEGER: VALUE will contain a two's complement form integer.
  *
  *            integer=-1  -> value[0]=0xFF , len=1.
@@ -874,7 +889,9 @@
     case ASN1_ETYPE_OBJECT_ID:
       if (node->type & CONST_ASSIGN)
 	{
-	  value[0] = 0;
+	  *len = 0;
+	  if (value)
+	  	value[0] = 0;
 	  p = node->down;
 	  while (p)
 	    {
@@ -888,7 +905,7 @@
 		}
 	      p = p->right;
 	    }
-	  *len = _asn1_strlen (value) + 1;
+	  (*len)++;
 	}
       else if ((node->type & CONST_DEFAULT) && (node->value == NULL))
 	{
