remove the use of alloca in skeletons
diff --git a/asn1c/unber.c b/asn1c/unber.c
index 4382180..1a33b4d 100644
--- a/asn1c/unber.c
+++ b/asn1c/unber.c
@@ -41,6 +41,7 @@
 #include <RELATIVE-OID.c>
 #include <asn_codecs_prim.c>
 #include <asn1p_integer.c>
+#include <asn_internal.c>
 
 #undef COPYRIGHT
 #define COPYRIGHT "Copyright (c) 2004, 2005 Lev Walkin <vlm@lionet.info>\n"
diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c
index f5dd44c..e9d6e87 100644
--- a/skeletons/INTEGER.c
+++ b/skeletons/INTEGER.c
@@ -122,7 +122,7 @@
 INTEGER__dump(const asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) {
     const asn_INTEGER_specifics_t *specs =
         (const asn_INTEGER_specifics_t *)td->specifics;
-    char scratch[32];	/* Enough for 64-bit integer */
+	char scratch[32];
 	uint8_t *buf = st->buf;
 	uint8_t *buf_end = st->buf + st->size;
 	intmax_t value;
@@ -138,19 +138,14 @@
 	/* Simple case: the integer size is small */
 	if(ret == 0) {
 		const asn_INTEGER_enum_map_t *el;
-		size_t scrsize;
-		char *scr;
-
 		el = (value >= 0 || !specs || !specs->field_unsigned)
 			? INTEGER_map_value2enum(specs, value) : 0;
 		if(el) {
-			scrsize = el->enum_len + 32;
-			scr = (char *)alloca(scrsize);
 			if(plainOrXER == 0)
-				ret = snprintf(scr, scrsize,
+				return asn__format_to_callback(cb, app_key,
 					"%" PRIdMAX " (%s)", value, el->enum_name);
 			else
-				ret = snprintf(scr, scrsize,
+				return asn__format_to_callback(cb, app_key,
 					"<%s/>", el->enum_name);
 		} else if(plainOrXER && specs && specs->strict_enumeration) {
 			ASN_DEBUG("ASN.1 forbids dealing with "
@@ -158,15 +153,10 @@
 			errno = EPERM;
 			return -1;
 		} else {
-			scrsize = sizeof(scratch);
-			scr = scratch;
-            ret = snprintf(
-                scr, scrsize,
+            return asn__format_to_callback(cb, app_key,
                 (specs && specs->field_unsigned) ? "%" PRIuMAX : "%" PRIdMAX,
                 value);
         }
-		assert(ret > 0 && (size_t)ret < scrsize);
-		return (cb(scr, ret, app_key) < 0) ? -1 : ret;
 	} else if(plainOrXER && specs && specs->strict_enumeration) {
 		/*
 		 * Here and earlier, we cannot encode the ENUMERATED values
diff --git a/skeletons/Makefile.am b/skeletons/Makefile.am
index 65455dc..43fde66 100644
--- a/skeletons/Makefile.am
+++ b/skeletons/Makefile.am
@@ -65,9 +65,9 @@
     asn_SEQUENCE_OF.c asn_SEQUENCE_OF.h         \
     asn_SET_OF.c asn_SET_OF.h                   \
     asn_application.c asn_application.h         \
-    asn_codecs.h                                \
+    asn_system.h asn_codecs.h                   \
     asn_codecs_prim.c asn_codecs_prim.h         \
-    asn_internal.h asn_system.h                 \
+    asn_internal.h asn_internal.c               \
     asn_bit_data.c asn_bit_data.h               \
     asn_random_fill.c asn_random_fill.h         \
     ber_decoder.c ber_decoder.h                 \
diff --git a/skeletons/NativeEnumerated.c b/skeletons/NativeEnumerated.c
index 3ddd812..d95dea2 100644
--- a/skeletons/NativeEnumerated.c
+++ b/skeletons/NativeEnumerated.c
@@ -73,12 +73,9 @@
 
     el = INTEGER_map_value2enum(specs, *native);
     if(el) {
-        size_t srcsize = el->enum_len + 5;
-        char *src = (char *)alloca(srcsize);
-
-        er.encoded = snprintf(src, srcsize, "<%s/>", el->enum_name);
-        assert(er.encoded > 0 && (size_t)er.encoded < srcsize);
-        if(cb(src, er.encoded, app_key) < 0) ASN__ENCODE_FAILED;
+        er.encoded =
+            asn__format_to_callback(cb, app_key, "<%s/>", el->enum_name);
+        if(er.encoded < 0) ASN__ENCODE_FAILED;
         ASN__ENCODED_OK(er);
     } else {
         ASN_DEBUG(
diff --git a/skeletons/REAL.c b/skeletons/REAL.c
index 6f27d4f..023afa3 100644
--- a/skeletons/REAL.c
+++ b/skeletons/REAL.c
@@ -10,9 +10,6 @@
 #if	defined(__alpha)
 #include <sys/resource.h>	/* For INFINITY */
 #endif
-#if defined(sun) || defined(__sun)
-#include <ieeefp.h>
-#endif
 #include <stdlib.h>	/* for strtod(3) */
 #include <math.h>
 #include <float.h>
@@ -519,7 +516,7 @@
 		 * NR3: [ ]*[+-]?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)[Ee][+-]?[0-9]+
 		 */
 		double d;
-		char *buf;
+		char *source = 0;
 		char *endptr;
 		int used_malloc = 0;
 
@@ -536,35 +533,31 @@
 		 * So her we fix both by reallocating, copying and fixing.
 		 */
 		if(st->buf[st->size] != '\0' || memchr(st->buf, ',', st->size)) {
-			uint8_t *p, *end;
+			const uint8_t *p, *end;
 			char *b;
-			if(st->size > 100) {
-				/* Avoid malicious stack overflow in alloca() */
-				buf = (char *)MALLOC(st->size);
-				if(!buf) return -1;
-				used_malloc = 1;
-			} else {
-				buf = alloca(st->size);
-			}
-			b = buf;
+
+            b = source = (char *)MALLOC(st->size + 1);
+            if(!source) return -1;
+            used_malloc = 1;
+
 			/* Copy without the first byte and with 0-termination */
 			for(p = st->buf + 1, end = st->buf + st->size;
 					p < end; b++, p++)
 				*b = (*p == ',') ? '.' : *p;
 			*b = '\0';
 		} else {
-			buf = (char *)&st->buf[1];
+			source = (char *)&st->buf[1];
 		}
 
-		endptr = buf;
-		d = strtod(buf, &endptr);
+		endptr = source;
+		d = strtod(source, &endptr);
 		if(*endptr != '\0') {
 			/* Format is not consistent with ISO 6093 */
-			if(used_malloc) FREEMEM(buf);
+			if(used_malloc) FREEMEM(source);
 			errno = EINVAL;
 			return -1;
 		}
-		if(used_malloc) FREEMEM(buf);
+		if(used_malloc) FREEMEM(source);
 		if(asn_isfinite(d)) {
 			*dbl_value = d;
 			return 0;
diff --git a/skeletons/asn_internal.h b/skeletons/asn_internal.h
index 53f12a6..09093b9 100644
--- a/skeletons/asn_internal.h
+++ b/skeletons/asn_internal.h
@@ -69,6 +69,19 @@
 #endif	/* ASN_DEBUG */
 
 /*
+ * Print to a callback.
+ * The callback is expected to return negative values on error.
+ * 0 and positive values are treated as success.
+ * RETURN VALUES:
+ *  -1: Failed to format or invoke the callback.
+ *  >0: Size of the data that got delivered to the callback.
+ */
+ssize_t CC_PRINTFLIKE(3, 4)
+asn__format_to_callback(
+    int (*callback)(const void *, size_t, void *key), void *key,
+    const char *fmt, ...);
+
+/*
  * Invoke the application-supplied callback and fail, if something is wrong.
  */
 #define ASN__E_cbc(buf, size) (cb((buf), (size), app_key) < 0)
diff --git a/skeletons/asn_system.h b/skeletons/asn_system.h
index 1bc53b0..6dbd148 100644
--- a/skeletons/asn_system.h
+++ b/skeletons/asn_system.h
@@ -1,5 +1,5 @@
-/*-
- * Copyright (c) 2003, 2004, 2007 Lev Walkin <vlm@lionet.info>.
+/*
+ * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>.
  * All rights reserved.
  * Redistribution and modifications are permitted subject to BSD license.
  */
@@ -25,10 +25,6 @@
 #include <stdarg.h>	/* For va_start */
 #include <stddef.h>	/* for offsetof and ptrdiff_t */
 
-#ifdef	HAVE_ALLOCA_H
-#include <alloca.h>	/* For alloca(3) */
-#endif
-
 #ifdef	_WIN32
 
 #include <malloc.h>
@@ -76,30 +72,8 @@
 #else	/* !defined(__vxworks) */
 
 #include <inttypes.h>	/* C99 specifies this file */
-/*
- * 1. Earlier FreeBSD version didn't have <stdint.h>,
- * but <inttypes.h> was present.
- * 2. Sun Solaris requires <alloca.h> for alloca(3),
- * but does not have <stdint.h>.
- */
-#if	(!defined(__FreeBSD__) || !defined(_SYS_INTTYPES_H_))
-#if	defined(sun)
-#include <alloca.h>	/* For alloca(3) */
-#include <ieeefp.h>	/* for finite(3) */
-#elif	defined(__hpux)
-#ifdef	__GNUC__
-#include <alloca.h>	/* For alloca(3) */
-#else	/* !__GNUC__ */
-#define inline
-#endif	/* __GNUC__ */
-#else
-#include <stdint.h>	/* SUSv2+ and C99 specify this file, for uintXX_t */
-#endif	/* defined(sun) */
-#endif
-
 #include <netinet/in.h> /* for ntohl() */
 #define	sys_ntohl(foo)	ntohl(foo)
-
 #endif	/* defined(__vxworks) */
 
 #endif	/* _WIN32 */
diff --git a/skeletons/constr_SET.c b/skeletons/constr_SET.c
index d956f95..422e663 100644
--- a/skeletons/constr_SET.c
+++ b/skeletons/constr_SET.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>.
  * All rights reserved.
  * Redistribution and modifications are permitted subject to BSD license.
  */
@@ -449,9 +449,9 @@
 	 * Use existing, or build our own tags map.
 	 */
 	if(t2m_build_own) {
-		t2m_build = (asn_TYPE_tag2member_t *)alloca(
-				td->elements_count * sizeof(t2m_build[0]));
-		if(!t2m_build) ASN__ENCODE_FAILED; /* There are such platforms */
+        t2m_build = (asn_TYPE_tag2member_t *)CALLOC(td->elements_count,
+                                                    sizeof(t2m_build[0]));
+        if(!t2m_build) ASN__ENCODE_FAILED;
 		t2m_count = 0;
 	} else {
 		t2m_build = NULL;
@@ -476,10 +476,12 @@
 		if(elm->flags & ATF_POINTER) {
 			memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
 			if(!*memb_ptr2) {
-				if(!elm->optional)
+				if(!elm->optional) {
 					/* Mandatory elements missing */
+					FREEMEM(t2m_build);
 					ASN__ENCODE_FAILED;
-				if(t2m_build_own) {
+				}
+				if(t2m_build) {
 					t2m_build[t2m_count].el_no = edx;
 					t2m_build[t2m_count].el_tag = 0;
 					t2m_count++;
@@ -493,7 +495,7 @@
 
 		/* Eliminate default values */
 		if(elm->default_value && elm->default_value(0, memb_ptr2) == 1) {
-			if(t2m_build_own) {
+			if(t2m_build) {
 				t2m_build[t2m_count].el_no = edx;
 				t2m_build[t2m_count].el_tag = 0;
 				t2m_count++;
@@ -511,7 +513,7 @@
 		/*
 		 * Remember the outmost tag of this member.
 		 */
-		if(t2m_build_own) {
+		if(t2m_build) {
 			t2m_build[t2m_count].el_no = edx;
 			t2m_build[t2m_count].el_tag = asn_TYPE_outmost_tag(
 				elm->type, *memb_ptr2, elm->tag_mode, elm->tag);
@@ -526,7 +528,7 @@
 	/*
 	 * Finalize order of the components.
 	 */
-	if(t2m_build_own) {
+	if(t2m_build) {
 		/*
 		 * Sort the underlying members according to their
 		 * canonical tags order. DER encoding mandates it.
@@ -546,10 +548,16 @@
 	 * Encode the TLV for the sequence itself.
 	 */
 	ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key);
-	if(ret == -1) ASN__ENCODE_FAILED;
+	if(ret == -1) {
+		FREEMEM(t2m_build);
+		ASN__ENCODE_FAILED;
+	}
 	er.encoded = computed_size + ret;
 
-	if(!cb) ASN__ENCODED_OK(er);
+	if(!cb) {
+		FREEMEM(t2m_build);
+		ASN__ENCODED_OK(er);
+    }
 
 	/*
 	 * Encode all members.
@@ -587,9 +595,11 @@
 		/*
 		 * Encoded size is not equal to the computed size.
 		 */
+		FREEMEM(t2m_build);
 		ASN__ENCODE_FAILED;
 	}
 
+    FREEMEM(t2m_build);
 	ASN__ENCODED_OK(er);
 }
 
diff --git a/skeletons/der_encoder.c b/skeletons/der_encoder.c
index 8673a31..a26d57e 100644
--- a/skeletons/der_encoder.c
+++ b/skeletons/der_encoder.c
@@ -74,19 +74,20 @@
  * Write out leading TL[v] sequence according to the type definition.
  */
 ssize_t
-der_write_tags(asn_TYPE_descriptor_t *sd,
-		size_t struct_length,
-		int tag_mode, int last_tag_form,
-		ber_tlv_tag_t tag,	/* EXPLICIT or IMPLICIT tag */
-		asn_app_consume_bytes_f *cb,
-		void *app_key) {
-	const ber_tlv_tag_t *tags;	/* Copy of tags stream */
-	int tags_count;			/* Number of tags */
-	size_t overall_length;
-	ssize_t *lens;
-	int i;
+der_write_tags(asn_TYPE_descriptor_t *sd, size_t struct_length, int tag_mode,
+               int last_tag_form,
+               ber_tlv_tag_t tag, /* EXPLICIT or IMPLICIT tag */
+               asn_app_consume_bytes_f *cb, void *app_key) {
+#define ASN1_DER_MAX_TAGS_COUNT 4
+    ber_tlv_tag_t
+        tags_buf_scratch[ASN1_DER_MAX_TAGS_COUNT * sizeof(ber_tlv_tag_t)];
+    ssize_t lens[ASN1_DER_MAX_TAGS_COUNT * sizeof(ssize_t)];
+    const ber_tlv_tag_t *tags; /* Copy of tags stream */
+    int tags_count;            /* Number of tags */
+    size_t overall_length;
+    int i;
 
-	ASN_DEBUG("Writing tags (%s, tm=%d, tc=%d, tag=%s, mtc=%d)",
+    ASN_DEBUG("Writing tags (%s, tm=%d, tc=%d, tag=%s, mtc=%d)",
 		sd->name, tag_mode, sd->tags_count,
 		ber_tlv_tag_string(tag),
 		tag_mode
@@ -95,6 +96,11 @@
 			:sd->tags_count
 	);
 
+    if(sd->tags_count + 1 > ASN1_DER_MAX_TAGS_COUNT) {
+        ASN_DEBUG("System limit %d on tags count", ASN1_DER_MAX_TAGS_COUNT);
+        return -1;
+    }
+
 	if(tag_mode) {
 		/*
 		 * Instead of doing shaman dance like we do in ber_check_tags(),
@@ -102,12 +108,7 @@
 		 * and initialize it appropriately.
 		 */
 		int stag_offset;
-		ber_tlv_tag_t *tags_buf;
-		tags_buf = (ber_tlv_tag_t *)alloca((sd->tags_count + 1) * sizeof(ber_tlv_tag_t));
-		if(!tags_buf) {	/* Can fail on !x86 */
-			errno = ENOMEM;
-			return -1;
-		}
+		ber_tlv_tag_t *tags_buf = tags_buf_scratch;
 		tags_count = sd->tags_count
 			+ 1	/* EXPLICIT or IMPLICIT tag is given */
 			- ((tag_mode == -1) && sd->tags_count);
@@ -126,12 +127,6 @@
 	if(tags_count == 0)
 		return 0;
 
-	lens = (ssize_t *)alloca(tags_count * sizeof(lens[0]));
-	if(!lens) {
-		errno = ENOMEM;
-		return -1;
-	}
-
 	/*
 	 * Array of tags is initialized.
 	 * Now, compute the size of the TLV pairs, from right to left.
diff --git a/skeletons/file-dependencies b/skeletons/file-dependencies
index 3661d0f..012ea6c 100644
--- a/skeletons/file-dependencies
+++ b/skeletons/file-dependencies
@@ -45,7 +45,7 @@
 asn_ioc.h			# Information Object Classes, runtime support
 asn_system.h			# Platform-dependent types
 asn_codecs.h			# Return types of encoders and decoders
-asn_internal.h			# Internal stuff
+asn_internal.h asn_internal.c			# Internal stuff
 asn_random_fill.h asn_random_fill.c		# Initialize with a random value
 asn_bit_data.h asn_bit_data.c         # Bit streaming support
 OCTET_STRING.h OCTET_STRING.c	# This one is used too widely