From e2bbbf8f1e3715e04df246f1f107c6e85cf567fe Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Sun, 8 Oct 2017 18:52:37 -0700 Subject: [PATCH] remove the use of alloca in skeletons --- asn1c/unber.c | 1 + skeletons/INTEGER.c | 18 ++++----------- skeletons/Makefile.am | 4 ++-- skeletons/NativeEnumerated.c | 9 +++----- skeletons/REAL.c | 31 ++++++++++---------------- skeletons/asn_internal.h | 13 +++++++++++ skeletons/asn_system.h | 30 ++----------------------- skeletons/constr_SET.c | 32 ++++++++++++++++++--------- skeletons/der_encoder.c | 43 ++++++++++++++++-------------------- skeletons/file-dependencies | 2 +- 10 files changed, 78 insertions(+), 105 deletions(-) diff --git a/asn1c/unber.c b/asn1c/unber.c index 4382180e..1a33b4db 100644 --- a/asn1c/unber.c +++ b/asn1c/unber.c @@ -41,6 +41,7 @@ #include #include #include +#include #undef COPYRIGHT #define COPYRIGHT "Copyright (c) 2004, 2005 Lev Walkin \n" diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c index f5dd44cd..e9d6e87b 100644 --- a/skeletons/INTEGER.c +++ b/skeletons/INTEGER.c @@ -122,7 +122,7 @@ static ssize_t 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 @@ INTEGER__dump(const asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_cons /* 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 @@ INTEGER__dump(const asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_cons 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 65455dcb..43fde666 100644 --- a/skeletons/Makefile.am +++ b/skeletons/Makefile.am @@ -65,9 +65,9 @@ libasn1cskeletons_la_SOURCES = \ 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 3ddd8126..d95dea20 100644 --- a/skeletons/NativeEnumerated.c +++ b/skeletons/NativeEnumerated.c @@ -73,12 +73,9 @@ NativeEnumerated_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, int ilevel, 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 6f27d4fc..023afa3c 100644 --- a/skeletons/REAL.c +++ b/skeletons/REAL.c @@ -10,9 +10,6 @@ #if defined(__alpha) #include /* For INFINITY */ #endif -#if defined(sun) || defined(__sun) -#include -#endif #include /* for strtod(3) */ #include #include @@ -519,7 +516,7 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) { * 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 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) { * 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 53f12a6b..09093b96 100644 --- a/skeletons/asn_internal.h +++ b/skeletons/asn_internal.h @@ -68,6 +68,19 @@ static void CC_PRINTFLIKE(1, 2) ASN_DEBUG(const char *fmt, ...) { (void)fmt; } #endif /* EMIT_ASN_DEBUG */ #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. */ diff --git a/skeletons/asn_system.h b/skeletons/asn_system.h index 1bc53b00..6dbd1480 100644 --- a/skeletons/asn_system.h +++ b/skeletons/asn_system.h @@ -1,5 +1,5 @@ -/*- - * Copyright (c) 2003, 2004, 2007 Lev Walkin . +/* + * Copyright (c) 2003-2017 Lev Walkin . * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ @@ -25,10 +25,6 @@ #include /* For va_start */ #include /* for offsetof and ptrdiff_t */ -#ifdef HAVE_ALLOCA_H -#include /* For alloca(3) */ -#endif - #ifdef _WIN32 #include @@ -76,30 +72,8 @@ typedef unsigned int uint32_t; #else /* !defined(__vxworks) */ #include /* C99 specifies this file */ -/* - * 1. Earlier FreeBSD version didn't have , - * but was present. - * 2. Sun Solaris requires for alloca(3), - * but does not have . - */ -#if (!defined(__FreeBSD__) || !defined(_SYS_INTTYPES_H_)) -#if defined(sun) -#include /* For alloca(3) */ -#include /* for finite(3) */ -#elif defined(__hpux) -#ifdef __GNUC__ -#include /* For alloca(3) */ -#else /* !__GNUC__ */ -#define inline -#endif /* __GNUC__ */ -#else -#include /* SUSv2+ and C99 specify this file, for uintXX_t */ -#endif /* defined(sun) */ -#endif - #include /* 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 d956f950..422e6639 100644 --- a/skeletons/constr_SET.c +++ b/skeletons/constr_SET.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * Copyright (c) 2003-2017 Lev Walkin . * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ @@ -449,9 +449,9 @@ SET_encode_der(asn_TYPE_descriptor_t *td, * 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 @@ SET_encode_der(asn_TYPE_descriptor_t *td, 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 @@ SET_encode_der(asn_TYPE_descriptor_t *td, /* 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 @@ SET_encode_der(asn_TYPE_descriptor_t *td, /* * 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 @@ SET_encode_der(asn_TYPE_descriptor_t *td, /* * 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 @@ SET_encode_der(asn_TYPE_descriptor_t *td, * 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 @@ SET_encode_der(asn_TYPE_descriptor_t *td, /* * 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 8673a31c..a26d57ee 100644 --- a/skeletons/der_encoder.c +++ b/skeletons/der_encoder.c @@ -74,19 +74,20 @@ der_encode_to_buffer(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr, * 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 @@ der_write_tags(asn_TYPE_descriptor_t *sd, :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 @@ der_write_tags(asn_TYPE_descriptor_t *sd, * 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 @@ der_write_tags(asn_TYPE_descriptor_t *sd, 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 3661d0f5..012ea6c9 100644 --- a/skeletons/file-dependencies +++ b/skeletons/file-dependencies @@ -45,7 +45,7 @@ asn_application.h asn_application.c # Applications should include this file 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