aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--asn1c-talloc.patch16
-rw-r--r--configure.ac2
-rw-r--r--include/asn1c/ANY.h3
-rw-r--r--include/asn1c/BOOLEAN.h2
-rw-r--r--include/asn1c/ENUMERATED.h2
-rw-r--r--include/asn1c/INTEGER.h27
-rw-r--r--include/asn1c/NULL.h2
-rw-r--r--include/asn1c/NativeEnumerated.h2
-rw-r--r--include/asn1c/NativeInteger.h2
-rw-r--r--include/asn1c/NativeReal.h2
-rw-r--r--include/asn1c/OBJECT_IDENTIFIER.h8
-rw-r--r--include/asn1c/OCTET_STRING.h4
-rw-r--r--include/asn1c/REAL.h2
-rw-r--r--include/asn1c/RELATIVE-OID.h2
-rw-r--r--include/asn1c/asn_codecs.h4
-rw-r--r--include/asn1c/asn_internal.h19
-rw-r--r--include/asn1c/asn_system.h12
-rw-r--r--include/asn1c/constr_CHOICE.h6
-rw-r--r--include/asn1c/constr_SEQUENCE.h8
-rw-r--r--include/asn1c/constr_SEQUENCE_OF.h2
-rw-r--r--include/asn1c/constr_SET.h10
-rw-r--r--include/asn1c/constr_SET_OF.h4
-rw-r--r--include/asn1c/constr_TYPE.h20
-rw-r--r--include/asn1c/per_decoder.h22
-rw-r--r--include/asn1c/per_encoder.h11
-rw-r--r--include/asn1c/per_opentype.h2
-rw-r--r--include/asn1c/per_support.h44
-rw-r--r--include/asn1c/xer_decoder.h7
-rw-r--r--src/ANY.c87
-rw-r--r--src/BIT_STRING.c6
-rw-r--r--src/BMPString.c6
-rw-r--r--src/BOOLEAN.c58
-rw-r--r--src/ENUMERATED.c36
-rw-r--r--src/GeneralString.c4
-rw-r--r--src/GeneralizedTime.c37
-rw-r--r--src/GraphicString.c4
-rw-r--r--src/IA5String.c4
-rw-r--r--src/INTEGER.c815
-rw-r--r--src/ISO646String.c4
-rw-r--r--src/Makefile.am2
-rw-r--r--src/NULL.c56
-rw-r--r--src/NativeEnumerated.c130
-rw-r--r--src/NativeInteger.c72
-rw-r--r--src/NativeReal.c104
-rw-r--r--src/NumericString.c4
-rw-r--r--src/OBJECT_IDENTIFIER.c131
-rw-r--r--src/OCTET_STRING.c405
-rw-r--r--src/ObjectDescriptor.c4
-rw-r--r--src/PrintableString.c10
-rw-r--r--src/REAL.c125
-rw-r--r--src/RELATIVE-OID.c16
-rw-r--r--src/T61String.c4
-rw-r--r--src/TeletexString.c4
-rw-r--r--src/UTCTime.c4
-rw-r--r--src/UTF8String.c8
-rw-r--r--src/UniversalString.c4
-rw-r--r--src/VideotexString.c4
-rw-r--r--src/VisibleString.c4
-rw-r--r--src/asn_codecs_prim.c45
-rw-r--r--src/ber_decoder.c2
-rw-r--r--src/constr_CHOICE.c194
-rw-r--r--src/constr_SEQUENCE.c355
-rw-r--r--src/constr_SEQUENCE_OF.c69
-rw-r--r--src/constr_SET.c218
-rw-r--r--src/constr_SET_OF.c94
-rw-r--r--src/constr_TYPE.c2
-rw-r--r--src/der_encoder.c14
-rw-r--r--src/per_decoder.c87
-rw-r--r--src/per_encoder.c95
-rw-r--r--src/per_opentype.c102
-rw-r--r--src/per_support.c307
-rw-r--r--src/xer_decoder.c14
-rw-r--r--src/xer_support.c16
73 files changed, 3489 insertions, 524 deletions
diff --git a/asn1c-talloc.patch b/asn1c-talloc.patch
index 909772f..87bb44b 100644
--- a/asn1c-talloc.patch
+++ b/asn1c-talloc.patch
@@ -1,18 +1,16 @@
-diff --git a/include/asn1c/asn_internal.h b/include/asn1c/asn_internal.h
-index 67f055a..45b1adb 100644
---- a/include/asn1c/asn_internal.h
-+++ b/include/asn1c/asn_internal.h
+--- ../asn1c/skeletons/asn_internal.h 2015-08-31 09:29:45.590924282 +0200
++++ include/asn1c/asn_internal.h 2015-08-31 09:26:17.461872713 +0200
@@ -15,6 +15,8 @@
#include <assert.h> /* for assert() macro */
#endif
-+#include <osmocore/talloc.h>
++#include <osmocom/core/talloc.h>
+
#ifdef __cplusplus
extern "C" {
#endif
-@@ -23,10 +25,12 @@ extern "C" {
- #define ASN1C_ENVIRONMENT_VERSION 920 /* Compile-time version */
+@@ -23,10 +25,12 @@
+ #define ASN1C_ENVIRONMENT_VERSION 924 /* Compile-time version */
int get_asn1c_environment_version(void); /* Run-time version */
-#define CALLOC(nmemb, size) calloc(nmemb, size)
@@ -26,5 +24,5 @@ index 67f055a..45b1adb 100644
+#define REALLOC(oldptr, size) talloc_realloc_size(talloc_asn1_ctx, oldptr, size)
+#define FREEMEM(ptr) talloc_free(ptr)
- /*
- * A macro for debugging the ASN.1 internals.
+ #define asn_debug_indent 0
+ #define ASN_DEBUG_INDENT_ADD(i) do{}while(0)
diff --git a/configure.ac b/configure.ac
index ce5140a..b8b5743 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([libasn1c], [0.9.21],
+AC_INIT([libasn1c], [0.9.28],
[openbsc-devel@lists.openbsc.org])
AM_INIT_AUTOMAKE([dist-bzip2])
diff --git a/include/asn1c/ANY.h b/include/asn1c/ANY.h
index b7d92fa..a68441d 100644
--- a/include/asn1c/ANY.h
+++ b/include/asn1c/ANY.h
@@ -32,10 +32,13 @@ xer_type_encoder_f ANY_encode_xer;
/* Convert another ASN.1 type into the ANY. This implies DER encoding. */
int ANY_fromType(ANY_t *, asn_TYPE_descriptor_t *td, void *struct_ptr);
+int ANY_fromType_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr);
ANY_t *ANY_new_fromType(asn_TYPE_descriptor_t *td, void *struct_ptr);
+ANY_t *ANY_new_fromType_aper(asn_TYPE_descriptor_t *td, void *sptr);
/* Convert the contents of the ANY type into the specified type. */
int ANY_to_type(ANY_t *, asn_TYPE_descriptor_t *td, void **struct_ptr);
+int ANY_to_type_aper(ANY_t *, asn_TYPE_descriptor_t *td, void **struct_ptr);
#define ANY_fromBuf(s, buf, size) OCTET_STRING_fromBuf((s), (buf), (size))
#define ANY_new_fromBuf(buf, size) OCTET_STRING_new_fromBuf( \
diff --git a/include/asn1c/BOOLEAN.h b/include/asn1c/BOOLEAN.h
index 217d0f1..8ea2892 100644
--- a/include/asn1c/BOOLEAN.h
+++ b/include/asn1c/BOOLEAN.h
@@ -28,6 +28,8 @@ xer_type_decoder_f BOOLEAN_decode_xer;
xer_type_encoder_f BOOLEAN_encode_xer;
per_type_decoder_f BOOLEAN_decode_uper;
per_type_encoder_f BOOLEAN_encode_uper;
+per_type_decoder_f BOOLEAN_decode_aper;
+per_type_encoder_f BOOLEAN_encode_aper;
#ifdef __cplusplus
}
diff --git a/include/asn1c/ENUMERATED.h b/include/asn1c/ENUMERATED.h
index 542dcae..5c4a2ed 100644
--- a/include/asn1c/ENUMERATED.h
+++ b/include/asn1c/ENUMERATED.h
@@ -17,6 +17,8 @@ extern asn_TYPE_descriptor_t asn_DEF_ENUMERATED;
per_type_decoder_f ENUMERATED_decode_uper;
per_type_encoder_f ENUMERATED_encode_uper;
+per_type_decoder_f ENUMERATED_decode_aper;
+per_type_encoder_f ENUMERATED_encode_aper;
#ifdef __cplusplus
}
diff --git a/include/asn1c/INTEGER.h b/include/asn1c/INTEGER.h
index 8411bfc..e8b36c7 100644
--- a/include/asn1c/INTEGER.h
+++ b/include/asn1c/INTEGER.h
@@ -18,15 +18,15 @@ extern asn_TYPE_descriptor_t asn_DEF_INTEGER;
/* Map with <tag> to integer value association */
typedef struct asn_INTEGER_enum_map_s {
- long nat_value; /* associated native integer value */
+ int64_t nat_value; /* associated native integer value */
size_t enum_len; /* strlen("tag") */
const char *enum_name; /* "tag" */
} asn_INTEGER_enum_map_t;
/* This type describes an enumeration for INTEGER and ENUMERATED types */
-typedef struct asn_INTEGER_specifics_s {
- asn_INTEGER_enum_map_t *value2enum; /* N -> "tag"; sorted by N */
- unsigned int *enum2value; /* "tag" => N; sorted by tag */
+typedef const struct asn_INTEGER_specifics_s {
+ const asn_INTEGER_enum_map_t *value2enum; /* N -> "tag"; sorted by N */
+ const unsigned int *enum2value; /* "tag" => N; sorted by tag */
int map_count; /* Elements in either map */
int extension; /* This map is extensible */
int strict_enumeration; /* Enumeration set is fixed */
@@ -41,6 +41,8 @@ xer_type_decoder_f INTEGER_decode_xer;
xer_type_encoder_f INTEGER_encode_xer;
per_type_decoder_f INTEGER_decode_uper;
per_type_encoder_f INTEGER_encode_uper;
+per_type_decoder_f INTEGER_decode_aper;
+per_type_encoder_f INTEGER_encode_aper;
/***********************************
* Some handy conversion routines. *
@@ -52,11 +54,28 @@ per_type_encoder_f INTEGER_encode_uper;
* -1/ERANGE: Value encoded is out of range for long representation
* -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()).
*/
+int asn_INTEGER2int64(const INTEGER_t *i, int64_t *l);
+int asn_INTEGER2uint64(const INTEGER_t *i, uint64_t *l);
int asn_INTEGER2long(const INTEGER_t *i, long *l);
int asn_INTEGER2ulong(const INTEGER_t *i, unsigned long *l);
+int asn_int642INTEGER(INTEGER_t *i, int64_t l);
+int asn_uint642INTEGER(INTEGER_t *i, uint64_t l);
int asn_long2INTEGER(INTEGER_t *i, long l);
int asn_ulong2INTEGER(INTEGER_t *i, unsigned long l);
+/* A a reified version of strtol(3) with nicer error reporting. */
+enum asn_strtol_result_e {
+ ASN_STRTOL_ERROR_RANGE = -3, /* Input outside of numeric range for long type */
+ ASN_STRTOL_ERROR_INVAL = -2, /* Invalid data encountered (e.g., "+-") */
+ ASN_STRTOL_EXPECT_MORE = -1, /* More data expected (e.g. "+") */
+ ASN_STRTOL_OK = 0, /* Conversion succeded, number ends at (*end) */
+ ASN_STRTOL_EXTRA_DATA = 1, /* Conversion succeded, but the string has extra stuff */
+};
+enum asn_strtol_result_e asn_strtol_lim(const char *str, const char **end, long *l);
+
+/* The asn_strtol is going to be DEPRECATED soon */
+enum asn_strtol_result_e asn_strtol(const char *str, const char *end, long *l);
+
/*
* Convert the integer value into the corresponding enumeration map entry.
*/
diff --git a/include/asn1c/NULL.h b/include/asn1c/NULL.h
index 131e775..90784d8 100644
--- a/include/asn1c/NULL.h
+++ b/include/asn1c/NULL.h
@@ -25,6 +25,8 @@ xer_type_decoder_f NULL_decode_xer;
xer_type_encoder_f NULL_encode_xer;
per_type_decoder_f NULL_decode_uper;
per_type_encoder_f NULL_encode_uper;
+per_type_decoder_f NULL_decode_aper;
+per_type_encoder_f NULL_encode_aper;
#ifdef __cplusplus
}
diff --git a/include/asn1c/NativeEnumerated.h b/include/asn1c/NativeEnumerated.h
index b5acc71..9db2611 100644
--- a/include/asn1c/NativeEnumerated.h
+++ b/include/asn1c/NativeEnumerated.h
@@ -24,6 +24,8 @@ extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated;
xer_type_encoder_f NativeEnumerated_encode_xer;
per_type_decoder_f NativeEnumerated_decode_uper;
per_type_encoder_f NativeEnumerated_encode_uper;
+per_type_decoder_f NativeEnumerated_decode_aper;
+per_type_encoder_f NativeEnumerated_encode_aper;
asn_struct_print_f NativeEnumerated_print;
#ifdef __cplusplus
diff --git a/include/asn1c/NativeInteger.h b/include/asn1c/NativeInteger.h
index 4e63a83..14aa1a4 100644
--- a/include/asn1c/NativeInteger.h
+++ b/include/asn1c/NativeInteger.h
@@ -29,6 +29,8 @@ xer_type_decoder_f NativeInteger_decode_xer;
xer_type_encoder_f NativeInteger_encode_xer;
per_type_decoder_f NativeInteger_decode_uper;
per_type_encoder_f NativeInteger_encode_uper;
+per_type_decoder_f NativeInteger_decode_aper;
+per_type_encoder_f NativeInteger_encode_aper;
#ifdef __cplusplus
}
diff --git a/include/asn1c/NativeReal.h b/include/asn1c/NativeReal.h
index 68a81d9..94ed9de 100644
--- a/include/asn1c/NativeReal.h
+++ b/include/asn1c/NativeReal.h
@@ -27,6 +27,8 @@ xer_type_decoder_f NativeReal_decode_xer;
xer_type_encoder_f NativeReal_encode_xer;
per_type_decoder_f NativeReal_decode_uper;
per_type_encoder_f NativeReal_encode_uper;
+per_type_decoder_f NativeReal_decode_aper;
+per_type_encoder_f NativeReal_encode_aper;
#ifdef __cplusplus
}
diff --git a/include/asn1c/OBJECT_IDENTIFIER.h b/include/asn1c/OBJECT_IDENTIFIER.h
index 2bb5d03..c2c6373 100644
--- a/include/asn1c/OBJECT_IDENTIFIER.h
+++ b/include/asn1c/OBJECT_IDENTIFIER.h
@@ -68,7 +68,7 @@ xer_type_encoder_f OBJECT_IDENTIFIER_encode_xer;
* WARNING: The function always returns the real number of arcs,
* even if there is no sufficient (_arc_slots) provided.
*/
-int OBJECT_IDENTIFIER_get_arcs(OBJECT_IDENTIFIER_t *_oid,
+int OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *_oid,
void *_arcs, /* e.g., unsigned int arcs[N] */
unsigned int _arc_type_size, /* e.g., sizeof(arcs[0]) */
unsigned int _arc_slots /* e.g., N */);
@@ -91,12 +91,12 @@ int OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *_oid,
/*
* Print the specified OBJECT IDENTIFIER arc.
*/
-int OBJECT_IDENTIFIER_print_arc(uint8_t *arcbuf, int arclen,
+int OBJECT_IDENTIFIER_print_arc(const uint8_t *arcbuf, int arclen,
int add, /* Arbitrary offset, required to process the first two arcs */
asn_app_consume_bytes_f *cb, void *app_key);
/* Same as above, but returns the number of written digits, instead of 0 */
-ssize_t OBJECT_IDENTIFIER__dump_arc(uint8_t *arcbuf, int arclen, int add,
+ssize_t OBJECT_IDENTIFIER__dump_arc(const uint8_t *arcbuf, int arclen, int add,
asn_app_consume_bytes_f *cb, void *app_key);
/*
@@ -127,7 +127,7 @@ int OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length,
* Internal functions.
* Used by RELATIVE-OID implementation in particular.
*/
-int OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen,
+int OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf, unsigned int arclen,
signed int add, void *value, unsigned int value_size);
int OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf,
const void *arcval, unsigned int arcval_size, int _prepared_order);
diff --git a/include/asn1c/OCTET_STRING.h b/include/asn1c/OCTET_STRING.h
index 8df9a18..bc25666 100644
--- a/include/asn1c/OCTET_STRING.h
+++ b/include/asn1c/OCTET_STRING.h
@@ -32,6 +32,8 @@ xer_type_encoder_f OCTET_STRING_encode_xer;
xer_type_encoder_f OCTET_STRING_encode_xer_utf8;
per_type_decoder_f OCTET_STRING_decode_uper;
per_type_encoder_f OCTET_STRING_encode_uper;
+per_type_decoder_f OCTET_STRING_decode_aper;
+per_type_encoder_f OCTET_STRING_encode_aper;
/******************************
* Handy conversion routines. *
@@ -63,7 +65,7 @@ OCTET_STRING_t *OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td,
* Internally useful stuff. *
****************************/
-typedef struct asn_OCTET_STRING_specifics_s {
+typedef const struct asn_OCTET_STRING_specifics_s {
/*
* Target structure description.
*/
diff --git a/include/asn1c/REAL.h b/include/asn1c/REAL.h
index af3e84c..503e254 100644
--- a/include/asn1c/REAL.h
+++ b/include/asn1c/REAL.h
@@ -21,6 +21,8 @@ xer_type_decoder_f REAL_decode_xer;
xer_type_encoder_f REAL_encode_xer;
per_type_decoder_f REAL_decode_uper;
per_type_encoder_f REAL_encode_uper;
+per_type_decoder_f REAL_decode_aper;
+per_type_encoder_f REAL_encode_aper;
/***********************************
* Some handy conversion routines. *
diff --git a/include/asn1c/RELATIVE-OID.h b/include/asn1c/RELATIVE-OID.h
index 2235cfd..65acaab 100644
--- a/include/asn1c/RELATIVE-OID.h
+++ b/include/asn1c/RELATIVE-OID.h
@@ -25,7 +25,7 @@ xer_type_encoder_f RELATIVE_OID_encode_xer;
**********************************/
/* See OBJECT_IDENTIFIER_get_arcs() function in OBJECT_IDENTIFIER.h */
-int RELATIVE_OID_get_arcs(RELATIVE_OID_t *_roid,
+int RELATIVE_OID_get_arcs(const RELATIVE_OID_t *_roid,
void *arcs, unsigned int arc_type_size, unsigned int arc_slots);
/* See OBJECT_IDENTIFIER_set_arcs() function in OBJECT_IDENTIFIER.h */
diff --git a/include/asn1c/asn_codecs.h b/include/asn1c/asn_codecs.h
index 4a251d9..e560014 100644
--- a/include/asn1c/asn_codecs.h
+++ b/include/asn1c/asn_codecs.h
@@ -62,7 +62,7 @@ typedef struct asn_enc_rval_s {
tmp_error.encoded = -1; \
tmp_error.failed_type = td; \
tmp_error.structure_ptr = sptr; \
- ASN_DEBUG("Failed to encode element %s", td->name); \
+ ASN_DEBUG("Failed to encode element %s", td ? td->name : ""); \
return tmp_error; \
} while(0)
#define _ASN_ENCODED_OK(rval) do { \
@@ -92,7 +92,7 @@ typedef struct asn_dec_rval_s {
asn_dec_rval_t tmp_error; \
tmp_error.code = RC_FAIL; \
tmp_error.consumed = 0; \
- ASN_DEBUG("Failed to decode element %s", td->name); \
+ ASN_DEBUG("Failed to decode element %s", td ? td->name : ""); \
return tmp_error; \
} while(0)
#define _ASN_DECODE_STARVED do { \
diff --git a/include/asn1c/asn_internal.h b/include/asn1c/asn_internal.h
index e6da3fe..58b4583 100644
--- a/include/asn1c/asn_internal.h
+++ b/include/asn1c/asn_internal.h
@@ -22,7 +22,7 @@ extern "C" {
#endif
/* Environment version might be used to avoid running with the old library */
-#define ASN1C_ENVIRONMENT_VERSION 922 /* Compile-time version */
+#define ASN1C_ENVIRONMENT_VERSION 924 /* Compile-time version */
int get_asn1c_environment_version(void); /* Run-time version */
extern void *talloc_asn1_ctx;
@@ -32,6 +32,9 @@ extern void *talloc_asn1_ctx;
#define REALLOC(oldptr, size) talloc_realloc_size(talloc_asn1_ctx, oldptr, size)
#define FREEMEM(ptr) talloc_free(ptr)
+#define asn_debug_indent 0
+#define ASN_DEBUG_INDENT_ADD(i) do{}while(0)
+
/*
* A macro for debugging the ASN.1 internals.
* You may enable or override it.
@@ -40,17 +43,25 @@ extern void *talloc_asn1_ctx;
#if EMIT_ASN_DEBUG == 1 /* And it was asked to emit this code... */
#ifdef __GNUC__
#ifdef ASN_THREAD_SAFE
-#define asn_debug_indent 0
+/* Thread safety requires sacrifice in output indentation:
+ * Retain empty definition of ASN_DEBUG_INDENT_ADD. */
#else /* !ASN_THREAD_SAFE */
+#undef ASN_DEBUG_INDENT_ADD
+#undef asn_debug_indent
int asn_debug_indent;
+#define ASN_DEBUG_INDENT_ADD(i) do { asn_debug_indent += i; } while(0)
#endif /* ASN_THREAD_SAFE */
-#define ASN_DEBUG(fmt, args...) do { \
+extern int asn_debug; /* Allow option on execution */
+#define ASN_DEBUG(fmt, args...) \
+if (asn_debug) { \
+ do { \
int adi = asn_debug_indent; \
while(adi--) fprintf(stderr, " "); \
fprintf(stderr, fmt, ##args); \
fprintf(stderr, " (%s:%d)\n", \
__FILE__, __LINE__); \
- } while(0)
+ } while(0); \
+}
#else /* !__GNUC__ */
void ASN_DEBUG_f(const char *fmt, ...);
#define ASN_DEBUG ASN_DEBUG_f
diff --git a/include/asn1c/asn_system.h b/include/asn1c/asn_system.h
index 0a9b092..e420ad2 100644
--- a/include/asn1c/asn_system.h
+++ b/include/asn1c/asn_system.h
@@ -21,7 +21,7 @@
#include <stdarg.h> /* For va_start */
#include <stddef.h> /* for offsetof and ptrdiff_t */
-#ifdef WIN32
+#ifdef _WIN32
#include <malloc.h>
#define snprintf _snprintf
@@ -29,9 +29,9 @@
/* To avoid linking with ws2_32.lib, here's the definition of ntohl() */
#define sys_ntohl(l) ((((l) << 24) & 0xff000000) \
- | (((l) << 16) & 0xff0000) \
- | (((l) << 8) & 0xff00) \
- | ((l) & 0xff))
+ | (((l) << 8) & 0xff0000) \
+ | (((l) >> 8) & 0xff00) \
+ | ((l >> 24) & 0xff))
#ifdef _MSC_VER /* MSVS.Net */
#ifndef __cplusplus
@@ -57,7 +57,7 @@ typedef unsigned int uint32_t;
#include <stdint.h>
#endif /* _MSC_VER */
-#else /* !WIN32 */
+#else /* !_WIN32 */
#if defined(__vxworks)
#include <types/vxTypes.h>
@@ -90,7 +90,7 @@ typedef unsigned int uint32_t;
#endif /* defined(__vxworks) */
-#endif /* WIN32 */
+#endif /* _WIN32 */
#if __GNUC__ >= 3
#ifndef GCC_PRINTFLIKE
diff --git a/include/asn1c/constr_CHOICE.h b/include/asn1c/constr_CHOICE.h
index 83404e6..ddcbb39 100644
--- a/include/asn1c/constr_CHOICE.h
+++ b/include/asn1c/constr_CHOICE.h
@@ -12,7 +12,7 @@
extern "C" {
#endif
-typedef struct asn_CHOICE_specifics_s {
+typedef const struct asn_CHOICE_specifics_s {
/*
* Target structure description.
*/
@@ -24,7 +24,7 @@ typedef struct asn_CHOICE_specifics_s {
/*
* Tags to members mapping table.
*/
- asn_TYPE_tag2member_t *tag2el;
+ const asn_TYPE_tag2member_t *tag2el;
int tag2el_count;
/* Canonical ordering of CHOICE elements, for PER */
@@ -48,6 +48,8 @@ xer_type_decoder_f CHOICE_decode_xer;
xer_type_encoder_f CHOICE_encode_xer;
per_type_decoder_f CHOICE_decode_uper;
per_type_encoder_f CHOICE_encode_uper;
+per_type_decoder_f CHOICE_decode_aper;
+per_type_encoder_f CHOICE_encode_aper;
asn_outmost_tag_f CHOICE_outmost_tag;
#ifdef __cplusplus
diff --git a/include/asn1c/constr_SEQUENCE.h b/include/asn1c/constr_SEQUENCE.h
index 5f589d5..d181848 100644
--- a/include/asn1c/constr_SEQUENCE.h
+++ b/include/asn1c/constr_SEQUENCE.h
@@ -11,7 +11,7 @@
extern "C" {
#endif
-typedef struct asn_SEQUENCE_specifics_s {
+typedef const struct asn_SEQUENCE_specifics_s {
/*
* Target structure description.
*/
@@ -21,14 +21,14 @@ typedef struct asn_SEQUENCE_specifics_s {
/*
* Tags to members mapping table (sorted).
*/
- asn_TYPE_tag2member_t *tag2el;
+ const asn_TYPE_tag2member_t *tag2el;
int tag2el_count;
/*
* Optional members of the extensions root (roms) or additions (aoms).
* Meaningful for PER.
*/
- int *oms; /* Optional MemberS */
+ const int *oms; /* Optional MemberS */
int roms_count; /* Root optional members count */
int aoms_count; /* Additions optional members count */
@@ -52,6 +52,8 @@ xer_type_decoder_f SEQUENCE_decode_xer;
xer_type_encoder_f SEQUENCE_encode_xer;
per_type_decoder_f SEQUENCE_decode_uper;
per_type_encoder_f SEQUENCE_encode_uper;
+per_type_decoder_f SEQUENCE_decode_aper;
+per_type_encoder_f SEQUENCE_encode_aper;
#ifdef __cplusplus
}
diff --git a/include/asn1c/constr_SEQUENCE_OF.h b/include/asn1c/constr_SEQUENCE_OF.h
index e2272f3..94a7cd5 100644
--- a/include/asn1c/constr_SEQUENCE_OF.h
+++ b/include/asn1c/constr_SEQUENCE_OF.h
@@ -22,9 +22,11 @@ extern "C" {
#define SEQUENCE_OF_decode_ber SET_OF_decode_ber
#define SEQUENCE_OF_decode_xer SET_OF_decode_xer
#define SEQUENCE_OF_decode_uper SET_OF_decode_uper
+#define SEQUENCE_OF_decode_aper SET_OF_decode_aper
der_type_encoder_f SEQUENCE_OF_encode_der;
xer_type_encoder_f SEQUENCE_OF_encode_xer;
per_type_encoder_f SEQUENCE_OF_encode_uper;
+per_type_encoder_f SEQUENCE_OF_encode_aper;
#ifdef __cplusplus
}
diff --git a/include/asn1c/constr_SET.h b/include/asn1c/constr_SET.h
index 0c78ed5..11b7153 100644
--- a/include/asn1c/constr_SET.h
+++ b/include/asn1c/constr_SET.h
@@ -12,7 +12,7 @@ extern "C" {
#endif
-typedef struct asn_SET_specifics_s {
+typedef const struct asn_SET_specifics_s {
/*
* Target structure description.
*/
@@ -25,21 +25,21 @@ typedef struct asn_SET_specifics_s {
* Sometimes suitable for DER encoding (untagged CHOICE is present);
* if so, tag2el_count will be greater than td->elements_count.
*/
- asn_TYPE_tag2member_t *tag2el;
+ const asn_TYPE_tag2member_t *tag2el;
int tag2el_count;
/*
* Tags to members mapping table, second edition.
* Suitable for CANONICAL-XER encoding.
*/
- asn_TYPE_tag2member_t *tag2el_cxer;
+ const asn_TYPE_tag2member_t *tag2el_cxer;
int tag2el_cxer_count;
/*
* Extensions-related stuff.
*/
int extensible; /* Whether SET is extensible */
- unsigned int *_mandatory_elements; /* Bitmask of mandatory ones */
+ const unsigned int *_mandatory_elements; /* Bitmask of mandatory ones */
} asn_SET_specifics_t;
/*
@@ -53,7 +53,9 @@ der_type_encoder_f SET_encode_der;
xer_type_decoder_f SET_decode_xer;
xer_type_encoder_f SET_encode_xer;
per_type_decoder_f SET_decode_uper;
+per_type_decoder_f SET_decode_aper;
per_type_encoder_f SET_encode_uper;
+per_type_encoder_f SET_encode_aper;
/***********************
* Some handy helpers. *
diff --git a/include/asn1c/constr_SET_OF.h b/include/asn1c/constr_SET_OF.h
index bcd0966..8ddd0e3 100644
--- a/include/asn1c/constr_SET_OF.h
+++ b/include/asn1c/constr_SET_OF.h
@@ -11,7 +11,7 @@
extern "C" {
#endif
-typedef struct asn_SET_OF_specifics_s {
+typedef const struct asn_SET_OF_specifics_s {
/*
* Target structure description.
*/
@@ -34,6 +34,8 @@ xer_type_decoder_f SET_OF_decode_xer;
xer_type_encoder_f SET_OF_encode_xer;
per_type_decoder_f SET_OF_decode_uper;
per_type_encoder_f SET_OF_encode_uper;
+per_type_decoder_f SET_OF_decode_aper;
+per_type_encoder_f SET_OF_encode_aper;
#ifdef __cplusplus
}
diff --git a/include/asn1c/constr_TYPE.h b/include/asn1c/constr_TYPE.h
index 95507c8..13c60f3 100644
--- a/include/asn1c/constr_TYPE.h
+++ b/include/asn1c/constr_TYPE.h
@@ -73,7 +73,7 @@ typedef int (asn_struct_print_f)(
* Do not use it in your application.
*/
typedef ber_tlv_tag_t (asn_outmost_tag_f)(
- struct asn_TYPE_descriptor_s *type_descriptor,
+ const struct asn_TYPE_descriptor_s *type_descriptor,
const void *struct_ptr, int tag_mode, ber_tlv_tag_t tag);
/* The instance of the above function type; used internally. */
asn_outmost_tag_f asn_TYPE_outmost_tag;
@@ -83,8 +83,8 @@ asn_outmost_tag_f asn_TYPE_outmost_tag;
* The definitive description of the destination language's structure.
*/
typedef struct asn_TYPE_descriptor_s {
- char *name; /* A name of the ASN.1 type. "" in some cases. */
- char *xml_tag; /* Name used in XML tag */
+ const char *name; /* A name of the ASN.1 type. "" in some cases. */
+ const char *xml_tag; /* Name used in XML tag */
/*
* Generalized functions for dealing with the specific type.
@@ -99,6 +99,8 @@ typedef struct asn_TYPE_descriptor_s {
xer_type_encoder_f *xer_encoder; /* [Canonical] XER encoder */
per_type_decoder_f *uper_decoder; /* Unaligned PER decoder */
per_type_encoder_f *uper_encoder; /* Unaligned PER encoder */
+ per_type_decoder_f *aper_decoder; /* Aligned PER decoder */
+ per_type_encoder_f *aper_encoder; /* Aligned PER encoder */
/***********************************************************************
* Internally useful members. Not to be used by applications directly. *
@@ -108,10 +110,10 @@ typedef struct asn_TYPE_descriptor_s {
* Tags that are expected to occur.
*/
asn_outmost_tag_f *outmost_tag; /* <optional, internal> */
- ber_tlv_tag_t *tags; /* Effective tags sequence for this type */
- int tags_count; /* Number of tags which are expected */
- ber_tlv_tag_t *all_tags;/* Every tag for BER/containment */
- int all_tags_count; /* Number of tags */
+ const ber_tlv_tag_t *tags; /* Effective tags sequence for this type */
+ int tags_count; /* Number of tags which are expected */
+ const ber_tlv_tag_t *all_tags; /* Every tag for BER/containment */
+ int all_tags_count; /* Number of tags */
asn_per_constraints_t *per_constraints; /* PER compiled constraints */
@@ -125,7 +127,7 @@ typedef struct asn_TYPE_descriptor_s {
* Additional information describing the type, used by appropriate
* functions above.
*/
- void *specifics;
+ const void *specifics;
} asn_TYPE_descriptor_t;
/*
@@ -147,7 +149,7 @@ typedef struct asn_TYPE_member_s {
asn_constr_check_f *memb_constraints; /* Constraints validator */
asn_per_constraints_t *per_constraints; /* PER compiled constraints */
int (*default_value)(int setval, void **sptr); /* DEFAULT <value> */
- char *name; /* ASN.1 identifier of the element */
+ const char *name; /* ASN.1 identifier of the element */
} asn_TYPE_member_t;
/*
diff --git a/include/asn1c/per_decoder.h b/include/asn1c/per_decoder.h
index 8397a54..5541bae 100644
--- a/include/asn1c/per_decoder.h
+++ b/include/asn1c/per_decoder.h
@@ -38,8 +38,30 @@ asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx,
int unused_bits /* Number of unused tailing bits, 0..7 */
);
+/*
+ * Aligned PER decoder of a "complete encoding" as per X.691#10.1.
+ * On success, this call always returns (.consumed >= 1), as per X.691#10.1.3.
+ */
+asn_dec_rval_t aper_decode_complete(struct asn_codec_ctx_s *opt_codec_ctx,
+ struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */
+ void **struct_ptr, /* Pointer to a target structure's pointer */
+ const void *buffer, /* Data to be decoded */
+ size_t size /* Size of data buffer */
+ );
/*
+ * Aligned PER decoder of any ASN.1 type. May be invoked by the application.
+ * WARNING: This call returns the number of BITS read from the stream. Beware.
+ */
+asn_dec_rval_t aper_decode(struct asn_codec_ctx_s *opt_codec_ctx,
+ struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */
+ void **struct_ptr, /* Pointer to a target structure's pointer */
+ const void *buffer, /* Data to be decoded */
+ size_t size, /* Size of data buffer */
+ int skip_bits, /* Number of unused leading bits, 0..7 */
+ int unused_bits /* Number of unused tailing bits, 0..7 */
+ );
+/*
* Type of the type-specific PER decoder function.
*/
typedef asn_dec_rval_t (per_type_decoder_f)(asn_codec_ctx_t *opt_codec_ctx,
diff --git a/include/asn1c/per_encoder.h b/include/asn1c/per_encoder.h
index 95a6506..e3b9190 100644
--- a/include/asn1c/per_encoder.h
+++ b/include/asn1c/per_encoder.h
@@ -38,6 +38,12 @@ asn_enc_rval_t uper_encode_to_buffer(
size_t buffer_size /* Initial buffer size (max) */
);
+asn_enc_rval_t aper_encode_to_buffer(
+ struct asn_TYPE_descriptor_s *type_descriptor,
+ void *struct_ptr, /* Structure to be encoded */
+ void *buffer, /* Pre-allocated buffer */
+ size_t buffer_size /* Initial buffer size (max) */
+);
/*
* A variant of uper_encode_to_buffer() which allocates buffer itself.
* Returns the number of bytes in the buffer or -1 in case of failure.
@@ -52,6 +58,11 @@ ssize_t uper_encode_to_new_buffer(
void **buffer_r /* Buffer allocated and returned */
);
+ssize_t
+aper_encode_to_new_buffer(struct asn_TYPE_descriptor_s *td,
+ asn_per_constraints_t *constraints,
+ void *sptr,
+ void **buffer_r);
/*
* Type of the generic PER encoder function.
*/
diff --git a/include/asn1c/per_opentype.h b/include/asn1c/per_opentype.h
index facfaa6..2117efe 100644
--- a/include/asn1c/per_opentype.h
+++ b/include/asn1c/per_opentype.h
@@ -15,6 +15,8 @@ int uper_open_type_skip(asn_codec_ctx_t *opt_codec_ctx, asn_per_data_t *pd);
int uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po);
+int aper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/asn1c/per_support.h b/include/asn1c/per_support.h
index 7cb1a0c..181fe24 100644
--- a/include/asn1c/per_support.h
+++ b/include/asn1c/per_support.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
+ * Copyright (c) 2005-2014 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
@@ -15,7 +15,7 @@ extern "C" {
/*
* Pre-computed PER constraints.
*/
-typedef struct asn_per_constraint_s {
+typedef const struct asn_per_constraint_s {
enum asn_per_constraint_flags {
APC_UNCONSTRAINED = 0x0, /* No PER visible constraints */
APC_SEMI_CONSTRAINED = 0x1, /* Constrained at "lb" */
@@ -24,12 +24,12 @@ typedef struct asn_per_constraint_s {
} flags;
int range_bits; /* Full number of bits in the range */
int effective_bits; /* Effective bits */
- long lower_bound; /* "lb" value */
- long upper_bound; /* "ub" value */
+ int64_t lower_bound; /* "lb" value */
+ int64_t upper_bound; /* "ub" value */
} asn_per_constraint_t;
-typedef struct asn_per_constraints_s {
- asn_per_constraint_t value;
- asn_per_constraint_t size;
+typedef const struct asn_per_constraints_s {
+ struct asn_per_constraint_s value;
+ struct asn_per_constraint_s size;
int (*value2code)(unsigned int value);
int (*code2value)(unsigned int code);
} asn_per_constraints_t;
@@ -39,9 +39,9 @@ typedef struct asn_per_constraints_s {
*/
typedef struct asn_per_data_s {
const uint8_t *buffer; /* Pointer to the octet stream */
- size_t nboff; /* Bit offset to the meaningful bit */
- size_t nbits; /* Number of bits in the stream */
- size_t moved; /* Number of bits moved through this bit stream */
+ size_t nboff; /* Bit offset to the meaningful bit */
+ size_t nbits; /* Number of bits in the stream */
+ size_t moved; /* Number of bits moved through this bit stream */
int (*refill)(struct asn_per_data_s *);
void *refill_key;
} asn_per_data_t;
@@ -71,15 +71,25 @@ ssize_t uper_get_length(asn_per_data_t *pd,
int effective_bound_bits,
int *repeat);
+ssize_t aper_get_length(asn_per_data_t *pd,
+ int range,
+ int effective_bound_bits,
+ int *repeat);
+
/*
* Get the normally small length "n".
*/
ssize_t uper_get_nslength(asn_per_data_t *pd);
+ssize_t aper_get_nslength(asn_per_data_t *pd);
/*
* Get the normally small non-negative whole number.
*/
ssize_t uper_get_nsnnwn(asn_per_data_t *pd);
+ssize_t aper_get_nsnnwn(asn_per_data_t *pd, int range);
+
+/* X.691-2008/11, #11.5.6 */
+int uper_get_constrained_whole_number(asn_per_data_t *pd, unsigned long *v, int nbits);
/* Non-thread-safe debugging function, don't use it */
char *per_data_string(asn_per_data_t *pd);
@@ -103,6 +113,14 @@ int per_put_few_bits(asn_per_outp_t *per_data, uint32_t bits, int obits);
/* Output a large number of bits */
int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits);
+/* X.691-2008/11, #11.5 */
+int uper_put_constrained_whole_number_s(asn_per_outp_t *po, long v, int nbits);
+int uper_put_constrained_whole_number_u(asn_per_outp_t *po, unsigned long v, int nbits);
+
+/* Align the current bit position to octet bundary */
+int aper_put_align(asn_per_outp_t *po);
+int32_t aper_get_align(asn_per_data_t *pd);
+
/*
* Put the length "n" to the Unaligned PER stream.
* This function returns the number of units which may be flushed
@@ -110,17 +128,23 @@ int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits);
*/
ssize_t uper_put_length(asn_per_outp_t *po, size_t whole_length);
+ssize_t aper_put_length(asn_per_outp_t *po, int range, size_t length);
+
/*
* Put the normally small length "n" to the Unaligned PER stream.
* Returns 0 or -1.
*/
int uper_put_nslength(asn_per_outp_t *po, size_t length);
+int aper_put_nslength(asn_per_outp_t *po, size_t length);
+
/*
* Put the normally small non-negative whole number.
*/
int uper_put_nsnnwn(asn_per_outp_t *po, int n);
+int aper_put_nsnnwn(asn_per_outp_t *po, int range, int number);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/asn1c/xer_decoder.h b/include/asn1c/xer_decoder.h
index cf0d846..6988648 100644
--- a/include/asn1c/xer_decoder.h
+++ b/include/asn1c/xer_decoder.h
@@ -87,12 +87,11 @@ xer_check_tag_e xer_check_tag(const void *buf_ptr, int size,
const char *need_tag);
/*
- * Check whether this buffer consists of entirely XER whitespace characters.
+ * Get the number of bytes consisting entirely of XER whitespace characters.
* RETURN VALUES:
- * 1: Whitespace or empty string
- * 0: Non-whitespace
+ * >=0: Number of whitespace characters in the string.
*/
-int xer_is_whitespace(const void *chunk_buf, size_t chunk_size);
+size_t xer_whitespace_span(const void *chunk_buf, size_t chunk_size);
/*
* Skip the series of anticipated extensions.
diff --git a/src/ANY.c b/src/ANY.c
index 0ad60d0..0fe63ae 100644
--- a/src/ANY.c
+++ b/src/ANY.c
@@ -21,7 +21,10 @@ asn_TYPE_descriptor_t asn_DEF_ANY = {
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
ANY_encode_xer,
- 0, 0,
+ OCTET_STRING_decode_uper,
+ OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
0, 0, 0, 0,
0, /* No PER visible constraints */
@@ -87,6 +90,37 @@ ANY_fromType(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
return 0;
}
+int
+ANY_fromType_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
+ uint8_t *buffer = NULL;
+ ssize_t erval;
+
+ if(!st || !td) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if(!sptr) {
+ if(st->buf) FREEMEM(st->buf);
+ st->size = 0;
+ return 0;
+ }
+
+ erval = aper_encode_to_new_buffer(td, td->per_constraints, sptr, (void**)&buffer);
+
+ if(erval == -1) {
+ if(buffer) FREEMEM(buffer);
+ return -1;
+ }
+ assert((size_t)erval > 0);
+
+ if(st->buf) FREEMEM(st->buf);
+ st->buf = buffer;
+ st->size = erval;
+
+ return 0;
+}
+
ANY_t *
ANY_new_fromType(asn_TYPE_descriptor_t *td, void *sptr) {
ANY_t tmp;
@@ -111,6 +145,30 @@ ANY_new_fromType(asn_TYPE_descriptor_t *td, void *sptr) {
}
}
+ANY_t *
+ANY_new_fromType_aper(asn_TYPE_descriptor_t *td, void *sptr) {
+ ANY_t tmp;
+ ANY_t *st;
+
+ if(!td || !sptr) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ memset(&tmp, 0, sizeof(tmp));
+
+ if(ANY_fromType_aper(&tmp, td, sptr)) return 0;
+
+ st = (ANY_t *)CALLOC(1, sizeof(ANY_t));
+ if(st) {
+ *st = tmp;
+ return st;
+ } else {
+ FREEMEM(tmp.buf);
+ return 0;
+ }
+}
+
int
ANY_to_type(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
asn_dec_rval_t rval;
@@ -138,6 +196,33 @@ ANY_to_type(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
}
}
+int
+ANY_to_type_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
+ asn_dec_rval_t rval;
+ void *newst = 0;
+
+ if(!st || !td || !struct_ptr) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if(st->buf == 0) {
+ /* Nothing to convert, make it empty. */
+ *struct_ptr = (void *)0;
+ return 0;
+ }
+
+ rval = aper_decode(0, td, (void **)&newst, st->buf, st->size, 0, 0);
+ if(rval.code == RC_OK) {
+ *struct_ptr = newst;
+ return 0;
+ } else {
+ /* Remove possibly partially decoded data. */
+ ASN_STRUCT_FREE(*td, newst);
+ return -1;
+ }
+}
+
static int ANY__consume_bytes(const void *buffer, size_t size, void *key) {
struct _callback_arg *arg = (struct _callback_arg *)key;
diff --git a/src/BIT_STRING.c b/src/BIT_STRING.c
index 9b98271..ad2ca60 100644
--- a/src/BIT_STRING.c
+++ b/src/BIT_STRING.c
@@ -9,7 +9,7 @@
/*
* BIT STRING basic type description.
*/
-static ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = {
+static const ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (3 << 2))
};
static asn_OCTET_STRING_specifics_t asn_DEF_BIT_STRING_specs = {
@@ -29,6 +29,8 @@ asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
BIT_STRING_encode_xer,
OCTET_STRING_decode_uper, /* Unaligned PER decoder */
OCTET_STRING_encode_uper, /* Unaligned PER encoder */
+ OCTET_STRING_decode_aper, /* Aligned PER decoder */
+ OCTET_STRING_encode_aper, /* Aligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_BIT_STRING_tags,
sizeof(asn_DEF_BIT_STRING_tags)
@@ -140,7 +142,7 @@ cb_failed:
int
BIT_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
- static const char *h2c = "0123456789ABCDEF";
+ const char * const h2c = "0123456789ABCDEF";
char scratch[64];
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
uint8_t *buf;
diff --git a/src/BMPString.c b/src/BMPString.c
index 072bd07..94471f6 100644
--- a/src/BMPString.c
+++ b/src/BMPString.c
@@ -9,7 +9,7 @@
/*
* BMPString basic type description.
*/
-static ber_tlv_tag_t asn_DEF_BMPString_tags[] = {
+static const ber_tlv_tag_t asn_DEF_BMPString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (30 << 2)), /* [UNIVERSAL 30] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
@@ -35,6 +35,8 @@ asn_TYPE_descriptor_t asn_DEF_BMPString = {
BMPString_encode_xer, /* Convert to UTF-8 */
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper, /* Aligned PER decoder */
+ OCTET_STRING_encode_aper, /* Aligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_BMPString_tags,
sizeof(asn_DEF_BMPString_tags)
@@ -143,7 +145,7 @@ BMPString_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
return rc;
} else {
dstwc[wcs_len] = 0; /* nul-terminate */
- wcs = (uint32_t *)dstwc;
+ wcs = (uint32_t *)(void *)dstwc; /* Alignment OK */
}
}
diff --git a/src/BOOLEAN.c b/src/BOOLEAN.c
index 2c2bbcf..42374b8 100644
--- a/src/BOOLEAN.c
+++ b/src/BOOLEAN.c
@@ -9,7 +9,7 @@
/*
* BOOLEAN basic type description.
*/
-static ber_tlv_tag_t asn_DEF_BOOLEAN_tags[] = {
+static const ber_tlv_tag_t asn_DEF_BOOLEAN_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (1 << 2))
};
asn_TYPE_descriptor_t asn_DEF_BOOLEAN = {
@@ -24,6 +24,8 @@ asn_TYPE_descriptor_t asn_DEF_BOOLEAN = {
BOOLEAN_encode_xer,
BOOLEAN_decode_uper, /* Unaligned PER decoder */
BOOLEAN_encode_uper, /* Unaligned PER encoder */
+ BOOLEAN_decode_aper, /* Aligned PER decoder */
+ BOOLEAN_encode_aper, /* Aligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_BOOLEAN_tags,
sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
@@ -161,10 +163,7 @@ BOOLEAN__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
}
return XPBD_BODY_CONSUMED;
} else {
- if(xer_is_whitespace(chunk_buf, chunk_size))
- return XPBD_NOT_BODY_IGNORE;
- else
- return XPBD_BROKEN_ENCODING;
+ return XPBD_BROKEN_ENCODING;
}
}
@@ -267,18 +266,63 @@ BOOLEAN_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
return rv;
}
+asn_dec_rval_t
+BOOLEAN_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_dec_rval_t rv;
+ BOOLEAN_t *st = (BOOLEAN_t *)*sptr;
+
+ (void)opt_codec_ctx;
+ (void)constraints;
+
+ if(!st) {
+ st = (BOOLEAN_t *)(*sptr = MALLOC(sizeof(*st)));
+ if(!st) _ASN_DECODE_FAILED;
+ }
+
+ /*
+ * Extract a single bit
+ */
+ switch(per_get_few_bits(pd, 1)) {
+ case 1: *st = 1; break;
+ case 0: *st = 0; break;
+ case -1: default: _ASN_DECODE_STARVED;
+ }
+
+ ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE");
+
+ rv.code = RC_OK;
+ rv.consumed = 1;
+ return rv;
+}
asn_enc_rval_t
BOOLEAN_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
- asn_enc_rval_t er;
+ asn_enc_rval_t er = { 0, 0, 0 };
(void)constraints;
if(!st) _ASN_ENCODE_FAILED;
- per_put_few_bits(po, *st ? 1 : 0, 1);
+ if(per_put_few_bits(po, *st ? 1 : 0, 1))
+ _ASN_ENCODE_FAILED;
_ASN_ENCODED_OK(er);
}
+
+asn_enc_rval_t
+BOOLEAN_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
+ asn_enc_rval_t er;
+
+ (void)constraints;
+
+ if(!st) _ASN_ENCODE_FAILED;
+
+ per_put_few_bits(po, *st ? 1 : 0, 1);
+
+ _ASN_ENCODED_OK(er);
+}
diff --git a/src/ENUMERATED.c b/src/ENUMERATED.c
index 90761a2..f313f96 100644
--- a/src/ENUMERATED.c
+++ b/src/ENUMERATED.c
@@ -11,7 +11,7 @@
/*
* ENUMERATED basic type description.
*/
-static ber_tlv_tag_t asn_DEF_ENUMERATED_tags[] = {
+static const ber_tlv_tag_t asn_DEF_ENUMERATED_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
};
asn_TYPE_descriptor_t asn_DEF_ENUMERATED = {
@@ -26,6 +26,8 @@ asn_TYPE_descriptor_t asn_DEF_ENUMERATED = {
INTEGER_encode_xer,
ENUMERATED_decode_uper, /* Unaligned PER decoder */
ENUMERATED_encode_uper, /* Unaligned PER encoder */
+ ENUMERATED_decode_aper, /* Aligned PER decoder */
+ ENUMERATED_encode_aper, /* Aligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_ENUMERATED_tags,
sizeof(asn_DEF_ENUMERATED_tags) / sizeof(asn_DEF_ENUMERATED_tags[0]),
@@ -57,6 +59,27 @@ ENUMERATED_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td
return rval;
}
+asn_dec_rval_t
+ENUMERATED_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_dec_rval_t rval;
+ ENUMERATED_t *st = (ENUMERATED_t *)*sptr;
+ long value;
+ void *vptr = &value;
+
+ if(!st) {
+ st = (ENUMERATED_t *)(*sptr = CALLOC(1, sizeof(*st)));
+ if(!st) _ASN_DECODE_FAILED;
+ }
+
+ rval = NativeEnumerated_decode_aper(opt_codec_ctx, td, constraints,
+ (void **)&vptr, pd);
+ if(rval.code == RC_OK)
+ if(asn_long2INTEGER(st, value))
+ rval.code = RC_FAIL;
+ return rval;
+}
+
asn_enc_rval_t
ENUMERATED_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
@@ -69,3 +92,14 @@ ENUMERATED_encode_uper(asn_TYPE_descriptor_t *td,
return NativeEnumerated_encode_uper(td, constraints, &value, po);
}
+asn_enc_rval_t
+ENUMERATED_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ ENUMERATED_t *st = (ENUMERATED_t *)sptr;
+ long value;
+
+ if(asn_INTEGER2long(st, &value))
+ _ASN_ENCODE_FAILED;
+
+ return NativeEnumerated_encode_aper(td, constraints, &value, po);
+}
diff --git a/src/GeneralString.c b/src/GeneralString.c
index 01b606b..934b8a2 100644
--- a/src/GeneralString.c
+++ b/src/GeneralString.c
@@ -8,7 +8,7 @@
/*
* GeneralString basic type description.
*/
-static ber_tlv_tag_t asn_DEF_GeneralString_tags[] = {
+static const ber_tlv_tag_t asn_DEF_GeneralString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (27 << 2)), /* [UNIVERSAL 27] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
@@ -24,6 +24,8 @@ asn_TYPE_descriptor_t asn_DEF_GeneralString = {
OCTET_STRING_encode_xer,
OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_GeneralString_tags,
sizeof(asn_DEF_GeneralString_tags)
diff --git a/src/GeneralizedTime.c b/src/GeneralizedTime.c
index 9d683ef..29dcc6c 100644
--- a/src/GeneralizedTime.c
+++ b/src/GeneralizedTime.c
@@ -14,7 +14,7 @@
#include <time.h>
#endif /* __CYGWIN__ */
-#if defined(WIN32)
+#if defined(_WIN32)
#pragma message( "PLEASE STOP AND READ!")
#pragma message( " localtime_r is implemented via localtime(), which may be not thread-safe.")
#pragma message( " gmtime_r is implemented via gmtime(), which may be not thread-safe.")
@@ -41,7 +41,7 @@ static struct tm *gmtime_r(const time_t *tloc, struct tm *result) {
#define putenv(c) _putenv(c)
#define _EMULATE_TIMEGM
-#endif /* WIN32 */
+#endif /* _WIN32 */
#if defined(sun) || defined(_sun_) || defined(__solaris__)
#define _EMULATE_TIMEGM
@@ -67,6 +67,14 @@ static struct tm *gmtime_r(const time_t *tloc, struct tm *result) {
#define GMTOFF(tm) (-timezone)
#endif /* HAVE_TM_GMTOFF */
+#if defined(_WIN32)
+#pragma message( "PLEASE STOP AND READ!")
+#pragma message( " timegm() is implemented via getenv(\"TZ\")/setenv(\"TZ\"), which may be not thread-safe.")
+#pragma message( " ")
+#pragma message( " You must fix the code by inserting appropriate locking")
+#pragma message( " if you want to use asn_GT2time() or asn_UT2time().")
+#pragma message( "PLEASE STOP AND READ!")
+#else
#if (defined(_EMULATE_TIMEGM) || !defined(HAVE_TM_GMTOFF))
#warning "PLEASE STOP AND READ!"
#warning " timegm() is implemented via getenv(\"TZ\")/setenv(\"TZ\"), which may be not thread-safe."
@@ -75,6 +83,7 @@ static struct tm *gmtime_r(const time_t *tloc, struct tm *result) {
#warning " if you want to use asn_GT2time() or asn_UT2time()."
#warning "PLEASE STOP AND READ!"
#endif /* _EMULATE_TIMEGM */
+#endif
/*
* Override our GMTOFF decision for other known platforms.
@@ -128,6 +137,7 @@ static long GMTOFF(struct tm a){
tzset(); \
} while(0); } while(0);
+#ifndef HAVE_TIMEGM
#ifdef _EMULATE_TIMEGM
static time_t timegm(struct tm *tm) {
time_t tloc;
@@ -138,6 +148,7 @@ static time_t timegm(struct tm *tm) {
return tloc;
}
#endif /* _EMULATE_TIMEGM */
+#endif
#ifndef __ASN_INTERNAL_TEST_MODE__
@@ -145,7 +156,7 @@ static time_t timegm(struct tm *tm) {
/*
* GeneralizedTime basic type description.
*/
-static ber_tlv_tag_t asn_DEF_GeneralizedTime_tags[] = {
+static const ber_tlv_tag_t asn_DEF_GeneralizedTime_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (24 << 2)), /* [UNIVERSAL 24] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)), /* [UNIVERSAL 26] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
@@ -167,6 +178,8 @@ asn_TYPE_descriptor_t asn_DEF_GeneralizedTime = {
GeneralizedTime_encode_xer,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_GeneralizedTime_tags,
sizeof(asn_DEF_GeneralizedTime_tags)
@@ -314,13 +327,14 @@ asn_GT2time_prec(const GeneralizedTime_t *st, int *frac_value, int frac_digits,
while(fd > frac_digits)
fv /= 10, fd--;
while(fd < frac_digits) {
- int new_fv = fv * 10;
- if(new_fv / 10 != fv) {
+ if(fv < INT_MAX / 10) {
+ fv *= 10;
+ fd++;
+ } else {
/* Too long precision request */
fv = 0;
break;
}
- fv = new_fv, fd++;
}
*frac_value = fv;
@@ -441,16 +455,15 @@ asn_GT2time_frac(const GeneralizedTime_t *st, int *frac_value, int *frac_digits,
*/
for(buf++; buf < end; buf++) {
int v = *buf;
- int new_fvalue;
+ /* GCC 4.x is being too smart without volatile */
switch(v) {
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
- new_fvalue = fvalue * 10 + (v - 0x30);
- if(new_fvalue / 10 != fvalue) {
- /* Not enough precision, ignore */
- } else {
- fvalue = new_fvalue;
+ if(fvalue < INT_MAX/10) {
+ fvalue = fvalue * 10 + (v - 0x30);
fdigits++;
+ } else {
+ /* Not enough precision, ignore */
}
continue;
default:
diff --git a/src/GraphicString.c b/src/GraphicString.c
index 7d59d52..5f62486 100644
--- a/src/GraphicString.c
+++ b/src/GraphicString.c
@@ -8,7 +8,7 @@
/*
* GraphicString basic type description.
*/
-static ber_tlv_tag_t asn_DEF_GraphicString_tags[] = {
+static const ber_tlv_tag_t asn_DEF_GraphicString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (25 << 2)), /* [UNIVERSAL 25] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
@@ -24,6 +24,8 @@ asn_TYPE_descriptor_t asn_DEF_GraphicString = {
OCTET_STRING_encode_xer, /* Can't expect it to be ASCII/UTF8 */
OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_GraphicString_tags,
sizeof(asn_DEF_GraphicString_tags)
diff --git a/src/IA5String.c b/src/IA5String.c
index 02ecd3e..cec61c3 100644
--- a/src/IA5String.c
+++ b/src/IA5String.c
@@ -8,7 +8,7 @@
/*
* IA5String basic type description.
*/
-static ber_tlv_tag_t asn_DEF_IA5String_tags[] = {
+static const ber_tlv_tag_t asn_DEF_IA5String_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (22 << 2)), /* [UNIVERSAL 22] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
@@ -29,6 +29,8 @@ asn_TYPE_descriptor_t asn_DEF_IA5String = {
OCTET_STRING_encode_xer_utf8,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_IA5String_tags,
sizeof(asn_DEF_IA5String_tags)
diff --git a/src/INTEGER.c b/src/INTEGER.c
index f016131..c74c5b4 100644
--- a/src/INTEGER.c
+++ b/src/INTEGER.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
+ * Copyright (c) 2003-2014 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
@@ -11,7 +11,7 @@
/*
* INTEGER basic type description.
*/
-static ber_tlv_tag_t asn_DEF_INTEGER_tags[] = {
+static const ber_tlv_tag_t asn_DEF_INTEGER_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
};
asn_TYPE_descriptor_t asn_DEF_INTEGER = {
@@ -24,8 +24,17 @@ asn_TYPE_descriptor_t asn_DEF_INTEGER = {
INTEGER_encode_der,
INTEGER_decode_xer,
INTEGER_encode_xer,
+#ifdef ASN_DISABLE_PER_SUPPORT
+ 0,
+ 0,
+ 0,
+ 0,
+#else
INTEGER_decode_uper, /* Unaligned PER decoder */
INTEGER_encode_uper, /* Unaligned PER encoder */
+ INTEGER_decode_aper,
+ INTEGER_encode_aper,
+#endif /* ASN_DISABLE_PER_SUPPORT */
0, /* Use generic outmost tag fetcher */
asn_DEF_INTEGER_tags,
sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
@@ -101,52 +110,35 @@ static const asn_INTEGER_enum_map_t *INTEGER_map_enum2value(asn_INTEGER_specific
* INTEGER specific human-readable output.
*/
static ssize_t
-INTEGER__dump(asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) {
+INTEGER__dump(const asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) {
asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
char scratch[32]; /* Enough for 64-bit integer */
uint8_t *buf = st->buf;
uint8_t *buf_end = st->buf + st->size;
- signed long accum;
+ signed long value;
ssize_t wrote = 0;
char *p;
int ret;
- /*
- * Advance buf pointer until the start of the value's body.
- * This will make us able to process large integers using simple case,
- * when the actual value is small
- * (0x0000000000abcdef would yield a fine 0x00abcdef)
- */
- /* Skip the insignificant leading bytes */
- for(; buf < buf_end-1; buf++) {
- switch(*buf) {
- case 0x00: if((buf[1] & 0x80) == 0) continue; break;
- case 0xff: if((buf[1] & 0x80) != 0) continue; break;
- }
- break;
- }
+ if(specs && specs->field_unsigned)
+ ret = asn_INTEGER2ulong(st, (unsigned long *)&value);
+ else
+ ret = asn_INTEGER2long(st, &value);
/* Simple case: the integer size is small */
- if((size_t)(buf_end - buf) <= sizeof(accum)) {
+ if(ret == 0) {
const asn_INTEGER_enum_map_t *el;
size_t scrsize;
char *scr;
- if(buf == buf_end) {
- accum = 0;
- } else {
- accum = (*buf & 0x80) ? -1 : 0;
- for(; buf < buf_end; buf++)
- accum = (accum << 8) | *buf;
- }
-
- el = INTEGER_map_value2enum(specs, accum);
+ 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,
- "%ld (%s)", accum, el->enum_name);
+ "%ld (%s)", value, el->enum_name);
else
ret = snprintf(scr, scrsize,
"<%s/>", el->enum_name);
@@ -160,7 +152,7 @@ INTEGER__dump(asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_by
scr = scratch;
ret = snprintf(scr, scrsize,
(specs && specs->field_unsigned)
- ?"%lu":"%ld", accum);
+ ?"%lu":"%ld", value);
}
assert(ret > 0 && (size_t)ret < scrsize);
return (cb(scr, ret, app_key) < 0) ? -1 : ret;
@@ -178,7 +170,7 @@ INTEGER__dump(asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_by
/* Output in the long xx:yy:zz... format */
/* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */
for(p = scratch; buf < buf_end; buf++) {
- static const char *h2c = "0123456789ABCDEF";
+ const char * const h2c = "0123456789ABCDEF";
if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) {
/* Flush buffer */
if(cb(scratch, p - scratch, app_key) < 0)
@@ -220,8 +212,8 @@ INTEGER_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
struct e2v_key {
const char *start;
const char *stop;
- asn_INTEGER_enum_map_t *vemap;
- unsigned int *evmap;
+ const asn_INTEGER_enum_map_t *vemap;
+ const unsigned int *evmap;
};
static int
INTEGER__compar_enum2value(const void *kp, const void *am) {
@@ -244,7 +236,7 @@ INTEGER__compar_enum2value(const void *kp, const void *am) {
static const asn_INTEGER_enum_map_t *
INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char *lstart, const char *lstop) {
- asn_INTEGER_enum_map_t *el_found;
+ const asn_INTEGER_enum_map_t *el_found;
int count = specs ? specs->map_count : 0;
struct e2v_key key;
const char *lp;
@@ -319,57 +311,71 @@ INTEGER_st_prealloc(INTEGER_t *st, int min_size) {
static enum xer_pbd_rval
INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) {
INTEGER_t *st = (INTEGER_t *)sptr;
- long sign = 1;
- long value;
+ long dec_value;
+ long hex_value = 0;
const char *lp;
const char *lstart = (const char *)chunk_buf;
const char *lstop = lstart + chunk_size;
enum {
- ST_SKIPSPACE,
+ ST_LEADSPACE,
ST_SKIPSPHEX,
ST_WAITDIGITS,
ST_DIGITS,
+ ST_DIGITS_TRAILSPACE,
ST_HEXDIGIT1,
ST_HEXDIGIT2,
+ ST_HEXDIGITS_TRAILSPACE,
ST_HEXCOLON,
- ST_EXTRASTUFF
- } state = ST_SKIPSPACE;
+ ST_END_ENUM,
+ ST_UNEXPECTED
+ } state = ST_LEADSPACE;
+ const char *dec_value_start = 0; /* INVARIANT: always !0 in ST_DIGITS */
+ const char *dec_value_end = 0;
if(chunk_size)
ASN_DEBUG("INTEGER body %ld 0x%2x..0x%2x",
(long)chunk_size, *lstart, lstop[-1]);
+ if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))
+ return XPBD_SYSTEM_FAILURE;
+
/*
* We may have received a tag here. It will be processed inline.
* Use strtoul()-like code and serialize the result.
*/
- for(value = 0, lp = lstart; lp < lstop; lp++) {
+ for(lp = lstart; lp < lstop; lp++) {
int lv = *lp;
switch(lv) {
case 0x09: case 0x0a: case 0x0d: case 0x20:
switch(state) {
- case ST_SKIPSPACE:
+ case ST_LEADSPACE:
+ case ST_DIGITS_TRAILSPACE:
+ case ST_HEXDIGITS_TRAILSPACE:
case ST_SKIPSPHEX:
continue;
+ case ST_DIGITS:
+ dec_value_end = lp;
+ state = ST_DIGITS_TRAILSPACE;
+ continue;
case ST_HEXCOLON:
- if(xer_is_whitespace(lp, lstop - lp)) {
- lp = lstop - 1;
- continue;
- }
- break;
+ state = ST_HEXDIGITS_TRAILSPACE;
+ continue;
default:
break;
}
break;
case 0x2d: /* '-' */
- if(state == ST_SKIPSPACE) {
- sign = -1;
+ if(state == ST_LEADSPACE) {
+ dec_value = 0;
+ dec_value_start = lp;
state = ST_WAITDIGITS;
continue;
}
break;
case 0x2b: /* '+' */
- if(state == ST_SKIPSPACE) {
+ if(state == ST_LEADSPACE) {
+ dec_value = 0;
+ dec_value_start = lp;
state = ST_WAITDIGITS;
continue;
}
@@ -377,57 +383,41 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
switch(state) {
- case ST_DIGITS: break;
+ case ST_DIGITS: continue;
case ST_SKIPSPHEX: /* Fall through */
case ST_HEXDIGIT1:
- value = (lv - 0x30) << 4;
+ hex_value = (lv - 0x30) << 4;
state = ST_HEXDIGIT2;
continue;
case ST_HEXDIGIT2:
- value += (lv - 0x30);
+ hex_value += (lv - 0x30);
state = ST_HEXCOLON;
- st->buf[st->size++] = (uint8_t)value;
+ st->buf[st->size++] = (uint8_t)hex_value;
continue;
case ST_HEXCOLON:
return XPBD_BROKEN_ENCODING;
- default:
+ case ST_LEADSPACE:
+ dec_value = 0;
+ dec_value_start = lp;
+ /* FALL THROUGH */
+ case ST_WAITDIGITS:
state = ST_DIGITS;
+ continue;
+ default:
break;
}
-
- {
- long new_value = value * 10;
-
- if(new_value / 10 != value)
- /* Overflow */
- return XPBD_DECODER_LIMIT;
-
- value = new_value + (lv - 0x30);
- /* Check for two's complement overflow */
- if(value < 0) {
- /* Check whether it is a LONG_MIN */
- if(sign == -1
- && (unsigned long)value
- == ~((unsigned long)-1 >> 1)) {
- sign = 1;
- } else {
- /* Overflow */
- return XPBD_DECODER_LIMIT;
- }
- }
- }
- continue;
- case 0x3c: /* '<' */
- if(state == ST_SKIPSPACE) {
+ break;
+ case 0x3c: /* '<', start of XML encoded enumeration */
+ if(state == ST_LEADSPACE) {
const asn_INTEGER_enum_map_t *el;
el = INTEGER_map_enum2value(
(asn_INTEGER_specifics_t *)
td->specifics, lstart, lstop);
if(el) {
- ASN_DEBUG("Found \"%s\" => %ld",
+ ASN_DEBUG("Found \"%s\" => %lld",
el->enum_name, el->nat_value);
- state = ST_DIGITS;
- value = el->nat_value;
+ dec_value = el->nat_value;
+ state = ST_END_ENUM;
lp = lstop - 1;
continue;
}
@@ -445,13 +435,12 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
* places as a decimal value.
* Switch decoding mode. */
ASN_DEBUG("INTEGER re-evaluate as hex form");
- if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))
- return XPBD_SYSTEM_FAILURE;
state = ST_SKIPSPHEX;
+ dec_value_start = 0;
lp = lstart - 1;
continue;
} else {
- ASN_DEBUG("state %d at %d", state, lp - lstart);
+ ASN_DEBUG("state %d at %ld", state, (long)(lp - lstart));
break;
}
/* [A-Fa-f] */
@@ -459,24 +448,23 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66:
switch(state) {
case ST_SKIPSPHEX:
- case ST_SKIPSPACE: /* Fall through */
+ case ST_LEADSPACE: /* Fall through */
case ST_HEXDIGIT1:
- value = lv - ((lv < 0x61) ? 0x41 : 0x61);
- value += 10;
- value <<= 4;
+ hex_value = lv - ((lv < 0x61) ? 0x41 : 0x61);
+ hex_value += 10;
+ hex_value <<= 4;
state = ST_HEXDIGIT2;
continue;
case ST_HEXDIGIT2:
- value += lv - ((lv < 0x61) ? 0x41 : 0x61);
- value += 10;
- st->buf[st->size++] = (uint8_t)value;
+ hex_value += lv - ((lv < 0x61) ? 0x41 : 0x61);
+ hex_value += 10;
+ st->buf[st->size++] = (uint8_t)hex_value;
state = ST_HEXCOLON;
continue;
case ST_DIGITS:
ASN_DEBUG("INTEGER re-evaluate as hex form");
- if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))
- return XPBD_SYSTEM_FAILURE;
state = ST_SKIPSPHEX;
+ dec_value_start = 0;
lp = lstart - 1;
continue;
default:
@@ -486,39 +474,54 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
}
/* Found extra non-numeric stuff */
- ASN_DEBUG("Found non-numeric 0x%2x at %d",
- lv, lp - lstart);
- state = ST_EXTRASTUFF;
+ ASN_DEBUG("INTEGER :: Found non-numeric 0x%2x at %ld",
+ lv, (long)(lp - lstart));
+ state = ST_UNEXPECTED;
break;
}
switch(state) {
+ case ST_END_ENUM:
+ /* Got a complete and valid enumeration encoded as a tag. */
+ break;
case ST_DIGITS:
- /* Everything is cool */
+ dec_value_end = lstop;
+ /* FALL THROUGH */
+ case ST_DIGITS_TRAILSPACE:
+ /* The last symbol encountered was a digit. */
+ switch(asn_strtol_lim(dec_value_start, &dec_value_end, &dec_value)) {
+ case ASN_STRTOL_OK:
+ break;
+ case ASN_STRTOL_ERROR_RANGE:
+ return XPBD_DECODER_LIMIT;
+ case ASN_STRTOL_ERROR_INVAL:
+ case ASN_STRTOL_EXPECT_MORE:
+ case ASN_STRTOL_EXTRA_DATA:
+ return XPBD_BROKEN_ENCODING;
+ }
break;
case ST_HEXCOLON:
+ case ST_HEXDIGITS_TRAILSPACE:
st->buf[st->size] = 0; /* Just in case termination */
return XPBD_BODY_CONSUMED;
case ST_HEXDIGIT1:
case ST_HEXDIGIT2:
case ST_SKIPSPHEX:
return XPBD_BROKEN_ENCODING;
- default:
- if(xer_is_whitespace(lp, lstop - lp)) {
- if(state != ST_EXTRASTUFF)
- return XPBD_NOT_BODY_IGNORE;
- break;
- } else {
- ASN_DEBUG("INTEGER: No useful digits (state %d)",
- state);
- return XPBD_BROKEN_ENCODING; /* No digits */
- }
- break;
+ case ST_LEADSPACE:
+ /* Content not found */
+ return XPBD_NOT_BODY_IGNORE;
+ case ST_WAITDIGITS:
+ case ST_UNEXPECTED:
+ ASN_DEBUG("INTEGER: No useful digits (state %d)", state);
+ return XPBD_BROKEN_ENCODING; /* No digits */
}
- value *= sign; /* Change sign, if needed */
-
- if(asn_long2INTEGER(st, value))
+ /*
+ * Convert the result of parsing of enumeration or a straight
+ * decimal value into a BER representation.
+ */
+ if(asn_long2INTEGER(st, dec_value))
return XPBD_SYSTEM_FAILURE;
return XPBD_BODY_CONSUMED;
@@ -553,6 +556,8 @@ INTEGER_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
_ASN_ENCODED_OK(er);
}
+#ifndef ASN_DISABLE_PER_SUPPORT
+
asn_dec_rval_t
INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
@@ -594,31 +599,179 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
}
}
+ /* X.691-2008/11, #13.2.2, constrained whole number */
+ if(ct && ct->flags != APC_UNCONSTRAINED) {
+ /* #11.5.6 */
+ ASN_DEBUG("Integer with range %d bits", ct->range_bits);
+ if(ct->range_bits >= 0) {
+ if((size_t)ct->range_bits > 8 * sizeof(unsigned long))
+ _ASN_DECODE_FAILED;
+
+ if(specs && specs->field_unsigned) {
+ unsigned long uvalue;
+ if(uper_get_constrained_whole_number(pd,
+ &uvalue, ct->range_bits))
+ _ASN_DECODE_STARVED;
+ ASN_DEBUG("Got value %lu + low %lld",
+ uvalue, ct->lower_bound);
+ uvalue += ct->lower_bound;
+ if(asn_ulong2INTEGER(st, uvalue))
+ _ASN_DECODE_FAILED;
+ } else {
+ unsigned long svalue;
+ if(uper_get_constrained_whole_number(pd,
+ &svalue, ct->range_bits))
+ _ASN_DECODE_STARVED;
+ ASN_DEBUG("Got value %ld + low %ld",
+ svalue, ct->lower_bound);
+ svalue += ct->lower_bound;
+ if(asn_long2INTEGER(st, svalue))
+ _ASN_DECODE_FAILED;
+ }
+ return rval;
+ }
+ } else {
+ ASN_DEBUG("Decoding unconstrained integer %s", td->name);
+ }
+
+ /* X.691, #12.2.3, #12.2.4 */
+ do {
+ ssize_t len;
+ void *p;
+ int ret;
+
+ /* Get the PER length */
+ len = uper_get_length(pd, -1, &repeat);
+ if(len < 0) _ASN_DECODE_STARVED;
+
+ p = REALLOC(st->buf, st->size + len + 1);
+ if(!p) _ASN_DECODE_FAILED;
+ st->buf = (uint8_t *)p;
+
+ ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
+ if(ret < 0) _ASN_DECODE_STARVED;
+ st->size += len;
+ } while(repeat);
+ st->buf[st->size] = 0; /* JIC */
+
+ /* #12.2.3 */
+ if(ct && ct->lower_bound) {
+ /*
+ * TODO: replace by in-place arithmetics.
+ */
+ long value;
+ if(asn_INTEGER2long(st, &value))
+ _ASN_DECODE_FAILED;
+ if(asn_long2INTEGER(st, value + ct->lower_bound))
+ _ASN_DECODE_FAILED;
+ }
+
+ return rval;
+}
+
+asn_dec_rval_t
+INTEGER_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+ asn_dec_rval_t rval = { RC_OK, 0 };
+ INTEGER_t *st = (INTEGER_t *)*sptr;
+ asn_per_constraint_t *ct;
+ int repeat;
+
+ (void)opt_codec_ctx;
+
+ if(!st) {
+ st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
+ if(!st) _ASN_DECODE_FAILED;
+ }
+
+ if(!constraints) constraints = td->per_constraints;
+ ct = constraints ? &constraints->value : 0;
+
+ if(ct && ct->flags & APC_EXTENSIBLE) {
+ int inext = per_get_few_bits(pd, 1);
+ if(inext < 0) _ASN_DECODE_STARVED;
+ if(inext) ct = 0;
+ }
+
+ FREEMEM(st->buf);
+ st->buf = 0;
+ st->size = 0;
+ if(ct) {
+ if(ct->flags & APC_SEMI_CONSTRAINED) {
+ st->buf = (uint8_t *)CALLOC(1, 2);
+ if(!st->buf) _ASN_DECODE_FAILED;
+ st->size = 1;
+ } else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {
+ size_t size = (ct->range_bits + 7) >> 3;
+ st->buf = (uint8_t *)MALLOC(1 + size + 1);
+ if(!st->buf) _ASN_DECODE_FAILED;
+ st->size = size;
+ }
+ }
+
/* X.691, #12.2.2 */
if(ct && ct->flags != APC_UNCONSTRAINED) {
/* #10.5.6 */
ASN_DEBUG("Integer with range %d bits", ct->range_bits);
if(ct->range_bits >= 0) {
- long value;
- if(ct->range_bits == 32) {
- long lhalf;
- value = per_get_few_bits(pd, 16);
- if(value < 0) _ASN_DECODE_STARVED;
- lhalf = per_get_few_bits(pd, 16);
- if(lhalf < 0) _ASN_DECODE_STARVED;
- value = (value << 16) | lhalf;
+ if (ct->range_bits > 16) {
+ int max_range_bytes = (ct->range_bits >> 3) + 1;
+ int length, i;
+ int64_t value = 0;
+
+ for (i = 0; i < max_range_bytes; i++) {
+ int upper = 1 << (i + 1);
+ if (upper > max_range_bytes)
+ break;
+ }
+ if ((length = per_get_few_bits(pd, i + 1)) < 0)
+ _ASN_DECODE_STARVED;
+ if (aper_get_align(pd) != 0)
+ _ASN_DECODE_STARVED;
+ ASN_DEBUG("Got length %d", length + 1);
+ for (i = 0; i < length + 1; i++) {
+ int buf = per_get_few_bits(pd, 8);
+ if (buf < 0)
+ _ASN_DECODE_STARVED;
+ value += (((int64_t)buf) << (8 * i));
+ }
+
+ if((specs && specs->field_unsigned)
+ ? asn_uint642INTEGER(st, value)
+ : asn_int642INTEGER(st, value))
+ _ASN_DECODE_FAILED;
+ ASN_DEBUG("Got value %lld + low %lld",
+ value, ct->lower_bound);
+ value += ct->lower_bound;
} else {
- value = per_get_few_bits(pd, ct->range_bits);
- if(value < 0) _ASN_DECODE_STARVED;
+ long value = 0;
+ if (ct->range_bits < 8) {
+ value = per_get_few_bits(pd, ct->range_bits);
+ if(value < 0) _ASN_DECODE_STARVED;
+ } else if (ct->range_bits == 8) {
+ if (aper_get_align(pd) < 0)
+ _ASN_DECODE_FAILED;
+ value = per_get_few_bits(pd, ct->range_bits);
+ if(value < 0) _ASN_DECODE_STARVED;
+ } else {
+ /* Align */
+ if (aper_get_align(pd) < 0)
+ _ASN_DECODE_FAILED;
+ value = per_get_few_bits(pd, 16);
+ if(value < 0) _ASN_DECODE_STARVED;
+ }
+ if((specs && specs->field_unsigned)
+ ? asn_ulong2INTEGER(st, value)
+ : asn_long2INTEGER(st, value))
+ _ASN_DECODE_FAILED;
+ ASN_DEBUG("Got value %ld + low %lld",
+ value, ct->lower_bound);
+ value += ct->lower_bound;
}
- ASN_DEBUG("Got value %ld + low %ld",
- value, ct->lower_bound);
- value += ct->lower_bound;
- if((specs && specs->field_unsigned)
- ? asn_ulong2INTEGER(st, value)
- : asn_long2INTEGER(st, value))
- _ASN_DECODE_FAILED;
return rval;
+ } else {
+ _ASN_DECODE_FAILED;
}
} else {
ASN_DEBUG("Decoding unconstrained integer %s", td->name);
@@ -631,7 +784,7 @@ INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
int ret;
/* Get the PER length */
- len = uper_get_length(pd, -1, &repeat);
+ len = aper_get_length(pd, -1, -1, &repeat);
if(len < 0) _ASN_DECODE_STARVED;
p = REALLOC(st->buf, st->size + len + 1);
@@ -692,7 +845,7 @@ INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
|| uval > (unsigned long)ct->upper_bound)
inext = 1;
}
- ASN_DEBUG("Value %lu (%02x/%d) lb %lu ub %lu %s",
+ ASN_DEBUG("Value %lu (%02x/%d) lb %llu ub %llu %s",
uval, st->buf[0], st->size,
ct->lower_bound, ct->upper_bound,
inext ? "ext" : "fix");
@@ -709,7 +862,7 @@ INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
|| value > ct->upper_bound)
inext = 1;
}
- ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld %s",
+ ASN_DEBUG("Value %ld (%02x/%d) lb %lld ub %lld %s",
value, st->buf[0], st->size,
ct->lower_bound, ct->upper_bound,
inext ? "ext" : "fix");
@@ -724,33 +877,148 @@ INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
}
+ /* X.691-11/2008, #13.2.2, test if constrained whole number */
+ if(ct && ct->range_bits >= 0) {
+ /* #11.5.6 -> #11.3 */
+ ASN_DEBUG("Encoding integer %ld (%lu) with range %d bits",
+ value, value - ct->lower_bound, ct->range_bits);
+ unsigned long v = value - ct->lower_bound;
+ if(uper_put_constrained_whole_number_u(po, v, ct->range_bits))
+ _ASN_ENCODE_FAILED;
+ _ASN_ENCODED_OK(er);
+ }
+
+ if(ct && ct->lower_bound) {
+ ASN_DEBUG("Adjust lower bound to %lld", ct->lower_bound);
+ /* TODO: adjust lower bound */
+ _ASN_ENCODE_FAILED;
+ }
+
+ for(buf = st->buf, end = st->buf + st->size; buf < end;) {
+ ssize_t mayEncode = uper_put_length(po, end - buf);
+ if(mayEncode < 0)
+ _ASN_ENCODE_FAILED;
+ if(per_put_many_bits(po, buf, 8 * mayEncode))
+ _ASN_ENCODE_FAILED;
+ buf += mayEncode;
+ }
+
+ _ASN_ENCODED_OK(er);
+}
+
+asn_enc_rval_t
+INTEGER_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+ asn_enc_rval_t er;
+ INTEGER_t *st = (INTEGER_t *)sptr;
+ const uint8_t *buf;
+ const uint8_t *end;
+ asn_per_constraint_t *ct;
+ int64_t value = 0;
+
+ if(!st || st->size == 0) _ASN_ENCODE_FAILED;
+
+ if(!constraints) constraints = td->per_constraints;
+ ct = constraints ? &constraints->value : 0;
+
+ er.encoded = 0;
+
+ if(ct) {
+ int inext = 0;
+ if(specs && specs->field_unsigned) {
+ uint64_t uval;
+ if(asn_INTEGER2uint64(st, &uval))
+ _ASN_ENCODE_FAILED;
+ /* Check proper range */
+ if(ct->flags & APC_SEMI_CONSTRAINED) {
+ if(uval < (unsigned long long)ct->lower_bound)
+ inext = 1;
+ } else if(ct->range_bits >= 0) {
+ if(uval < (unsigned long long)ct->lower_bound
+ || uval > (unsigned long long)ct->upper_bound)
+ inext = 1;
+ }
+ ASN_DEBUG("Value %llu (%02x/%d) lb %llu ub %llu %s",
+ uval, st->buf[0], st->size,
+ ct->lower_bound, ct->upper_bound,
+ inext ? "ext" : "fix");
+ value = uval;
+ } else {
+ if(asn_INTEGER2int64(st, &value)) _ASN_ENCODE_FAILED;
+ /* Check proper range */
+ if(ct->flags & APC_SEMI_CONSTRAINED) {
+ if(value < ct->lower_bound)
+ inext = 1;
+ } else if(ct->range_bits >= 0) {
+ if(value < ct->lower_bound
+ || value > ct->upper_bound)
+ inext = 1;
+ }
+ ASN_DEBUG("Value %lld (%02x/%d) lb %lld ub %lld %s",
+ value, st->buf[0], st->size,
+ ct->lower_bound, ct->upper_bound,
+ inext ? "ext" : "fix");
+ }
+ if(ct->flags & APC_EXTENSIBLE) {
+ if(per_put_few_bits(po, inext, 1))
+ _ASN_ENCODE_FAILED;
+ if(inext) ct = 0;
+ } else if(inext) {
+ _ASN_ENCODE_FAILED;
+ }
+ }
+
/* X.691, #12.2.2 */
if(ct && ct->range_bits >= 0) {
/* #10.5.6 */
ASN_DEBUG("Encoding integer with range %d bits",
- ct->range_bits);
- if(ct->range_bits == 32) {
- /* TODO: extend to >32 bits */
- long v = value - ct->lower_bound;
- if(per_put_few_bits(po, v >> 1, 31)
- || per_put_few_bits(po, v, 1))
+ ct->range_bits);
+
+ /* #12 <= 8 -> alignment ? */
+ if (ct->range_bits < 8) {
+ if(per_put_few_bits(po, 0x00 | value, ct->range_bits))
+ _ASN_ENCODE_FAILED;
+ } else if (ct->range_bits == 8) {
+ if(aper_put_align(po) < 0)
+ _ASN_ENCODE_FAILED;
+ if(per_put_few_bits(po, 0x00 | value, ct->range_bits))
+ _ASN_ENCODE_FAILED;
+ } else if (ct->range_bits <= 16) {
+ // Consume the bytes to align on octet
+ if(aper_put_align(po) < 0)
+ _ASN_ENCODE_FAILED;
+ if(per_put_few_bits(po, 0x0000 | value,
+ 16))
_ASN_ENCODE_FAILED;
} else {
- if(per_put_few_bits(po, value - ct->lower_bound,
- ct->range_bits))
+ /* TODO: extend to >64 bits */
+ int64_t v = value;
+ int i;
+
+ /* Putting length - 1 in the minimum number of bits ex: 5 = 3bits */
+ if (per_put_few_bits(po, st->size - 1, (ct->range_bits >> 3)-1))
+ _ASN_ENCODE_FAILED;
+
+ // Consume the bits to align on octet
+ if (aper_put_align(po) < 0)
_ASN_ENCODE_FAILED;
+ /* Put the value */
+ for (i = 0; i < st->size; i++) {
+ if(per_put_few_bits(po, (v >> (8 * (st->size - i - 1))) & 0xff, 8)) _ASN_ENCODE_FAILED;
+ }
}
_ASN_ENCODED_OK(er);
}
if(ct && ct->lower_bound) {
- ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);
+ ASN_DEBUG("Adjust lower bound to %lld", ct->lower_bound);
/* TODO: adjust lower bound */
_ASN_ENCODE_FAILED;
}
for(buf = st->buf, end = st->buf + st->size; buf < end;) {
- ssize_t mayEncode = uper_put_length(po, end - buf);
+ ssize_t mayEncode = aper_put_length(po, -1, end - buf);
if(mayEncode < 0)
_ASN_ENCODE_FAILED;
if(per_put_many_bits(po, buf, 8 * mayEncode))
@@ -761,6 +1029,8 @@ INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
_ASN_ENCODED_OK(er);
}
+#endif /* ASN_DISABLE_PER_SUPPORT */
+
int
asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
uint8_t *b, *end;
@@ -822,6 +1092,66 @@ asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
}
int
+asn_INTEGER2int64(const INTEGER_t *iptr, int64_t *lptr) {
+ uint8_t *b, *end;
+ size_t size;
+ int64_t l;
+
+ /* Sanity checking */
+ if(!iptr || !iptr->buf || !lptr) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Cache the begin/end of the buffer */
+ b = iptr->buf; /* Start of the INTEGER buffer */
+ size = iptr->size;
+ end = b + size; /* Where to stop */
+
+ if(size > sizeof(int64_t)) {
+ uint8_t *end1 = end - 1;
+ /*
+ * Slightly more advanced processing,
+ * able to >sizeof(int64_t) bytes,
+ * when the actual value is small
+ * (0x0000000000abcdef would yield a fine 0x00abcdef)
+ */
+ /* Skip out the insignificant leading bytes */
+ for(; b < end1; b++) {
+ switch(*b) {
+ case 0x00: if((b[1] & 0x80) == 0) continue; break;
+ case 0xff: if((b[1] & 0x80) != 0) continue; break;
+ }
+ break;
+ }
+
+ size = end - b;
+ if(size > sizeof(int64_t)) {
+ /* Still cannot fit the int64_t */
+ errno = ERANGE;
+ return -1;
+ }
+ }
+
+ /* Shortcut processing of a corner case */
+ if(end == b) {
+ *lptr = 0;
+ return 0;
+ }
+
+ /* Perform the sign initialization */
+ /* Actually l = -(*b >> 7); gains nothing, yet unreadable! */
+ if((*b >> 7)) l = -1; else l = 0;
+
+ /* Conversion engine */
+ for(; b < end; b++)
+ l = (l << 8) | *b;
+
+ *lptr = l;
+ return 0;
+}
+
+int
asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *lptr) {
uint8_t *b, *end;
unsigned long l;
@@ -854,6 +1184,38 @@ asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *lptr) {
}
int
+asn_INTEGER2uint64(const INTEGER_t *iptr, uint64_t *lptr) {
+ uint8_t *b, *end;
+ uint64_t l;
+ size_t size;
+
+ if(!iptr || !iptr->buf || !lptr) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ b = iptr->buf;
+ size = iptr->size;
+ end = b + size;
+
+ /* If all extra leading bytes are zeroes, ignore them */
+ for(; size > sizeof(uint64_t); b++, size--) {
+ if(*b) {
+ /* Value won't fit unsigned long */
+ errno = ERANGE;
+ return -1;
+ }
+ }
+
+ /* Conversion engine */
+ for(l = 0; b < end; b++)
+ l = (l << 8) | *b;
+
+ *lptr = l;
+ return 0;
+}
+
+int
asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
uint8_t *buf;
uint8_t *end;
@@ -879,6 +1241,86 @@ asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
}
int
+asn_uint642INTEGER(INTEGER_t *st, uint64_t value) {
+ uint8_t *buf;
+ uint8_t *end;
+ uint8_t *b;
+ int shr;
+
+ if(value <= INT64_MAX)
+ return asn_int642INTEGER(st, value);
+
+ buf = (uint8_t *)MALLOC(1 + sizeof(value));
+ if(!buf) return -1;
+
+ end = buf + (sizeof(value) + 1);
+ buf[0] = 0;
+ for(b = buf + 1, shr = (sizeof(value)-1)*8; b < end; shr -= 8, b++)
+ *b = (uint8_t)(value >> shr);
+
+ if(st->buf) FREEMEM(st->buf);
+ st->buf = buf;
+ st->size = 1 + sizeof(value);
+
+ return 0;
+}
+
+int
+asn_int642INTEGER(INTEGER_t *st, int64_t value) {
+ uint8_t *buf, *bp;
+ uint8_t *p;
+ uint8_t *pstart;
+ uint8_t *pend1;
+ int littleEndian = 1; /* Run-time detection */
+ int add;
+
+ if(!st) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ buf = (uint8_t *)MALLOC(sizeof(value));
+ if(!buf) return -1;
+
+ if(*(char *)&littleEndian) {
+ pstart = (uint8_t *)&value + sizeof(value) - 1;
+ pend1 = (uint8_t *)&value;
+ add = -1;
+ } else {
+ pstart = (uint8_t *)&value;
+ pend1 = pstart + sizeof(value) - 1;
+ add = 1;
+ }
+
+ /*
+ * If the contents octet consists of more than one octet,
+ * then bits of the first octet and bit 8 of the second octet:
+ * a) shall not all be ones; and
+ * b) shall not all be zero.
+ */
+ for(p = pstart; p != pend1; p += add) {
+ switch(*p) {
+ case 0x00: if((*(p+add) & 0x80) == 0)
+ continue;
+ break;
+ case 0xff: if((*(p+add) & 0x80))
+ continue;
+ break;
+ }
+ break;
+ }
+ /* Copy the integer body */
+ for(pstart = p, bp = buf, pend1 += add; p != pend1; p += add)
+ *bp++ = *p;
+
+ if(st->buf) FREEMEM(st->buf);
+ st->buf = buf;
+ st->size = bp - buf;
+
+ return 0;
+}
+
+int
asn_long2INTEGER(INTEGER_t *st, long value) {
uint8_t *buf, *bp;
uint8_t *p;
@@ -932,3 +1374,92 @@ asn_long2INTEGER(INTEGER_t *st, long value) {
return 0;
}
+
+/*
+ * This function is going to be DEPRECATED soon.
+ */
+enum asn_strtol_result_e
+asn_strtol(const char *str, const char *end, long *lp) {
+ const char *endp = end;
+
+ switch(asn_strtol_lim(str, &endp, lp)) {
+ case ASN_STRTOL_ERROR_RANGE:
+ return ASN_STRTOL_ERROR_RANGE;
+ case ASN_STRTOL_ERROR_INVAL:
+ return ASN_STRTOL_ERROR_INVAL;
+ case ASN_STRTOL_EXPECT_MORE:
+ return ASN_STRTOL_ERROR_INVAL; /* Retain old behavior */
+ case ASN_STRTOL_OK:
+ return ASN_STRTOL_OK;
+ case ASN_STRTOL_EXTRA_DATA:
+ return ASN_STRTOL_ERROR_INVAL; /* Retain old behavior */
+ }
+
+ return ASN_STRTOL_ERROR_INVAL; /* Retain old behavior */
+}
+
+/*
+ * Parse the number in the given string until the given *end position,
+ * returning the position after the last parsed character back using the
+ * same (*end) pointer.
+ * WARNING: This behavior is different from the standard strtol(3).
+ */
+enum asn_strtol_result_e
+asn_strtol_lim(const char *str, const char **end, long *lp) {
+ int sign = 1;
+ long l;
+
+ const long upper_boundary = LONG_MAX / 10;
+ long last_digit_max = LONG_MAX % 10;
+
+ if(str >= *end) return ASN_STRTOL_ERROR_INVAL;
+
+ switch(*str) {
+ case '-':
+ last_digit_max++;
+ sign = -1;
+ case '+':
+ str++;
+ if(str >= *end) {
+ *end = str;
+ return ASN_STRTOL_EXPECT_MORE;
+ }
+ }
+
+ for(l = 0; str < (*end); str++) {
+ switch(*str) {
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
+ case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: {
+ int d = *str - '0';
+ if(l < upper_boundary) {
+ l = l * 10 + d;
+ } else if(l == upper_boundary) {
+ if(d <= last_digit_max) {
+ if(sign > 0) {
+ l = l * 10 + d;
+ } else {
+ sign = 1;
+ l = -l * 10 - d;
+ }
+ } else {
+ *end = str;
+ return ASN_STRTOL_ERROR_RANGE;
+ }
+ } else {
+ *end = str;
+ return ASN_STRTOL_ERROR_RANGE;
+ }
+ }
+ continue;
+ default:
+ *end = str;
+ *lp = sign * l;
+ return ASN_STRTOL_EXTRA_DATA;
+ }
+ }
+
+ *end = str;
+ *lp = sign * l;
+ return ASN_STRTOL_OK;
+}
+
diff --git a/src/ISO646String.c b/src/ISO646String.c
index d6ded0e..a6cc761 100644
--- a/src/ISO646String.c
+++ b/src/ISO646String.c
@@ -8,7 +8,7 @@
/*
* ISO646String basic type description.
*/
-static ber_tlv_tag_t asn_DEF_ISO646String_tags[] = {
+static const ber_tlv_tag_t asn_DEF_ISO646String_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)), /* [UNIVERSAL 26] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
@@ -29,6 +29,8 @@ asn_TYPE_descriptor_t asn_DEF_ISO646String = {
OCTET_STRING_encode_xer_utf8,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_ISO646String_tags,
sizeof(asn_DEF_ISO646String_tags)
diff --git a/src/Makefile.am b/src/Makefile.am
index 1bbcfc5..633cc04 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,7 @@
# This is _NOT_ the library release version, it's an API version.
# Please read Chapter 6 "Library interface versions" of the libtool
# documentation before making any modification
-LIBVERSION=0:0:0
+LIBVERSION=1:0:0
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include/asn1c
AM_CFLAGS = -fPIC -Wall $(LIBOSMOCORE_CFLAGS)
diff --git a/src/NULL.c b/src/NULL.c
index 6d3316f..f514ca2 100644
--- a/src/NULL.c
+++ b/src/NULL.c
@@ -10,7 +10,7 @@
/*
* NULL basic type description.
*/
-static ber_tlv_tag_t asn_DEF_NULL_tags[] = {
+static const ber_tlv_tag_t asn_DEF_NULL_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (5 << 2))
};
asn_TYPE_descriptor_t asn_DEF_NULL = {
@@ -25,6 +25,8 @@ asn_TYPE_descriptor_t asn_DEF_NULL = {
NULL_encode_xer,
NULL_decode_uper, /* Unaligned PER decoder */
NULL_encode_uper, /* Unaligned PER encoder */
+ NULL_decode_aper, /* Aligned PER decoder */
+ NULL_encode_aper, /* Aligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_NULL_tags,
sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]),
@@ -73,11 +75,15 @@ static enum xer_pbd_rval
NULL__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) {
(void)td;
(void)sptr;
+ (void)chunk_buf; /* Going to be empty according to the rules below. */
- if(xer_is_whitespace(chunk_buf, chunk_size))
- return XPBD_BODY_CONSUMED;
- else
+ /*
+ * There must be no content in self-terminating <NULL/> tag.
+ */
+ if(chunk_size)
return XPBD_BROKEN_ENCODING;
+ else
+ return XPBD_BODY_CONSUMED;
}
asn_dec_rval_t
@@ -132,6 +138,34 @@ NULL_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
return rv;
}
+asn_dec_rval_t
+NULL_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_dec_rval_t rv;
+
+ (void)opt_codec_ctx;
+ (void)td;
+ (void)constraints;
+ (void)pd;
+
+ if(!*sptr) {
+ *sptr = MALLOC(sizeof(NULL_t));
+ if(*sptr) {
+ *(NULL_t *)*sptr = 0;
+ } else {
+ _ASN_DECODE_FAILED;
+ }
+ }
+
+ /*
+ * NULL type does not have content octets.
+ */
+
+ rv.code = RC_OK;
+ rv.consumed = 0;
+ return rv;
+}
+
asn_enc_rval_t
NULL_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
void *sptr, asn_per_outp_t *po) {
@@ -145,3 +179,17 @@ NULL_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
er.encoded = 0;
_ASN_ENCODED_OK(er);
}
+
+asn_enc_rval_t
+NULL_encode_aper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+ void *sptr, asn_per_outp_t *po) {
+ asn_enc_rval_t er;
+
+ (void)td;
+ (void)constraints;
+ (void)sptr;
+ (void)po;
+
+ er.encoded = 0;
+ _ASN_ENCODED_OK(er);
+}
diff --git a/src/NativeEnumerated.c b/src/NativeEnumerated.c
index 3184644..124e7f0 100644
--- a/src/NativeEnumerated.c
+++ b/src/NativeEnumerated.c
@@ -15,7 +15,7 @@
/*
* NativeEnumerated basic type description.
*/
-static ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
+static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
};
asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
@@ -30,6 +30,8 @@ asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
NativeEnumerated_encode_xer,
NativeEnumerated_decode_uper,
NativeEnumerated_encode_uper,
+ NativeEnumerated_decode_aper,
+ NativeEnumerated_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_NativeEnumerated_tags,
sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
@@ -125,6 +127,61 @@ NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
return rval;
}
+asn_dec_rval_t
+NativeEnumerated_decode_aper(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+ void **sptr, asn_per_data_t *pd) {
+ asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
+ asn_dec_rval_t rval = { RC_OK, 0 };
+ long *native = (long *)*sptr;
+ asn_per_constraint_t *ct;
+ long value;
+
+ (void)opt_codec_ctx;
+
+ if(constraints) ct = &constraints->value;
+ else if(td->per_constraints) ct = &td->per_constraints->value;
+ else _ASN_DECODE_FAILED; /* Mandatory! */
+ if(!specs) _ASN_DECODE_FAILED;
+
+ if(!native) {
+ native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
+ if(!native) _ASN_DECODE_FAILED;
+ }
+
+ ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
+
+ if(ct->flags & APC_EXTENSIBLE) {
+ int inext = per_get_few_bits(pd, 1);
+ if(inext < 0) _ASN_DECODE_STARVED;
+ if(inext) ct = 0;
+ }
+
+ if(ct && ct->range_bits >= 0) {
+ value = per_get_few_bits(pd, ct->range_bits);
+ if(value < 0) _ASN_DECODE_STARVED;
+ if(value >= (specs->extension
+ ? specs->extension - 1 : specs->map_count))
+ _ASN_DECODE_FAILED;
+ } else {
+ if(!specs->extension)
+ _ASN_DECODE_FAILED;
+ /*
+ * X.691, #10.6: normally small non-negative whole number;
+ */
+ value = uper_get_nsnnwn(pd);
+ if(value < 0) _ASN_DECODE_STARVED;
+ value += specs->extension - 1;
+ if(value >= specs->map_count)
+ _ASN_DECODE_FAILED;
+ }
+
+ *native = specs->value2enum[value].nat_value;
+ ASN_DEBUG("Decoded %s = %ld", td->name, *native);
+
+ return rval;
+}
+
static int
NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
const asn_INTEGER_enum_map_t *a = ap;
@@ -145,7 +202,7 @@ NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraint_t *ct;
int inext = 0;
asn_INTEGER_enum_map_t key;
- asn_INTEGER_enum_map_t *kf;
+ const asn_INTEGER_enum_map_t *kf;
if(!sptr) _ASN_ENCODE_FAILED;
if(!specs) _ASN_ENCODE_FAILED;
@@ -205,6 +262,75 @@ NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td,
_ASN_ENCODED_OK(er);
}
+asn_enc_rval_t
+NativeEnumerated_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
+ asn_enc_rval_t er;
+ long native, value;
+ asn_per_constraint_t *ct;
+ int inext = 0;
+ asn_INTEGER_enum_map_t key;
+ asn_INTEGER_enum_map_t *kf;
+
+ if(!sptr) _ASN_ENCODE_FAILED;
+ if(!specs) _ASN_ENCODE_FAILED;
+
+ if(constraints) ct = &constraints->value;
+ else if(td->per_constraints) ct = &td->per_constraints->value;
+ else _ASN_ENCODE_FAILED; /* Mandatory! */
+
+ ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
+
+ er.encoded = 0;
+
+ native = *(long *)sptr;
+ if(native < 0) _ASN_ENCODE_FAILED;
+
+ key.nat_value = native;
+ kf = bsearch(&key, specs->value2enum, specs->map_count,
+ sizeof(key), NativeEnumerated__compar_value2enum);
+ if(!kf) {
+ ASN_DEBUG("No element corresponds to %ld", native);
+ _ASN_ENCODE_FAILED;
+ }
+ value = kf - specs->value2enum;
+
+ if(ct->range_bits >= 0) {
+ int cmpWith = specs->extension
+ ? specs->extension - 1 : specs->map_count;
+ if(value >= cmpWith)
+ inext = 1;
+ }
+ if(ct->flags & APC_EXTENSIBLE) {
+ if(per_put_few_bits(po, inext, 1))
+ _ASN_ENCODE_FAILED;
+ if(inext) ct = 0;
+ } else if(inext) {
+ _ASN_ENCODE_FAILED;
+ }
+
+ if(ct && ct->range_bits >= 0) {
+ if(per_put_few_bits(po, value, ct->range_bits))
+ _ASN_ENCODE_FAILED;
+ _ASN_ENCODED_OK(er);
+ }
+
+ if(!specs->extension)
+ _ASN_ENCODE_FAILED;
+
+ /*
+ * X.691, #10.6: normally small non-negative whole number;
+ */
+ ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
+ value, specs->extension, inext,
+ value - (inext ? (specs->extension - 1) : 0));
+ if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
+ _ASN_ENCODE_FAILED;
+
+ _ASN_ENCODED_OK(er);
+}
+
int
NativeEnumerated_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
diff --git a/src/NativeInteger.c b/src/NativeInteger.c
index abdb71a..ef17bee 100644
--- a/src/NativeInteger.c
+++ b/src/NativeInteger.c
@@ -16,7 +16,7 @@
/*
* NativeInteger basic type description.
*/
-static ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = {
+static const ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
};
asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
@@ -31,6 +31,8 @@ asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
NativeInteger_encode_xer,
NativeInteger_decode_uper, /* Unaligned PER decoder */
NativeInteger_encode_uper, /* Unaligned PER encoder */
+ NativeInteger_decode_aper, /* Aligned PER decoder */
+ NativeInteger_encode_aper, /* Aligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_NativeInteger_tags,
sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
@@ -107,7 +109,7 @@ NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
tmp.size = length;
if((specs&&specs->field_unsigned)
- ? asn_INTEGER2ulong(&tmp, &l)
+ ? asn_INTEGER2ulong(&tmp, (unsigned long *)&l) /* sic */
: asn_INTEGER2long(&tmp, &l)) {
rval.code = RC_FAIL;
rval.consumed = 0;
@@ -187,7 +189,7 @@ NativeInteger_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
if(rval.code == RC_OK) {
long l;
if((specs&&specs->field_unsigned)
- ? asn_INTEGER2ulong(&st, &l)
+ ? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */
: asn_INTEGER2long(&st, &l)) {
rval.code = RC_FAIL;
rval.consumed = 0;
@@ -255,7 +257,43 @@ NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
&tmpintptr, pd);
if(rval.code == RC_OK) {
if((specs&&specs->field_unsigned)
- ? asn_INTEGER2ulong(&tmpint, native)
+ ? asn_INTEGER2ulong(&tmpint, (unsigned long *)native)
+ : asn_INTEGER2long(&tmpint, native))
+ rval.code = RC_FAIL;
+ else
+ ASN_DEBUG("NativeInteger %s got value %ld",
+ td->name, *native);
+ }
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
+
+ return rval;
+}
+
+asn_dec_rval_t
+NativeInteger_decode_aper(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+ asn_dec_rval_t rval;
+ long *native = (long *)*sptr;
+ INTEGER_t tmpint;
+ void *tmpintptr = &tmpint;
+
+ (void)opt_codec_ctx;
+ ASN_DEBUG("Decoding NativeInteger %s (APER)", td->name);
+
+ if(!native) {
+ native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
+ if(!native) _ASN_DECODE_FAILED;
+ }
+
+ memset(&tmpint, 0, sizeof tmpint);
+ rval = INTEGER_decode_aper(opt_codec_ctx, td, constraints,
+ &tmpintptr, pd);
+ if(rval.code == RC_OK) {
+ if((specs&&specs->field_unsigned)
+ ? asn_INTEGER2ulong(&tmpint, (unsigned long *)native)
: asn_INTEGER2long(&tmpint, native))
rval.code = RC_FAIL;
else
@@ -291,6 +329,32 @@ NativeInteger_encode_uper(asn_TYPE_descriptor_t *td,
return er;
}
+asn_enc_rval_t
+NativeInteger_encode_aper(
+ asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+
+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
+ asn_enc_rval_t er;
+ long native;
+ INTEGER_t tmpint;
+
+ if(!sptr) _ASN_ENCODE_FAILED;
+
+ native = *(long *)sptr;
+
+ ASN_DEBUG("Encoding NativeInteger %s %ld (APER)", td->name, native);
+
+ memset(&tmpint, 0, sizeof(tmpint));
+ if((specs&&specs->field_unsigned)
+ ? asn_ulong2INTEGER(&tmpint, native)
+ : asn_long2INTEGER(&tmpint, native))
+ _ASN_ENCODE_FAILED;
+ er = INTEGER_encode_aper(td, constraints, &tmpint, po);
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
+ return er;
+}
+
/*
* INTEGER specific human-readable output.
*/
diff --git a/src/NativeReal.c b/src/NativeReal.c
index a1ff91e..3bd5a28 100644
--- a/src/NativeReal.c
+++ b/src/NativeReal.c
@@ -17,7 +17,7 @@
/*
* NativeReal basic type description.
*/
-static ber_tlv_tag_t asn_DEF_NativeReal_tags[] = {
+static const ber_tlv_tag_t asn_DEF_NativeReal_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (9 << 2))
};
asn_TYPE_descriptor_t asn_DEF_NativeReal = {
@@ -32,6 +32,8 @@ asn_TYPE_descriptor_t asn_DEF_NativeReal = {
NativeReal_encode_xer,
NativeReal_decode_uper,
NativeReal_encode_uper,
+ NativeReal_decode_aper,
+ NativeReal_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_NativeReal_tags,
sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]),
@@ -107,10 +109,39 @@ NativeReal_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
tmp.size = length;
- if(asn_REAL2double(&tmp, &d)) {
- rval.code = RC_FAIL;
- rval.consumed = 0;
- return rval;
+ if(length < (ber_tlv_len_t)size) {
+ int ret;
+ uint8_t saved_byte = tmp.buf[tmp.size];
+ tmp.buf[tmp.size] = '\0';
+ ret = asn_REAL2double(&tmp, &d);
+ tmp.buf[tmp.size] = saved_byte;
+ if(ret) {
+ rval.code = RC_FAIL;
+ rval.consumed = 0;
+ return rval;
+ }
+ } else if(length < 48 /* Enough for longish %f value. */) {
+ tmp.buf = alloca(length + 1);
+ tmp.size = length;
+ memcpy(tmp.buf, buf_ptr, length);
+ tmp.buf[tmp.size] = '\0';
+ if(asn_REAL2double(&tmp, &d)) {
+ rval.code = RC_FAIL;
+ rval.consumed = 0;
+ return rval;
+ }
+ } else {
+ /* This should probably never happen: impractically long value */
+ tmp.buf = CALLOC(1, length + 1);
+ tmp.size = length;
+ if(tmp.buf) memcpy(tmp.buf, buf_ptr, length);
+ if(!tmp.buf || asn_REAL2double(&tmp, &d)) {
+ FREEMEM(tmp.buf);
+ rval.code = RC_FAIL;
+ rval.consumed = 0;
+ return rval;
+ }
+ FREEMEM(tmp.buf);
}
*Dbl = d;
@@ -199,6 +230,43 @@ NativeReal_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
return rval;
}
+asn_dec_rval_t
+NativeReal_decode_aper(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+ void **dbl_ptr, asn_per_data_t *pd) {
+ double *Dbl = (double *)*dbl_ptr;
+ asn_dec_rval_t rval;
+ REAL_t tmp;
+ void *ptmp = &tmp;
+ int ret;
+
+ (void)constraints;
+
+ /*
+ * If the structure is not there, allocate it.
+ */
+ if(Dbl == NULL) {
+ *dbl_ptr = CALLOC(1, sizeof(*Dbl));
+ Dbl = (double *)*dbl_ptr;
+ if(Dbl == NULL)
+ _ASN_DECODE_FAILED;
+ }
+
+ memset(&tmp, 0, sizeof(tmp));
+ rval = OCTET_STRING_decode_aper(opt_codec_ctx, td, NULL,
+ &ptmp, pd);
+ if(rval.code != RC_OK) {
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
+ return rval;
+ }
+
+ ret = asn_REAL2double(&tmp, Dbl);
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
+ if(ret) _ASN_DECODE_FAILED;
+
+ return rval;
+}
+
/*
* Encode the NativeReal using the OCTET STRING PER encoder.
*/
@@ -228,6 +296,32 @@ NativeReal_encode_uper(asn_TYPE_descriptor_t *td,
return erval;
}
+asn_enc_rval_t
+NativeReal_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ double Dbl = *(const double *)sptr;
+ asn_enc_rval_t erval;
+ REAL_t tmp;
+
+ (void)constraints;
+
+ /* Prepare a temporary clean structure */
+ memset(&tmp, 0, sizeof(tmp));
+
+ if(asn_double2REAL(&tmp, Dbl))
+ _ASN_ENCODE_FAILED;
+
+ /* Encode a DER REAL */
+ erval = OCTET_STRING_encode_aper(td, NULL, &tmp, po);
+ if(erval.encoded == -1)
+ erval.structure_ptr = sptr;
+
+ /* Free possibly allocated members of the temporary structure */
+ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_REAL, &tmp);
+
+ return erval;
+}
+
/*
* Decode the chunk of XML text encoding REAL.
*/
diff --git a/src/NumericString.c b/src/NumericString.c
index 50fe449..81b880a 100644
--- a/src/NumericString.c
+++ b/src/NumericString.c
@@ -8,7 +8,7 @@
/*
* NumericString basic type description.
*/
-static ber_tlv_tag_t asn_DEF_NumericString_tags[] = {
+static const ber_tlv_tag_t asn_DEF_NumericString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (18 << 2)), /* [UNIVERSAL 18] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
@@ -49,6 +49,8 @@ asn_TYPE_descriptor_t asn_DEF_NumericString = {
OCTET_STRING_encode_xer_utf8,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_NumericString_tags,
sizeof(asn_DEF_NumericString_tags)
diff --git a/src/OBJECT_IDENTIFIER.c b/src/OBJECT_IDENTIFIER.c
index 0d7043e..24f4e0e 100644
--- a/src/OBJECT_IDENTIFIER.c
+++ b/src/OBJECT_IDENTIFIER.c
@@ -3,6 +3,7 @@
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
+#include <INTEGER.h>
#include <OBJECT_IDENTIFIER.h>
#include <OCTET_STRING.h>
#include <limits.h> /* for CHAR_BIT */
@@ -11,7 +12,7 @@
/*
* OBJECT IDENTIFIER basic type description.
*/
-static ber_tlv_tag_t asn_DEF_OBJECT_IDENTIFIER_tags[] = {
+static const ber_tlv_tag_t asn_DEF_OBJECT_IDENTIFIER_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (6 << 2))
};
asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER = {
@@ -26,6 +27,8 @@ asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER = {
OBJECT_IDENTIFIER_encode_xer,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_OBJECT_IDENTIFIER_tags,
sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)
@@ -64,9 +67,9 @@ OBJECT_IDENTIFIER_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
int
-OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, signed int add, void *rvbufp, unsigned int rvsize) {
+OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf, unsigned int arclen, signed int add, void *rvbufp, unsigned int rvsize) {
unsigned LE GCC_NOTUSED = 1; /* Little endian (x86) */
- uint8_t *arcend = arcbuf + arclen; /* End of arc */
+ const uint8_t *arcend = arcbuf + arclen; /* End of arc */
unsigned int cache = 0; /* No more than 14 significant bits */
unsigned char *rvbuf = (unsigned char *)rvbufp;
unsigned char *rvstart = rvbuf; /* Original start of the value buffer */
@@ -119,7 +122,7 @@ OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, signed in
errno = ERANGE; /* Overflow */
return -1;
}
- *(unsigned long *)rvbuf = accum + add; /* alignment OK! */
+ *(unsigned long *)(void *)rvbuf = accum + add; /* alignment OK! */
return 0;
}
@@ -180,7 +183,7 @@ OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, signed in
}
ssize_t
-OBJECT_IDENTIFIER__dump_arc(uint8_t *arcbuf, int arclen, int add,
+OBJECT_IDENTIFIER__dump_arc(const uint8_t *arcbuf, int arclen, int add,
asn_app_consume_bytes_f *cb, void *app_key) {
char scratch[64]; /* Conservative estimate */
unsigned long accum; /* Bits accumulator */
@@ -211,7 +214,7 @@ OBJECT_IDENTIFIER__dump_arc(uint8_t *arcbuf, int arclen, int add,
}
int
-OBJECT_IDENTIFIER_print_arc(uint8_t *arcbuf, int arclen, int add,
+OBJECT_IDENTIFIER_print_arc(const uint8_t *arcbuf, int arclen, int add,
asn_app_consume_bytes_f *cb, void *app_key) {
if(OBJECT_IDENTIFIER__dump_arc(arcbuf, arclen, add, cb, app_key) < 0)
@@ -281,15 +284,13 @@ OBJECT_IDENTIFIER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const
arcs_count = OBJECT_IDENTIFIER_parse_arcs(
(const char *)chunk_buf, chunk_size, arcs,
sizeof(s_arcs)/sizeof(s_arcs[0]), &endptr);
- if(arcs_count <= 0) {
+ if(arcs_count < 0) {
/* Expecting more than zero arcs */
return XPBD_BROKEN_ENCODING;
+ } else if(arcs_count == 0) {
+ return XPBD_NOT_BODY_IGNORE;
}
- if(endptr < chunk_end) {
- /* We have a tail of unrecognized data. Check its safety. */
- if(!xer_is_whitespace(endptr, chunk_end - endptr))
- return XPBD_BROKEN_ENCODING;
- }
+ assert(endptr == chunk_end);
if((size_t)arcs_count > sizeof(s_arcs)/sizeof(s_arcs[0])) {
arcs = (long *)MALLOC(arcs_count * sizeof(long));
@@ -361,7 +362,7 @@ OBJECT_IDENTIFIER_print(asn_TYPE_descriptor_t *td, const void *sptr,
}
int
-OBJECT_IDENTIFIER_get_arcs(OBJECT_IDENTIFIER_t *oid, void *arcs,
+OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *oid, void *arcs,
unsigned int arc_type_size, unsigned int arc_slots) {
void *arcs_end = (char *)arcs + (arc_type_size * arc_slots);
int num_arcs = 0;
@@ -649,12 +650,12 @@ OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length,
long *arcs, unsigned int arcs_slots, const char **opt_oid_text_end) {
unsigned int arcs_count = 0;
const char *oid_end;
- long value = 0;
enum {
- ST_SKIPSPACE,
+ ST_LEADSPACE,
+ ST_TAILSPACE,
+ ST_AFTERVALUE, /* Next character ought to be '.' or a space */
ST_WAITDIGITS, /* Next character is expected to be a digit */
- ST_DIGITS
- } state = ST_SKIPSPACE;
+ } state = ST_LEADSPACE;
if(!oid_text || oid_txt_length < -1 || (arcs_slots && !arcs)) {
if(opt_oid_text_end) *opt_oid_text_end = oid_text;
@@ -665,41 +666,76 @@ OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length,
if(oid_txt_length == -1)
oid_txt_length = strlen(oid_text);
+#define _OID_CAPTURE_ARC(oid_text, oid_end) do { \
+ const char *endp = oid_end; \
+ long value; \
+ switch(asn_strtol_lim(oid_text, &endp, &value)) { \
+ case ASN_STRTOL_EXTRA_DATA: \
+ case ASN_STRTOL_OK: \
+ if(arcs_count < arcs_slots) \
+ arcs[arcs_count] = value; \
+ arcs_count++; \
+ oid_text = endp - 1; \
+ break; \
+ case ASN_STRTOL_ERROR_RANGE: \
+ if(opt_oid_text_end) \
+ *opt_oid_text_end = oid_text; \
+ errno = ERANGE; \
+ return -1; \
+ case ASN_STRTOL_ERROR_INVAL: \
+ case ASN_STRTOL_EXPECT_MORE: \
+ if(opt_oid_text_end) \
+ *opt_oid_text_end = oid_text; \
+ errno = EINVAL; \
+ return -1; \
+ } \
+ } while(0)
+
for(oid_end = oid_text + oid_txt_length; oid_text<oid_end; oid_text++) {
switch(*oid_text) {
case 0x09: case 0x0a: case 0x0d: case 0x20: /* whitespace */
- if(state == ST_SKIPSPACE) {
+ switch(state) {
+ case ST_LEADSPACE:
+ case ST_TAILSPACE:
continue;
- } else {
- break; /* Finish */
+ case ST_AFTERVALUE:
+ state = ST_TAILSPACE;
+ continue;
+ case ST_WAITDIGITS:
+ break; /* Digits expected after ".", got whitespace */
}
+ break;
case 0x2e: /* '.' */
- if(state != ST_DIGITS
- || (oid_text + 1) == oid_end) {
- state = ST_WAITDIGITS;
+ switch(state) {
+ case ST_LEADSPACE:
+ case ST_TAILSPACE:
+ case ST_WAITDIGITS:
+ if(opt_oid_text_end)
+ *opt_oid_text_end = oid_text;
+ errno = EINVAL; /* Broken OID */
+ return -1;
break;
+ case ST_AFTERVALUE:
+ state = ST_WAITDIGITS;
+ continue;
}
- if(arcs_count < arcs_slots)
- arcs[arcs_count] = value;
- arcs_count++;
- state = ST_WAITDIGITS;
- continue;
+ break;
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
- if(state != ST_DIGITS) {
- state = ST_DIGITS;
- value = 0;
- }
- if(1) {
- long new_value = value * 10;
- if(new_value / 10 != value
- || (value = new_value + (*oid_text - 0x30)) < 0) {
- /* Overflow */
- state = ST_WAITDIGITS;
- break;
- }
+ switch(state) {
+ case ST_TAILSPACE:
+ case ST_AFTERVALUE:
+ if(opt_oid_text_end)
+ *opt_oid_text_end = oid_text;
+ errno = EINVAL; /* "1. 1" => broken OID */
+ return -1;
+ case ST_LEADSPACE:
+ case ST_WAITDIGITS:
+ _OID_CAPTURE_ARC(oid_text, oid_end);
+ state = ST_AFTERVALUE;
continue;
}
+ break;
default:
/* Unexpected symbols */
state = ST_WAITDIGITS;
@@ -713,17 +749,18 @@ OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length,
/* Finalize last arc */
switch(state) {
+ case ST_LEADSPACE:
+ return 0; /* No OID found in input data */
case ST_WAITDIGITS:
- errno = EINVAL;
+ errno = EINVAL; /* Broken OID */
return -1;
- case ST_DIGITS:
- if(arcs_count < arcs_slots)
- arcs[arcs_count] = value;
- arcs_count++;
- /* Fall through */
- default:
+ case ST_AFTERVALUE:
+ case ST_TAILSPACE:
return arcs_count;
}
+
+ errno = EINVAL; /* Broken OID */
+ return -1;
}
diff --git a/src/OCTET_STRING.c b/src/OCTET_STRING.c
index 584def8..3e424e7 100644
--- a/src/OCTET_STRING.c
+++ b/src/OCTET_STRING.c
@@ -11,15 +11,15 @@
/*
* OCTET STRING basic type description.
*/
-static ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] = {
+static const ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
};
-static asn_OCTET_STRING_specifics_t asn_DEF_OCTET_STRING_specs = {
+static const asn_OCTET_STRING_specifics_t asn_DEF_OCTET_STRING_specs = {
sizeof(OCTET_STRING_t),
offsetof(OCTET_STRING_t, _asn_ctx),
ASN_OSUBV_STR
};
-static asn_per_constraints_t asn_DEF_OCTET_STRING_constraints = {
+static const asn_per_constraints_t asn_DEF_OCTET_STRING_constraints = {
{ APC_CONSTRAINED, 8, 8, 0, 255 },
{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },
0, 0
@@ -36,6 +36,8 @@ asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
OCTET_STRING_encode_xer,
OCTET_STRING_decode_uper, /* Unaligned PER decoder */
OCTET_STRING_encode_uper, /* Unaligned PER encoder */
+ OCTET_STRING_decode_aper, /* Aligned PER decoder */
+ OCTET_STRING_encode_aper, /* Aligned PER encoder */
0, /* Use generic outmost tag fetcher */
asn_DEF_OCTET_STRING_tags,
sizeof(asn_DEF_OCTET_STRING_tags)
@@ -580,7 +582,7 @@ asn_enc_rval_t
OCTET_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
- static const char *h2c = "0123456789ABCDEF";
+ const char * const h2c = "0123456789ABCDEF";
const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
asn_enc_rval_t er;
char scratch[16 * 3 + 4];
@@ -639,8 +641,8 @@ cb_failed:
_ASN_ENCODE_FAILED;
}
-static struct OCTET_STRING__xer_escape_table_s {
- char *string;
+static const struct OCTET_STRING__xer_escape_table_s {
+ const char *string;
int size;
} OCTET_STRING__xer_escape_table[] = {
#define OSXET(s) { s, sizeof(s) - 1 }
@@ -702,7 +704,7 @@ OS__check_escaped_control_char(const void *buf, int size) {
* nested table lookups).
*/
for(i = 0; i < 32 /* Don't spend time on the bottom half */; i++) {
- struct OCTET_STRING__xer_escape_table_s *el;
+ const struct OCTET_STRING__xer_escape_table_s *el;
el = &OCTET_STRING__xer_escape_table[i];
if(el->size == size && memcmp(buf, el->string, size) == 0)
return i;
@@ -1194,14 +1196,14 @@ OCTET_STRING_decode_xer_utf8(asn_codec_ctx_t *opt_codec_ctx,
static int
OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
size_t units, unsigned int bpc, unsigned int unit_bits,
- long lb, long ub, asn_per_constraints_t *pc) {
+ int64_t lb, int64_t ub, asn_per_constraints_t *pc) {
uint8_t *end = buf + units * bpc;
- ASN_DEBUG("Expanding %d characters into (%ld..%ld):%d",
+ ASN_DEBUG("Expanding %d characters into (%lld..%lld):%d",
(int)units, lb, ub, unit_bits);
/* X.691: 27.5.4 */
- if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
+ if((uint64_t)ub <= ((uint64_t)2 << (unit_bits - 1))) {
/* Decode without translation */
lb = 0;
} else if(pc && pc->code2value) {
@@ -1216,7 +1218,7 @@ OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
value = pc->code2value(code);
if(value < 0) {
ASN_DEBUG("Code %d (0x%02x) is"
- " not in map (%ld..%ld)",
+ " not in map (%lld..%lld)",
code, code, lb, ub);
return 1; /* FATAL */
}
@@ -1240,7 +1242,7 @@ OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
int ch = code + lb;
if(code < 0) return -1; /* WMORE */
if(ch > ub) {
- ASN_DEBUG("Code %d is out of range (%ld..%ld)",
+ ASN_DEBUG("Code %d is out of range (%lld..%lld)",
ch, lb, ub);
return 1; /* FATAL */
}
@@ -1258,14 +1260,14 @@ OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
static int
OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t *buf,
size_t units, unsigned int bpc, unsigned int unit_bits,
- long lb, long ub, asn_per_constraints_t *pc) {
+ int64_t lb, int64_t ub, asn_per_constraints_t *pc) {
const uint8_t *end = buf + units * bpc;
- ASN_DEBUG("Squeezing %d characters into (%ld..%ld):%d (%d bpc)",
+ ASN_DEBUG("Squeezing %d characters into (%lld..%lld):%d (%d bpc)",
(int)units, lb, ub, unit_bits, bpc);
/* X.691: 27.5.4 */
- if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
+ if((uint64_t)ub <= ((uint64_t)2 << (unit_bits - 1))) {
/* Encode as is */
lb = 0;
} else if(pc && pc->value2code) {
@@ -1282,7 +1284,7 @@ OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t *buf,
code = pc->value2code(value);
if(code < 0) {
ASN_DEBUG("Character %d (0x%02x) is"
- " not in map (%ld..%ld)",
+ " not in map (%lld..%lld)",
*buf, *buf, lb, ub);
return -1;
}
@@ -1309,7 +1311,7 @@ OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t *buf,
ch = value - lb;
if(ch < 0 || ch > ub) {
ASN_DEBUG("Character %d (0x%02x)"
- " is out of range (%ld..%ld)",
+ " is out of range (%lld..%lld)",
*buf, *buf, lb, ub + lb);
return -1;
}
@@ -1392,7 +1394,7 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
if(!st) RETURN(RC_FAIL);
}
- ASN_DEBUG("PER Decoding %s size %ld .. %ld bits %d",
+ ASN_DEBUG("PER Decoding %s size %lld .. %lld bits %d",
csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
@@ -1423,14 +1425,14 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
if(csiz->effective_bits == 0) {
int ret;
if(bpc) {
- ASN_DEBUG("Encoding OCTET STRING size %ld",
+ ASN_DEBUG("Encoding OCTET STRING size %lld",
csiz->upper_bound);
ret = OCTET_STRING_per_get_characters(pd, st->buf,
csiz->upper_bound, bpc, unit_bits,
cval->lower_bound, cval->upper_bound, pc);
if(ret > 0) RETURN(RC_FAIL);
} else {
- ASN_DEBUG("Encoding BIT STRING size %ld",
+ ASN_DEBUG("Encoding BIT STRING size %lld",
csiz->upper_bound);
ret = per_get_many_bits(pd, st->buf, 0,
unit_bits * csiz->upper_bound);
@@ -1492,6 +1494,194 @@ OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
return rval;
}
+asn_dec_rval_t
+OCTET_STRING_decode_aper(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+ void **sptr, asn_per_data_t *pd) {
+
+ asn_OCTET_STRING_specifics_t *specs = td->specifics
+ ? (asn_OCTET_STRING_specifics_t *)td->specifics
+ : &asn_DEF_OCTET_STRING_specs;
+ asn_per_constraints_t *pc = constraints ? constraints
+ : td->per_constraints;
+ asn_per_constraint_t *cval;
+ asn_per_constraint_t *csiz;
+ asn_dec_rval_t rval = { RC_OK, 0 };
+ BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
+ ssize_t consumed_myself = 0;
+ int repeat;
+ enum {
+ OS__BPC_BIT = 0,
+ OS__BPC_CHAR = 1,
+ OS__BPC_U16 = 2,
+ OS__BPC_U32 = 4
+ } bpc; /* Bytes per character */
+ unsigned int unit_bits;
+ unsigned int canonical_unit_bits;
+
+ (void)opt_codec_ctx;
+
+ if(pc) {
+ cval = &pc->value;
+ csiz = &pc->size;
+ } else {
+ cval = &asn_DEF_OCTET_STRING_constraints.value;
+ csiz = &asn_DEF_OCTET_STRING_constraints.size;
+ }
+
+ switch(specs->subvariant) {
+ default:
+// case ASN_OSUBV_ANY:
+// ASN_DEBUG("Unrecognized subvariant %d", specs->subvariant);
+// RETURN(RC_FAIL);
+ case ASN_OSUBV_BIT:
+ canonical_unit_bits = unit_bits = 1;
+ bpc = OS__BPC_BIT;
+ break;
+ case ASN_OSUBV_ANY:
+ case ASN_OSUBV_STR:
+ canonical_unit_bits = unit_bits = 8;
+// if(cval->flags & APC_CONSTRAINED)
+// unit_bits = cval->range_bits;
+ bpc = OS__BPC_CHAR;
+ break;
+ case ASN_OSUBV_U16:
+ canonical_unit_bits = unit_bits = 16;
+ if(cval->flags & APC_CONSTRAINED)
+ unit_bits = cval->range_bits;
+ bpc = OS__BPC_U16;
+ break;
+ case ASN_OSUBV_U32:
+ canonical_unit_bits = unit_bits = 32;
+ if(cval->flags & APC_CONSTRAINED)
+ unit_bits = cval->range_bits;
+ bpc = OS__BPC_U32;
+ break;
+ }
+
+ /*
+ * Allocate the string.
+ */
+ if(!st) {
+ st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
+ if(!st) RETURN(RC_FAIL);
+ }
+
+ ASN_DEBUG("PER Decoding %s size %lld .. %lld bits %d",
+ csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
+ csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
+
+ if(csiz->flags & APC_EXTENSIBLE) {
+ int inext = per_get_few_bits(pd, 1);
+ if(inext < 0) RETURN(RC_WMORE);
+ if(inext) {
+ csiz = &asn_DEF_OCTET_STRING_constraints.size;
+ cval = &asn_DEF_OCTET_STRING_constraints.value;
+ unit_bits = canonical_unit_bits;
+ }
+ }
+
+ if(csiz->effective_bits >= 0) {
+ FREEMEM(st->buf);
+ if(bpc) {
+ st->size = csiz->upper_bound * bpc;
+ } else {
+ st->size = (csiz->upper_bound + 7) >> 3;
+ }
+ st->buf = (uint8_t *)MALLOC(st->size + 1);
+ if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
+ }
+
+ /* X.691, #16.5: zero-length encoding */
+ /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
+ /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
+ if(csiz->effective_bits == 0) {
+ int ret;
+ if (st->size > 2) { /* X.691 #16 NOTE 1 */
+ if (aper_get_align(pd) < 0)
+ RETURN(RC_FAIL);
+ }
+ if(bpc) {
+ ASN_DEBUG("Decoding OCTET STRING size %lld",
+ csiz->upper_bound);
+ ret = OCTET_STRING_per_get_characters(pd, st->buf,
+ csiz->upper_bound, bpc, unit_bits,
+ cval->lower_bound, cval->upper_bound, pc);
+ if(ret > 0) RETURN(RC_FAIL);
+ } else {
+ ASN_DEBUG("Decoding BIT STRING size %lld",
+ csiz->upper_bound);
+ ret = per_get_many_bits(pd, st->buf, 0,
+ unit_bits * csiz->upper_bound);
+ }
+ if(ret < 0) RETURN(RC_WMORE);
+ consumed_myself += unit_bits * csiz->upper_bound;
+ st->buf[st->size] = 0;
+ if(bpc == 0) {
+ int ubs = (csiz->upper_bound & 0x7);
+ st->bits_unused = ubs ? 8 - ubs : 0;
+ }
+ RETURN(RC_OK);
+ }
+
+ st->size = 0;
+ do {
+ ssize_t raw_len;
+ ssize_t len_bytes;
+ ssize_t len_bits;
+ void *p;
+ int ret;
+
+ /* Get the PER length */
+ if (csiz->upper_bound - csiz->lower_bound == 0)
+ // Indefinite length case
+ raw_len = aper_get_length(pd, -1, csiz->effective_bits, &repeat);
+ else
+ raw_len = aper_get_length(pd, csiz->upper_bound - csiz->lower_bound + 1, csiz->effective_bits, &repeat);
+ repeat = 0;
+ if(raw_len < 0) RETURN(RC_WMORE);
+ raw_len += csiz->lower_bound;
+
+ ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
+ (long)csiz->effective_bits, (long)raw_len,
+ repeat ? "repeat" : "once", td->name);
+
+ if (raw_len > 2) { /* X.691 #16 NOTE 1 */
+ if (aper_get_align(pd) < 0)
+ RETURN(RC_FAIL);
+ }
+
+ if(bpc) {
+ len_bytes = raw_len * bpc;
+ len_bits = len_bytes * unit_bits;
+ } else {
+ len_bits = raw_len;
+ len_bytes = (len_bits + 7) >> 3;
+ if(len_bits & 0x7)
+ st->bits_unused = 8 - (len_bits & 0x7);
+ /* len_bits be multiple of 16K if repeat is set */
+ }
+ p = REALLOC(st->buf, st->size + len_bytes + 1);
+ if(!p) RETURN(RC_FAIL);
+ st->buf = (uint8_t *)p;
+
+ if(bpc) {
+ ret = OCTET_STRING_per_get_characters(pd,
+ &st->buf[st->size], raw_len, bpc, unit_bits,
+ cval->lower_bound, cval->upper_bound, pc);
+ if(ret > 0) RETURN(RC_FAIL);
+ } else {
+ ret = per_get_many_bits(pd, &st->buf[st->size],
+ 0, len_bits);
+ }
+ if(ret < 0) RETURN(RC_WMORE);
+ st->size += len_bytes;
+ } while(repeat);
+ st->buf[st->size] = 0; /* nul-terminate */
+
+ return rval;
+}
+
asn_enc_rval_t
OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
@@ -1566,12 +1756,12 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
}
ASN_DEBUG("Encoding %s into %d units of %d bits"
- " (%ld..%ld, effective %d)%s",
+ " (%lld..%lld, effective %d)%s",
td->name, sizeinunits, unit_bits,
csiz->lower_bound, csiz->upper_bound,
csiz->effective_bits, ct_extensible ? " EXT" : "");
- /* Figure out wheter size lies within PER visible constraint */
+ /* Figure out whether size lies within PER visible constraint */
if(csiz->effective_bits >= 0) {
if((int)sizeinunits < csiz->lower_bound
@@ -1598,7 +1788,7 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
if(csiz->effective_bits >= 0) {
- ASN_DEBUG("Encoding %d bytes (%ld), length in %d bits",
+ ASN_DEBUG("Encoding %d bytes (%lld), length in %d bits",
st->size, sizeinunits - csiz->lower_bound,
csiz->effective_bits);
ret = per_put_few_bits(po, sizeinunits - csiz->lower_bound,
@@ -1652,10 +1842,177 @@ OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
_ASN_ENCODED_OK(er);
}
+asn_enc_rval_t
+OCTET_STRING_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+
+ asn_OCTET_STRING_specifics_t *specs = td->specifics
+ ? (asn_OCTET_STRING_specifics_t *)td->specifics
+ : &asn_DEF_OCTET_STRING_specs;
+ asn_per_constraints_t *pc = constraints ? constraints
+ : td->per_constraints;
+ asn_per_constraint_t *cval;
+ asn_per_constraint_t *csiz;
+ const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
+ asn_enc_rval_t er = { 0, 0, 0 };
+ int inext = 0; /* Lies not within extension root */
+ unsigned int unit_bits;
+ unsigned int canonical_unit_bits;
+ unsigned int sizeinunits;
+ const uint8_t *buf;
+ int ret;
+ enum {
+ OS__BPC_BIT = 0,
+ OS__BPC_CHAR = 1,
+ OS__BPC_U16 = 2,
+ OS__BPC_U32 = 4
+ } bpc; /* Bytes per character */
+ int ct_extensible;
+
+ if(!st || (!st->buf && st->size))
+ _ASN_ENCODE_FAILED;
+
+ if(pc) {
+ cval = &pc->value;
+ csiz = &pc->size;
+ } else {
+ cval = &asn_DEF_OCTET_STRING_constraints.value;
+ csiz = &asn_DEF_OCTET_STRING_constraints.size;
+ }
+ ct_extensible = csiz->flags & APC_EXTENSIBLE;
+
+ switch(specs->subvariant) {
+ default:
+// case ASN_OSUBV_ANY:
+// _ASN_ENCODE_FAILED;
+ case ASN_OSUBV_BIT:
+ canonical_unit_bits = unit_bits = 1;
+ bpc = OS__BPC_BIT;
+ sizeinunits = st->size * 8 - (st->bits_unused & 0x07);
+ ASN_DEBUG("BIT STRING of %d bytes",
+ sizeinunits);
+ break;
+ case ASN_OSUBV_ANY:
+ case ASN_OSUBV_STR:
+ canonical_unit_bits = unit_bits = 8;
+// if(cval->flags & APC_CONSTRAINED)
+// unit_bits = 8;
+ bpc = OS__BPC_CHAR;
+ sizeinunits = st->size;
+ break;
+ case ASN_OSUBV_U16:
+ canonical_unit_bits = unit_bits = 16;
+ if(cval->flags & APC_CONSTRAINED)
+ unit_bits = cval->range_bits;
+ bpc = OS__BPC_U16;
+ sizeinunits = st->size / 2;
+ break;
+ case ASN_OSUBV_U32:
+ canonical_unit_bits = unit_bits = 32;
+ if(cval->flags & APC_CONSTRAINED)
+ unit_bits = cval->range_bits;
+ bpc = OS__BPC_U32;
+ sizeinunits = st->size / 4;
+ break;
+ }
+
+ ASN_DEBUG("Encoding %s into %d units of %d bits"
+ " (%lld..%lld, effective %d)%s",
+ td->name, sizeinunits, unit_bits,
+ csiz->lower_bound, csiz->upper_bound,
+ csiz->effective_bits, ct_extensible ? " EXT" : "");
+
+ /* Figure out wheter size lies within PER visible constraint */
+
+ if(csiz->effective_bits >= 0) {
+ if((int)sizeinunits < csiz->lower_bound
+ || (int)sizeinunits > csiz->upper_bound) {
+ if(ct_extensible) {
+ cval = &asn_DEF_OCTET_STRING_constraints.value;
+ csiz = &asn_DEF_OCTET_STRING_constraints.size;
+ unit_bits = canonical_unit_bits;
+ inext = 1;
+ } else
+ _ASN_ENCODE_FAILED;
+ }
+ } else {
+ inext = 0;
+ }
+
+
+ if(ct_extensible) {
+ /* Declare whether length is [not] within extension root */
+ if(per_put_few_bits(po, inext, 1))
+ _ASN_ENCODE_FAILED;
+ }
+
+ /* X.691, #16.5: zero-length encoding */
+ /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
+ /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
+ if(csiz->effective_bits >= 0) {
+ ASN_DEBUG("Encoding %d bytes (%lld), length in %d bits",
+ st->size, sizeinunits - csiz->lower_bound,
+ csiz->effective_bits);
+ ret = per_put_few_bits(po, sizeinunits - csiz->lower_bound,
+ csiz->effective_bits);
+ if(ret) _ASN_ENCODE_FAILED;
+ if (st->size > 2) { /* X.691 #16 NOTE 1 */
+ if (aper_put_align(po) < 0)
+ _ASN_ENCODE_FAILED;
+ }
+ if(bpc) {
+ ret = OCTET_STRING_per_put_characters(po, st->buf,
+ sizeinunits, bpc, unit_bits,
+ cval->lower_bound, cval->upper_bound, pc);
+ } else {
+ ret = per_put_many_bits(po, st->buf,
+ sizeinunits * unit_bits);
+ }
+ if(ret) _ASN_ENCODE_FAILED;
+ _ASN_ENCODED_OK(er);
+ }
+
+ ASN_DEBUG("Encoding %d bytes", st->size);
+
+ if(sizeinunits == 0) {
+ if(aper_put_length(po, -1, 0))
+ _ASN_ENCODE_FAILED;
+ _ASN_ENCODED_OK(er);
+ }
+
+ buf = st->buf;
+ while(sizeinunits) {
+ ssize_t maySave = aper_put_length(po, -1, sizeinunits);
+
+ if(maySave < 0) _ASN_ENCODE_FAILED;
+
+ ASN_DEBUG("Encoding %ld of %ld",
+ (long)maySave, (long)sizeinunits);
+
+ if(bpc) {
+ ret = OCTET_STRING_per_put_characters(po, buf,
+ maySave, bpc, unit_bits,
+ cval->lower_bound, cval->upper_bound, pc);
+ } else {
+ ret = per_put_many_bits(po, buf, maySave * unit_bits);
+ }
+ if(ret) _ASN_ENCODE_FAILED;
+
+ if(bpc)
+ buf += maySave * bpc;
+ else
+ buf += maySave >> 3;
+ sizeinunits -= maySave;
+ assert(!(maySave & 0x07) || !sizeinunits);
+ }
+
+ _ASN_ENCODED_OK(er);
+}
+
int
OCTET_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
- static const char *h2c = "0123456789ABCDEF";
+ const char * const h2c = "0123456789ABCDEF";
const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
char scratch[16 * 3 + 4];
char *p = scratch;
diff --git a/src/ObjectDescriptor.c b/src/ObjectDescriptor.c
index cd8e8a3..f049c1c 100644
--- a/src/ObjectDescriptor.c
+++ b/src/ObjectDescriptor.c
@@ -8,7 +8,7 @@
/*
* ObjectDescriptor basic type description.
*/
-static ber_tlv_tag_t asn_DEF_ObjectDescriptor_tags[] = {
+static const ber_tlv_tag_t asn_DEF_ObjectDescriptor_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (7 << 2)), /* [UNIVERSAL 7] IMPLICIT ... */
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
@@ -24,6 +24,8 @@ asn_TYPE_descriptor_t asn_DEF_ObjectDescriptor = {
OCTET_STRING_encode_xer_utf8,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_ObjectDescriptor_tags,
sizeof(asn_DEF_ObjectDescriptor_tags)
diff --git a/src/PrintableString.c b/src/PrintableString.c
index c8ee3ae..3058d09 100644
--- a/src/PrintableString.c
+++ b/src/PrintableString.c
@@ -9,7 +9,7 @@
/*
* ASN.1:1984 (X.409)
*/
-static int _PrintableString_alphabet[256] = {
+static const int _PrintableString_alphabet[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */
1, 0, 0, 0, 0, 0, 0, 2, 3, 4, 0, 5, 6, 7, 8, 9, /* . '() +,-./ */
@@ -19,7 +19,7 @@ static int _PrintableString_alphabet[256] = {
0,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, /* abcdefghijklmno */
64,65,66,67,68,69,70,71,72,73,74, 0, 0, 0, 0, 0, /* pqrstuvwxyz */
};
-static int _PrintableString_code2value[74] = {
+static const int _PrintableString_code2value[74] = {
32,39,40,41,43,44,45,46,47,48,49,50,51,52,53,54,
55,56,57,58,61,63,65,66,67,68,69,70,71,72,73,74,
75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,
@@ -29,7 +29,7 @@ static int _PrintableString_code2value[74] = {
/*
* PrintableString basic type description.
*/
-static ber_tlv_tag_t asn_DEF_PrintableString_tags[] = {
+static const ber_tlv_tag_t asn_DEF_PrintableString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (19 << 2)), /* [UNIVERSAL 19] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
@@ -41,7 +41,7 @@ static int asn_DEF_PrintableString_c2v(unsigned int code) {
return _PrintableString_code2value[code];
return -1;
}
-static asn_per_constraints_t asn_DEF_PrintableString_constraints = {
+static const asn_per_constraints_t asn_DEF_PrintableString_constraints = {
{ APC_CONSTRAINED, 4, 4, 0x20, 0x39 }, /* Value */
{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
asn_DEF_PrintableString_v2c,
@@ -59,6 +59,8 @@ asn_TYPE_descriptor_t asn_DEF_PrintableString = {
OCTET_STRING_encode_xer_utf8,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_PrintableString_tags,
sizeof(asn_DEF_PrintableString_tags)
diff --git a/src/REAL.c b/src/REAL.c
index 5e93ac8..e179152 100644
--- a/src/REAL.c
+++ b/src/REAL.c
@@ -1,10 +1,10 @@
/*-
- * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2004-2013 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
-#if defined(__alpha)
-#define _ISOC99_SOURCE /* For quiet NAN, through bits/nan.h */
+#define _ISOC99_SOURCE /* For ilogb() and quiet NAN */
#define _BSD_SOURCE /* To reintroduce finite(3) */
+#if defined(__alpha)
#include <sys/resource.h> /* For INFINITY */
#endif
#include <asn_internal.h>
@@ -27,10 +27,16 @@ static volatile double real_zero GCC_NOTUSED = 0.0;
#define INFINITY (1.0/real_zero)
#endif
+#ifdef isfinite
+#define _asn_isfinite(d) isfinite(d) /* ISO C99 */
+#else
+#define _asn_isfinite(d) finite(d) /* Deprecated on Mac OS X 10.9 */
+#endif
+
/*
* REAL basic type description.
*/
-static ber_tlv_tag_t asn_DEF_REAL_tags[] = {
+static const ber_tlv_tag_t asn_DEF_REAL_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (9 << 2))
};
asn_TYPE_descriptor_t asn_DEF_REAL = {
@@ -45,6 +51,8 @@ asn_TYPE_descriptor_t asn_DEF_REAL = {
REAL_encode_xer,
REAL_decode_uper,
REAL_encode_uper,
+ REAL_decode_aper,
+ REAL_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_REAL_tags,
sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]),
@@ -88,7 +96,7 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key)
buf = specialRealValue[SRV__NOT_A_NUMBER].string;
buflen = specialRealValue[SRV__NOT_A_NUMBER].length;
return (cb(buf, buflen, app_key) < 0) ? -1 : buflen;
- } else if(!finite(d)) {
+ } else if(!_asn_isfinite(d)) {
if(copysign(1.0, d) < 0.0) {
buf = specialRealValue[SRV__MINUS_INFINITY].string;
buflen = specialRealValue[SRV__MINUS_INFINITY].length;
@@ -137,6 +145,7 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key)
dot = (buf[0] == 0x2d /* '-' */) ? (buf + 2) : (buf + 1);
if(*dot >= 0x30) {
+ if(buf != local_buf) FREEMEM(buf);
errno = EINVAL;
return -1; /* Not a dot, really */
}
@@ -157,6 +166,7 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key)
}
expptr++;
if(expptr > end) {
+ if(buf != local_buf) FREEMEM(buf);
errno = EINVAL;
return -1;
}
@@ -182,6 +192,7 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key)
}
}
if(E == end) {
+ if(buf != local_buf) FREEMEM(buf);
errno = EINVAL;
return -1; /* No promised E */
}
@@ -358,6 +369,21 @@ REAL_encode_uper(asn_TYPE_descriptor_t *td,
return OCTET_STRING_encode_uper(td, 0, sptr, po);
}
+asn_dec_rval_t
+REAL_decode_aper(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
+ void **sptr, asn_per_data_t *pd) {
+ (void)constraints; /* No PER visible constraints */
+ return OCTET_STRING_decode_aper(opt_codec_ctx, td, 0, sptr, pd);
+}
+
+asn_enc_rval_t
+REAL_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ (void)constraints; /* No PER visible constraints */
+ return OCTET_STRING_encode_aper(td, 0, sptr, po);
+}
+
int
asn_REAL2double(const REAL_t *st, double *dbl_value) {
unsigned int octv;
@@ -375,10 +401,11 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) {
octv = st->buf[0]; /* unsigned byte */
switch(octv & 0xC0) {
- case 0x40: /* X.690: 8.5.8 */
+ case 0x40: /* X.690: 8.5.6 a) => 8.5.9 */
/* "SpecialRealValue" */
/* Be liberal in what you accept...
+ * http://en.wikipedia.org/wiki/Robustness_principle
if(st->size != 1) ...
*/
@@ -389,10 +416,6 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) {
case 0x41: /* 01000001: MINUS-INFINITY */
*dbl_value = - INFINITY;
return 0;
- /*
- * The following cases are defined by
- * X.690 Amendment 1 (10/03)
- */
case 0x42: /* 01000010: NOT-A-NUMBER */
*dbl_value = NAN;
return 0;
@@ -403,21 +426,67 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) {
errno = EINVAL;
return -1;
- case 0x00: { /* X.690: 8.5.6 */
+ case 0x00: { /* X.690: 8.5.7 */
/*
- * Decimal. NR{1,2,3} format.
+ * Decimal. NR{1,2,3} format from ISO 6093.
+ * NR1: [ ]*[+-]?[0-9]+
+ * NR2: [ ]*[+-]?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)
+ * NR3: [ ]*[+-]?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)[Ee][+-]?[0-9]+
*/
double d;
+ char *buf;
+ char *endptr;
+ int used_malloc = 0;
+
+ if(octv == 0 || (octv & 0x3C)) {
+ /* Remaining values of bits 6 to 1 are Reserved. */
+ errno = EINVAL;
+ return -1;
+ }
- assert(st->buf[st->size - 1] == 0); /* Security, vashu mat' */
- d = strtod((char *)st->buf, 0);
- if(finite(d)) {
+ /* 1. By contract, an input buffer should be null-terminated.
+ * OCTET STRING decoder ensures that, as is asn_double2REAL().
+ * 2. ISO 6093 specifies COMMA as a possible decimal separator.
+ * However, strtod() can't always deal with COMMA.
+ * So her we fix both by reallocating, copying and fixing.
+ */
+ if(st->buf[st->size] || memchr(st->buf, ',', st->size)) {
+ 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;
+ /* 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];
+ }
+
+ endptr = buf;
+ d = strtod(buf, &endptr);
+ if(*endptr != '\0') {
+ /* Format is not consistent with ISO 6093 */
+ if(used_malloc) FREEMEM(buf);
+ errno = EINVAL;
+ return -1;
+ }
+ if(used_malloc) FREEMEM(buf);
+ if(_asn_isfinite(d)) {
*dbl_value = d;
return 0;
} else {
errno = ERANGE;
- return 0;
+ return -1;
}
}
}
@@ -476,13 +545,11 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) {
/* Okay, the exponent is here. Now, what about mantissa? */
end = st->buf + st->size;
- if(ptr < end) {
- for(; ptr < end; ptr++)
- m = ldexp(m, 8) + *ptr;
- }
+ for(; ptr < end; ptr++)
+ m = ldexp(m, 8) + *ptr;
if(0)
- ASN_DEBUG("m=%.10f, scF=%d, bF=%d, expval=%d, ldexp()=%f, ldexp()=%f",
+ ASN_DEBUG("m=%.10f, scF=%d, bF=%d, expval=%d, ldexp()=%f, ldexp()=%f\n",
m, scaleF, baseF, expval,
ldexp(m, expval * baseF + scaleF),
ldexp(m, scaleF) * pow(pow(2, baseF), expval)
@@ -494,7 +561,7 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) {
m = ldexp(m, scaleF) * pow(pow(2, base), expval);
*/
m = ldexp(m, expval * baseF + scaleF);
- if(finite(m)) {
+ if(_asn_isfinite(m)) {
*dbl_value = sign ? -m : m;
} else {
errno = ERANGE;
@@ -555,7 +622,7 @@ asn_double2REAL(REAL_t *st, double dbl_value) {
st->buf[0] = 0x42; /* NaN */
st->buf[1] = 0;
st->size = 1;
- } else if(!finite(dbl_value)) {
+ } else if(!_asn_isfinite(dbl_value)) {
if(copysign(1.0, dbl_value) < 0.0) {
st->buf[0] = 0x41; /* MINUS-INFINITY */
} else {
@@ -564,14 +631,14 @@ asn_double2REAL(REAL_t *st, double dbl_value) {
st->buf[1] = 0;
st->size = 1;
} else {
- if(copysign(1.0, dbl_value) < 0.0) {
- st->buf[0] = 0x80 | 0x40;
- st->buf[1] = 0;
- st->size = 2;
- } else {
+ if(copysign(1.0, dbl_value) >= 0.0) {
/* no content octets: positive zero */
st->buf[0] = 0; /* JIC */
st->size = 0;
+ } else {
+ /* Negative zero. #8.5.3, 8.5.9 */
+ st->buf[0] = 0x43;
+ st->size = 1;
}
}
return 0;
@@ -630,7 +697,7 @@ asn_double2REAL(REAL_t *st, double dbl_value) {
accum = mval << ishift;
}
- /* Adjust mantissa appropriately. */
+ /* Adjust exponent appropriately. */
expval += shift_count;
}
diff --git a/src/RELATIVE-OID.c b/src/RELATIVE-OID.c
index 983fc09..8e3e97f 100644
--- a/src/RELATIVE-OID.c
+++ b/src/RELATIVE-OID.c
@@ -13,7 +13,7 @@
/*
* RELATIVE-OID basic type description.
*/
-static ber_tlv_tag_t asn_DEF_RELATIVE_OID_tags[] = {
+static const ber_tlv_tag_t asn_DEF_RELATIVE_OID_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (13 << 2))
};
asn_TYPE_descriptor_t asn_DEF_RELATIVE_OID = {
@@ -28,6 +28,8 @@ asn_TYPE_descriptor_t asn_DEF_RELATIVE_OID = {
RELATIVE_OID_encode_xer,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_RELATIVE_OID_tags,
sizeof(asn_DEF_RELATIVE_OID_tags)
@@ -106,14 +108,12 @@ RELATIVE_OID__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void
(const char *)chunk_buf, chunk_size,
arcs, sizeof(s_arcs)/sizeof(s_arcs[0]), &endptr);
if(arcs_count < 0) {
- /* Expecting at least zero arcs */
+ /* Expecting at least one arc arcs */
return XPBD_BROKEN_ENCODING;
+ } else if(arcs_count == 0) {
+ return XPBD_NOT_BODY_IGNORE;
}
- if(endptr < chunk_end) {
- /* We have a tail of unrecognized data. Check its safety. */
- if(!xer_is_whitespace(endptr, chunk_end - endptr))
- return XPBD_BROKEN_ENCODING;
- }
+ assert(endptr == chunk_end);
if((size_t)arcs_count > sizeof(s_arcs)/sizeof(s_arcs[0])) {
arcs = (long *)MALLOC(arcs_count * sizeof(long));
@@ -164,7 +164,7 @@ RELATIVE_OID_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
}
int
-RELATIVE_OID_get_arcs(RELATIVE_OID_t *roid,
+RELATIVE_OID_get_arcs(const RELATIVE_OID_t *roid,
void *arcs, unsigned int arc_type_size, unsigned int arc_slots) {
void *arcs_end = (char *)arcs + (arc_slots * arc_type_size);
int num_arcs = 0;
diff --git a/src/T61String.c b/src/T61String.c
index 98461bb..4a6ad47 100644
--- a/src/T61String.c
+++ b/src/T61String.c
@@ -8,7 +8,7 @@
/*
* T61String basic type description.
*/
-static ber_tlv_tag_t asn_DEF_T61String_tags[] = {
+static const ber_tlv_tag_t asn_DEF_T61String_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (20 << 2)), /* [UNIVERSAL 20] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
@@ -24,6 +24,8 @@ asn_TYPE_descriptor_t asn_DEF_T61String = {
OCTET_STRING_encode_xer,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_T61String_tags,
sizeof(asn_DEF_T61String_tags)
diff --git a/src/TeletexString.c b/src/TeletexString.c
index cc2acad..40b5c4e 100644
--- a/src/TeletexString.c
+++ b/src/TeletexString.c
@@ -8,7 +8,7 @@
/*
* TeletexString basic type description.
*/
-static ber_tlv_tag_t asn_DEF_TeletexString_tags[] = {
+static const ber_tlv_tag_t asn_DEF_TeletexString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (20 << 2)), /* [UNIVERSAL 20] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), /* ... OCTET STRING */
};
@@ -24,6 +24,8 @@ asn_TYPE_descriptor_t asn_DEF_TeletexString = {
OCTET_STRING_encode_xer,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_TeletexString_tags,
sizeof(asn_DEF_TeletexString_tags)
diff --git a/src/UTCTime.c b/src/UTCTime.c
index 0abe1db..98a4c15 100644
--- a/src/UTCTime.c
+++ b/src/UTCTime.c
@@ -18,7 +18,7 @@
/*
* UTCTime basic type description.
*/
-static ber_tlv_tag_t asn_DEF_UTCTime_tags[] = {
+static const ber_tlv_tag_t asn_DEF_UTCTime_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (23 << 2)), /* [UNIVERSAL 23] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)), /* [UNIVERSAL 26] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
@@ -40,6 +40,8 @@ asn_TYPE_descriptor_t asn_DEF_UTCTime = {
UTCTime_encode_xer,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_UTCTime_tags,
sizeof(asn_DEF_UTCTime_tags)
diff --git a/src/UTF8String.c b/src/UTF8String.c
index 7e73d77..4103af3 100644
--- a/src/UTF8String.c
+++ b/src/UTF8String.c
@@ -9,7 +9,7 @@
/*
* UTF8String basic type description.
*/
-static ber_tlv_tag_t asn_DEF_UTF8String_tags[] = {
+static const ber_tlv_tag_t asn_DEF_UTF8String_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (12 << 2)), /* [UNIVERSAL 12] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), /* ... OCTET STRING */
};
@@ -25,6 +25,8 @@ asn_TYPE_descriptor_t asn_DEF_UTF8String = {
OCTET_STRING_encode_xer_utf8,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_UTF8String_tags,
sizeof(asn_DEF_UTF8String_tags)
@@ -41,7 +43,7 @@ asn_TYPE_descriptor_t asn_DEF_UTF8String = {
* This is the table of length expectations.
* The second half of this table is only applicable to the long sequences.
*/
-static int UTF8String_ht[2][16] = {
+static const int UTF8String_ht[2][16] = {
{ /* 0x0 ... 0x7 */
/* 0000..0111 */
1, 1, 1, 1, 1, 1, 1, 1,
@@ -52,7 +54,7 @@ static int UTF8String_ht[2][16] = {
4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 6, 6, -1, -1 }
};
-static int32_t UTF8String_mv[7] = { 0, 0,
+static const int32_t UTF8String_mv[7] = { 0, 0,
0x00000080,
0x00000800,
0x00010000,
diff --git a/src/UniversalString.c b/src/UniversalString.c
index 7d16781..0cffce5 100644
--- a/src/UniversalString.c
+++ b/src/UniversalString.c
@@ -9,7 +9,7 @@
/*
* UniversalString basic type description.
*/
-static ber_tlv_tag_t asn_DEF_UniversalString_tags[] = {
+static const ber_tlv_tag_t asn_DEF_UniversalString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (28 << 2)), /* [UNIVERSAL 28] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
@@ -35,6 +35,8 @@ asn_TYPE_descriptor_t asn_DEF_UniversalString = {
UniversalString_encode_xer, /* Convert into UTF-8 */
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_UniversalString_tags,
sizeof(asn_DEF_UniversalString_tags)
diff --git a/src/VideotexString.c b/src/VideotexString.c
index df7233e..e6fc423 100644
--- a/src/VideotexString.c
+++ b/src/VideotexString.c
@@ -8,7 +8,7 @@
/*
* VideotexString basic type description.
*/
-static ber_tlv_tag_t asn_DEF_VideotexString_tags[] = {
+static const ber_tlv_tag_t asn_DEF_VideotexString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (21 << 2)), /* [UNIVERSAL 21] IMPLICIT */
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
@@ -24,6 +24,8 @@ asn_TYPE_descriptor_t asn_DEF_VideotexString = {
OCTET_STRING_encode_xer,
OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_VideotexString_tags,
sizeof(asn_DEF_VideotexString_tags)
diff --git a/src/VisibleString.c b/src/VisibleString.c
index 3487b6f..20d1b21 100644
--- a/src/VisibleString.c
+++ b/src/VisibleString.c
@@ -8,7 +8,7 @@
/*
* VisibleString basic type description.
*/
-static ber_tlv_tag_t asn_DEF_VisibleString_tags[] = {
+static const ber_tlv_tag_t asn_DEF_VisibleString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)), /* [UNIVERSAL 26] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
@@ -29,6 +29,8 @@ asn_TYPE_descriptor_t asn_DEF_VisibleString = {
OCTET_STRING_encode_xer_utf8,
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
+ OCTET_STRING_decode_aper,
+ OCTET_STRING_encode_aper,
0, /* Use generic outmost tag fetcher */
asn_DEF_VisibleString_tags,
sizeof(asn_DEF_VisibleString_tags)
diff --git a/src/asn_codecs_prim.c b/src/asn_codecs_prim.c
index a9bc10d..8e604a4 100644
--- a/src/asn_codecs_prim.c
+++ b/src/asn_codecs_prim.c
@@ -6,8 +6,6 @@
#include <asn_codecs_prim.h>
#include <errno.h>
-void *talloc_asn1_ctx;
-
/*
* Decode an always-primitive type.
*/
@@ -17,7 +15,7 @@ ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
void **sptr, const void *buf_ptr, size_t size, int tag_mode) {
ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
asn_dec_rval_t rval;
- ber_tlv_len_t length;
+ ber_tlv_len_t length = 0; // =0 to avoid [incorrect] warning.
/*
* If the structure is not there, allocate it.
@@ -145,20 +143,26 @@ struct xdp_arg_s {
int want_more;
};
-
+/*
+ * Since some kinds of primitive values can be encoded using value-specific
+ * tags (<MINUS-INFINITY>, <enum-element>, etc), the primitive decoder must
+ * be supplied with such tags to parse them as needed.
+ */
static int
xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
enum xer_pbd_rval bret;
- if(arg->decoded_something) {
- if(xer_is_whitespace(chunk_buf, chunk_size))
- return 0; /* Skip it. */
- /*
- * Decoding was done once already. Prohibit doing it again.
- */
+ /*
+ * The chunk_buf is guaranteed to start at '<'.
+ */
+ assert(chunk_size && ((const char *)chunk_buf)[0] == 0x3c);
+
+ /*
+ * Decoding was performed once already. Prohibit doing it again.
+ */
+ if(arg->decoded_something)
return -1;
- }
bret = arg->prim_body_decoder(arg->type_descriptor,
arg->struct_key, chunk_buf, chunk_size);
@@ -179,13 +183,20 @@ xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size)
}
static ssize_t
-xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
+xer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
enum xer_pbd_rval bret;
+ size_t lead_wsp_size;
if(arg->decoded_something) {
- if(xer_is_whitespace(chunk_buf, chunk_size))
+ if(xer_whitespace_span(chunk_buf, chunk_size) == chunk_size) {
+ /*
+ * Example:
+ * "<INTEGER>123<!--/--> </INTEGER>"
+ * ^- chunk_buf position.
+ */
return chunk_size;
+ }
/*
* Decoding was done once already. Prohibit doing it again.
*/
@@ -205,6 +216,10 @@ xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_m
return -1;
}
+ lead_wsp_size = xer_whitespace_span(chunk_buf, chunk_size);
+ chunk_buf = (const char *)chunk_buf + lead_wsp_size;
+ chunk_size -= lead_wsp_size;
+
bret = arg->prim_body_decoder(arg->type_descriptor,
arg->struct_key, chunk_buf, chunk_size);
switch(bret) {
@@ -217,7 +232,7 @@ xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_m
arg->decoded_something = 1;
/* Fall through */
case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
- return chunk_size;
+ return lead_wsp_size + chunk_size;
}
return -1;
@@ -255,7 +270,7 @@ xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
xml_tag, buf_ptr, size,
- xer_decode__unexpected_tag, xer_decode__body);
+ xer_decode__unexpected_tag, xer_decode__primitive_body);
switch(rc.code) {
case RC_OK:
if(!s_arg.decoded_something) {
diff --git a/src/ber_decoder.c b/src/ber_decoder.c
index 601f66c..0f99400 100644
--- a/src/ber_decoder.c
+++ b/src/ber_decoder.c
@@ -206,7 +206,7 @@ ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
*/
len_len = ber_fetch_length(tlv_constr,
(const char *)ptr + tag_len, size - tag_len, &tlv_len);
- ASN_DEBUG("Fetchinig len = %ld", (long)len_len);
+ ASN_DEBUG("Fetching len = %ld", (long)len_len);
switch(len_len) {
case -1: RETURN(RC_FAIL);
case 0: RETURN(RC_WMORE);
diff --git a/src/constr_CHOICE.c b/src/constr_CHOICE.c
index 4f0d992..18c24cd 100644
--- a/src/constr_CHOICE.c
+++ b/src/constr_CHOICE.c
@@ -183,11 +183,11 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
}
do {
- asn_TYPE_tag2member_t *t2m;
+ const asn_TYPE_tag2member_t *t2m;
asn_TYPE_tag2member_t key;
key.el_tag = tlv_tag;
- t2m = (asn_TYPE_tag2member_t *)bsearch(&key,
+ t2m = (const asn_TYPE_tag2member_t *)bsearch(&key,
specs->tag2el, specs->tag2el_count,
sizeof(specs->tag2el[0]), _search4tag);
if(t2m) {
@@ -445,7 +445,7 @@ CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
}
ber_tlv_tag_t
-CHOICE_outmost_tag(asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber_tlv_tag_t tag) {
+CHOICE_outmost_tag(const asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber_tlv_tag_t tag) {
asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
int present;
@@ -458,7 +458,7 @@ CHOICE_outmost_tag(asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber
present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size);
if(present > 0 || present <= td->elements_count) {
- asn_TYPE_member_t *elm = &td->elements[present-1];
+ const asn_TYPE_member_t *elm = &td->elements[present-1];
const void *memb_ptr;
if(elm->flags & ATF_POINTER) {
@@ -535,7 +535,7 @@ CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
#undef XER_ADVANCE
#define XER_ADVANCE(num_bytes) do { \
size_t num = num_bytes; \
- buf_ptr = ((const char *)buf_ptr) + num;\
+ buf_ptr = (const void *)(((const char *)buf_ptr) + num); \
size -= num; \
consumed_myself += num; \
} while(0)
@@ -904,7 +904,88 @@ CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
elm->name, td->name, rv.code);
return rv;
}
-
+
+asn_dec_rval_t
+CHOICE_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+ asn_dec_rval_t rv;
+ asn_per_constraint_t *ct;
+ asn_TYPE_member_t *elm; /* CHOICE's element */
+ void *memb_ptr;
+ void **memb_ptr2;
+ void *st = *sptr;
+ int value;
+
+ if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
+ _ASN_DECODE_FAILED;
+
+ /*
+ * Create the target structure if it is not present already.
+ */
+ if(!st) {
+ st = *sptr = CALLOC(1, specs->struct_size);
+ if(!st) _ASN_DECODE_FAILED;
+ }
+
+ if(constraints) ct = &constraints->value;
+ else if(td->per_constraints) ct = &td->per_constraints->value;
+ else ct = 0;
+
+ if(ct && ct->flags & APC_EXTENSIBLE) {
+ value = per_get_few_bits(pd, 1);
+ if(value < 0) _ASN_DECODE_STARVED;
+ if(value) ct = 0; /* Not restricted */
+ }
+
+ if(ct && ct->range_bits >= 0) {
+ value = per_get_few_bits(pd, ct->range_bits);
+ if(value < 0) _ASN_DECODE_STARVED;
+ ASN_DEBUG("CHOICE %s got index %d in range %d",
+ td->name, value, ct->range_bits);
+ if(value > ct->upper_bound)
+ _ASN_DECODE_FAILED;
+ } else {
+ if(specs->ext_start == -1)
+ _ASN_DECODE_FAILED;
+ value = uper_get_nsnnwn(pd);
+ if(value < 0) _ASN_DECODE_STARVED;
+ value += specs->ext_start;
+ if(value >= td->elements_count)
+ _ASN_DECODE_FAILED;
+ }
+
+ /* Adjust if canonical order is different from natural order */
+ if(specs->canonical_order)
+ value = specs->canonical_order[value];
+
+ /* Set presence to be able to free it later */
+ _set_present_idx(st, specs->pres_offset, specs->pres_size, value + 1);
+
+ elm = &td->elements[value];
+ if(elm->flags & ATF_POINTER) {
+ /* Member is a pointer to another structure */
+ memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+ } else {
+ memb_ptr = (char *)st + elm->memb_offset;
+ memb_ptr2 = &memb_ptr;
+ }
+ ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name);
+
+ if(ct && ct->range_bits >= 0) {
+ rv = elm->type->aper_decoder(opt_codec_ctx, elm->type,
+ elm->per_constraints, memb_ptr2, pd);
+ } else {
+ rv = uper_open_type_get(opt_codec_ctx, elm->type,
+ elm->per_constraints, memb_ptr2, pd);
+ }
+
+ if(rv.code != RC_OK)
+ ASN_DEBUG("Failed to decode %s in %s (CHOICE) %d",
+ elm->name, td->name, rv.code);
+ return rv;
+}
+
asn_enc_rval_t
CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
@@ -913,10 +994,11 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraint_t *ct;
void *memb_ptr;
int present;
+ int present_enc;
if(!sptr) _ASN_ENCODE_FAILED;
- ASN_DEBUG("Encoding %s as CHOICE", td->name);
+ ASN_DEBUG("Encoding %s as CHOICE using UPER", td->name);
if(constraints) ct = &constraints->value;
else if(td->per_constraints) ct = &td->per_constraints->value;
@@ -934,15 +1016,17 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
else
present--;
+ ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
+
/* Adjust if canonical order is different from natural order */
if(specs->canonical_order)
- present = specs->canonical_order[present];
-
- ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
+ present_enc = specs->canonical_order[present];
+ else
+ present_enc = present;
if(ct && ct->range_bits >= 0) {
- if(present < ct->lower_bound
- || present > ct->upper_bound) {
+ if(present_enc < ct->lower_bound
+ || present_enc > ct->upper_bound) {
if(ct->flags & APC_EXTENSIBLE) {
if(per_put_few_bits(po, 1, 1))
_ASN_ENCODE_FAILED;
@@ -966,7 +1050,7 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
}
if(ct && ct->range_bits >= 0) {
- if(per_put_few_bits(po, present, ct->range_bits))
+ if(per_put_few_bits(po, present_enc, ct->range_bits))
_ASN_ENCODE_FAILED;
return elm->type->uper_encoder(elm->type, elm->per_constraints,
@@ -975,7 +1059,7 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
asn_enc_rval_t rval;
if(specs->ext_start == -1)
_ASN_ENCODE_FAILED;
- if(uper_put_nsnnwn(po, present - specs->ext_start))
+ if(uper_put_nsnnwn(po, present_enc - specs->ext_start))
_ASN_ENCODE_FAILED;
if(uper_open_type_put(elm->type, elm->per_constraints,
memb_ptr, po))
@@ -984,7 +1068,87 @@ CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
_ASN_ENCODED_OK(rval);
}
}
-
+
+asn_enc_rval_t
+CHOICE_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
+ asn_TYPE_member_t *elm; /* CHOICE's element */
+ asn_per_constraint_t *ct;
+ void *memb_ptr;
+ int present;
+
+ if(!sptr) _ASN_ENCODE_FAILED;
+
+ ASN_DEBUG("Encoding %s as CHOICE using ALIGNED PER", td->name);
+
+ if(constraints) ct = &constraints->value;
+ else if(td->per_constraints) ct = &td->per_constraints->value;
+ else ct = 0;
+
+ present = _fetch_present_idx(sptr,
+ specs->pres_offset, specs->pres_size);
+
+ /*
+ * If the structure was not initialized properly, it cannot be encoded:
+ * can't deduce what to encode in the choice type.
+ */
+ if(present <= 0 || present > td->elements_count)
+ _ASN_ENCODE_FAILED;
+ else
+ present--;
+
+ /* Adjust if canonical order is different from natural order */
+ if(specs->canonical_order)
+ present = specs->canonical_order[present];
+
+ ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
+
+ if(ct && ct->range_bits >= 0) {
+ if(present < ct->lower_bound
+ || present > ct->upper_bound) {
+ if(ct->flags & APC_EXTENSIBLE) {
+ if(per_put_few_bits(po, 1, 1))
+ _ASN_ENCODE_FAILED;
+ } else {
+ _ASN_ENCODE_FAILED;
+ }
+ ct = 0;
+ }
+ }
+ if(ct && ct->flags & APC_EXTENSIBLE) {
+ if(per_put_few_bits(po, 0, 1))
+ _ASN_ENCODE_FAILED;
+ }
+
+ elm = &td->elements[present];
+ if(elm->flags & ATF_POINTER) {
+ /* Member is a pointer to another structure */
+ memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
+ if(!memb_ptr) _ASN_ENCODE_FAILED;
+ } else {
+ memb_ptr = (char *)sptr + elm->memb_offset;
+ }
+
+ if(ct && ct->range_bits >= 0) {
+ if(per_put_few_bits(po, present, ct->range_bits))
+ _ASN_ENCODE_FAILED;
+
+ return elm->type->aper_encoder(elm->type, elm->per_constraints,
+ memb_ptr, po);
+ } else {
+ asn_enc_rval_t rval;
+ if(specs->ext_start == -1)
+ _ASN_ENCODE_FAILED;
+ if(aper_put_nsnnwn(po, ct->range_bits, present - specs->ext_start))
+ _ASN_ENCODE_FAILED;
+ if(aper_open_type_put(elm->type, elm->per_constraints,
+ memb_ptr, po))
+ _ASN_ENCODE_FAILED;
+ rval.encoded = 0;
+ _ASN_ENCODED_OK(rval);
+ }
+}
int
CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
diff --git a/src/constr_SEQUENCE.c b/src/constr_SEQUENCE.c
index db3c925..21e5190 100644
--- a/src/constr_SEQUENCE.c
+++ b/src/constr_SEQUENCE.c
@@ -34,7 +34,7 @@
#undef ADVANCE
#define ADVANCE(num_bytes) do { \
size_t num = num_bytes; \
- ptr = ((const char *)ptr) + num;\
+ ptr = ((const char *)ptr) + num; \
size -= num; \
if(ctx->left >= 0) \
ctx->left -= num; \
@@ -310,16 +310,16 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
* Resort to a binary search over
* sorted array of tags.
*/
- asn_TYPE_tag2member_t *t2m;
+ const asn_TYPE_tag2member_t *t2m;
asn_TYPE_tag2member_t key;
key.el_tag = tlv_tag;
key.el_no = edx;
- t2m = (asn_TYPE_tag2member_t *)bsearch(&key,
+ t2m = (const asn_TYPE_tag2member_t *)bsearch(&key,
specs->tag2el, specs->tag2el_count,
sizeof(specs->tag2el[0]), _t2e_cmp);
if(t2m) {
- asn_TYPE_tag2member_t *best = 0;
- asn_TYPE_tag2member_t *t2m_f, *t2m_l;
+ const asn_TYPE_tag2member_t *best = 0;
+ const asn_TYPE_tag2member_t *t2m_f, *t2m_l;
int edx_max = edx + elements[edx].optional;
/*
* Rewind to the first element with that tag,
@@ -667,8 +667,7 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
if(elm->flags & ATF_POINTER) {
/* Member is a pointer to another structure */
- memb_ptr2 = (void **)((char *)st
- + elm->memb_offset);
+ memb_ptr2 = (void **)((char *)st + elm->memb_offset);
} else {
memb_ptr = (char *)st + elm->memb_offset;
memb_ptr2 = &memb_ptr;
@@ -1143,6 +1142,219 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
bmlength = uper_get_nslength(pd);
if(bmlength < 0) _ASN_DECODE_STARVED;
+ ASN_DEBUG("Extensions %ld present in %s", (long)bmlength, td->name);
+
+ epres = (uint8_t *)MALLOC((bmlength + 15) >> 3);
+ if(!epres) _ASN_DECODE_STARVED;
+
+ /* Get the extensions map */
+ if(per_get_many_bits(pd, epres, 0, bmlength))
+ _ASN_DECODE_STARVED;
+
+ memset(&epmd, 0, sizeof(epmd));
+ epmd.buffer = epres;
+ epmd.nbits = bmlength;
+ ASN_DEBUG("Read in extensions bitmap for %s of %ld bits (%x..)",
+ td->name, (long)bmlength, *epres);
+
+ /* Go over extensions and read them in */
+ for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+ int present;
+
+ if(!IN_EXTENSION_GROUP(specs, edx)) {
+ ASN_DEBUG("%d is not extension", edx);
+ continue;
+ }
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+ } else {
+ memb_ptr = (void *)((char *)st + elm->memb_offset);
+ memb_ptr2 = &memb_ptr;
+ }
+
+ present = per_get_few_bits(&epmd, 1);
+ if(present <= 0) {
+ if(present < 0) break; /* No more extensions */
+ continue;
+ }
+
+ ASN_DEBUG("Decoding member %s in %s %p", elm->name, td->name, *memb_ptr2);
+ rv = uper_open_type_get(opt_codec_ctx, elm->type,
+ elm->per_constraints, memb_ptr2, pd);
+ if(rv.code != RC_OK) {
+ FREEMEM(epres);
+ return rv;
+ }
+ }
+
+ /* Skip over overflow extensions which aren't present
+ * in this system's version of the protocol */
+ for(;;) {
+ ASN_DEBUG("Getting overflow extensions");
+ switch(per_get_few_bits(&epmd, 1)) {
+ case -1: break;
+ case 0: continue;
+ default:
+ if(uper_open_type_skip(opt_codec_ctx, pd)) {
+ FREEMEM(epres);
+ _ASN_DECODE_STARVED;
+ }
+ }
+ break;
+ }
+
+ FREEMEM(epres);
+ }
+
+ /* Fill DEFAULT members in extensions */
+ for(edx = specs->roms_count; edx < specs->roms_count
+ + specs->aoms_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void **memb_ptr2; /* Pointer to member pointer */
+
+ if(!elm->default_value) continue;
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)st
+ + elm->memb_offset);
+ if(*memb_ptr2) continue;
+ } else {
+ continue; /* Extensions are all optionals */
+ }
+
+ /* Set default value */
+ if(elm->default_value(1, memb_ptr2)) {
+ _ASN_DECODE_FAILED;
+ }
+ }
+
+ rv.consumed = 0;
+ rv.code = RC_OK;
+ return rv;
+}
+
+asn_dec_rval_t
+SEQUENCE_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
+ void *st = *sptr; /* Target structure. */
+ int extpresent; /* Extension additions are present */
+ uint8_t *opres; /* Presence of optional root members */
+ asn_per_data_t opmd;
+ asn_dec_rval_t rv;
+ int edx;
+
+ (void)constraints;
+
+ if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
+ _ASN_DECODE_FAILED;
+
+ if(!st) {
+ st = *sptr = CALLOC(1, specs->struct_size);
+ if(!st) _ASN_DECODE_FAILED;
+ }
+
+ ASN_DEBUG("Decoding %s as SEQUENCE (APER)", td->name);
+
+ /* Handle extensions */
+ if(specs->ext_before >= 0) {
+ extpresent = per_get_few_bits(pd, 1);
+ if(extpresent < 0) _ASN_DECODE_STARVED;
+ } else {
+ extpresent = 0;
+ }
+
+ /* Prepare a place and read-in the presence bitmap */
+ memset(&opmd, 0, sizeof(opmd));
+ if(specs->roms_count) {
+ opres = (uint8_t *)MALLOC(((specs->roms_count + 7) >> 3) + 1);
+ if(!opres) _ASN_DECODE_FAILED;
+ /* Get the presence map */
+ if(per_get_many_bits(pd, opres, 0, specs->roms_count)) {
+ FREEMEM(opres);
+ _ASN_DECODE_STARVED;
+ }
+ opmd.buffer = opres;
+ opmd.nbits = specs->roms_count;
+ ASN_DEBUG("Read in presence bitmap for %s of %d bits (%x..)",
+ td->name, specs->roms_count, *opres);
+ } else {
+ opres = 0;
+ }
+
+ /*
+ * Get the sequence ROOT elements.
+ */
+ for(edx = 0; edx < td->elements_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+
+ if(IN_EXTENSION_GROUP(specs, edx))
+ continue;
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)st + elm->memb_offset);
+ } else {
+ memb_ptr = (char *)st + elm->memb_offset;
+ memb_ptr2 = &memb_ptr;
+ }
+
+ /* Deal with optionality */
+ if(elm->optional) {
+ int present = per_get_few_bits(&opmd, 1);
+ ASN_DEBUG("Member %s->%s is optional, p=%d (%d->%d)",
+ td->name, elm->name, present,
+ (int)opmd.nboff, (int)opmd.nbits);
+ if(present == 0) {
+ /* This element is not present */
+ if(elm->default_value) {
+ /* Fill-in DEFAULT */
+ if(elm->default_value(1, memb_ptr2)) {
+ FREEMEM(opres);
+ _ASN_DECODE_FAILED;
+ }
+ ASN_DEBUG("Filled-in default");
+ }
+ /* The member is just not present */
+ continue;
+ }
+ /* Fall through */
+ }
+
+ /* Fetch the member from the stream */
+ ASN_DEBUG("Decoding member %s in %s", elm->name, td->name);
+ rv = elm->type->aper_decoder(opt_codec_ctx, elm->type,
+ elm->per_constraints, memb_ptr2, pd);
+ if(rv.code != RC_OK) {
+ ASN_DEBUG("Failed decode %s in %s",
+ elm->name, td->name);
+ FREEMEM(opres);
+ return rv;
+ }
+ }
+
+ /* Optionality map is not needed anymore */
+ FREEMEM(opres);
+
+ /*
+ * Deal with extensions.
+ */
+ if(extpresent) {
+ ssize_t bmlength;
+ uint8_t *epres; /* Presence of extension members */
+ asn_per_data_t epmd;
+
+ bmlength = uper_get_nslength(pd);
+ if(bmlength < 0) _ASN_DECODE_STARVED;
+
ASN_DEBUG("Extensions %d present in %s", bmlength, td->name);
epres = (uint8_t *)MALLOC((bmlength + 15) >> 3);
@@ -1283,7 +1495,7 @@ SEQUENCE_handle_extensions(asn_TYPE_descriptor_t *td, void *sptr,
if(po1 && per_put_few_bits(po1, present, 1))
return -1;
/* Encode as open type field */
- if(po2 && present && uper_open_type_put(elm->type,
+ if(po2 && present && aper_open_type_put(elm->type,
elm->per_constraints, *memb_ptr2, po2))
return -1;
@@ -1421,3 +1633,130 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td,
_ASN_ENCODED_OK(er);
}
+asn_enc_rval_t
+SEQUENCE_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_SEQUENCE_specifics_t *specs
+ = (asn_SEQUENCE_specifics_t *)td->specifics;
+ asn_enc_rval_t er;
+ int n_extensions;
+ int edx;
+ int i;
+
+ (void)constraints;
+
+ if(!sptr)
+ _ASN_ENCODE_FAILED;
+
+ er.encoded = 0;
+
+ ASN_DEBUG("Encoding %s as SEQUENCE (APER)", td->name);
+
+ /*
+ * X.691#18.1 Whether structure is extensible
+ * and whether to encode extensions
+ */
+ if(specs->ext_before >= 0) {
+ n_extensions = SEQUENCE_handle_extensions(td, sptr, 0, 0);
+ per_put_few_bits(po, n_extensions ? 1 : 0, 1);
+ } else {
+ n_extensions = 0; /* There are no extensions to encode */
+ }
+
+ /* Encode a presence bitmap */
+ for(i = 0; i < specs->roms_count; i++) {
+ asn_TYPE_member_t *elm;
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+ int present;
+
+ edx = specs->oms[i];
+ elm = &td->elements[edx];
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
+ present = (*memb_ptr2 != 0);
+ } else {
+ memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+ memb_ptr2 = &memb_ptr;
+ present = 1;
+ }
+
+ /* Eliminate default values */
+ if(present && elm->default_value
+ && elm->default_value(0, memb_ptr2) == 1)
+ present = 0;
+
+ ASN_DEBUG("Element %s %s %s->%s is %s",
+ elm->flags & ATF_POINTER ? "ptr" : "inline",
+ elm->default_value ? "def" : "wtv",
+ td->name, elm->name, present ? "present" : "absent");
+ if(per_put_few_bits(po, present, 1))
+ _ASN_ENCODE_FAILED;
+ }
+
+ /*
+ * Encode the sequence ROOT elements.
+ */
+ ASN_DEBUG("ext_after = %d, ec = %d, eb = %d", specs->ext_after, td->elements_count, specs->ext_before);
+ for(edx = 0; edx < ((specs->ext_after < 0)
+ ? td->elements_count : specs->ext_before - 1); edx++) {
+
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+
+ if(IN_EXTENSION_GROUP(specs, edx))
+ continue;
+
+ ASN_DEBUG("About to encode %s", elm->type->name);
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
+ if(!*memb_ptr2) {
+ ASN_DEBUG("Element %s %d not present",
+ elm->name, edx);
+ if(elm->optional)
+ continue;
+ /* Mandatory element is missing */
+ _ASN_ENCODE_FAILED;
+ }
+ } else {
+ memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+ memb_ptr2 = &memb_ptr;
+ }
+
+ /* Eliminate default values */
+ if(elm->default_value && elm->default_value(0, memb_ptr2) == 1)
+ continue;
+
+ ASN_DEBUG("Encoding %s->%s", td->name, elm->name);
+ er = elm->type->aper_encoder(elm->type, elm->per_constraints,
+ *memb_ptr2, po);
+ if(er.encoded == -1)
+ return er;
+ }
+
+ /* No extensions to encode */
+ if(!n_extensions) _ASN_ENCODED_OK(er);
+
+ ASN_DEBUG("Length of %d bit-map", n_extensions);
+ /* #18.8. Write down the presence bit-map length. */
+ if(aper_put_nslength(po, n_extensions))
+ _ASN_ENCODE_FAILED;
+
+ ASN_DEBUG("Bit-map of %d elements", n_extensions);
+ /* #18.7. Encoding the extensions presence bit-map. */
+ /* TODO: act upon NOTE in #18.7 for canonical PER */
+ if(SEQUENCE_handle_extensions(td, sptr, po, 0) != n_extensions)
+ _ASN_ENCODE_FAILED;
+
+ ASN_DEBUG("Writing %d extensions", n_extensions);
+ /* #18.9. Encode extensions as open type fields. */
+ if(SEQUENCE_handle_extensions(td, sptr, 0, po) != n_extensions)
+ _ASN_ENCODE_FAILED;
+
+ _ASN_ENCODED_OK(er);
+}
diff --git a/src/constr_SEQUENCE_OF.c b/src/constr_SEQUENCE_OF.c
index aa10117..6981c8b 100644
--- a/src/constr_SEQUENCE_OF.c
+++ b/src/constr_SEQUENCE_OF.c
@@ -164,7 +164,7 @@ SEQUENCE_OF_encode_uper(asn_TYPE_descriptor_t *td,
if(ct) {
int not_in_root = (list->count < ct->lower_bound
|| list->count > ct->upper_bound);
- ASN_DEBUG("lb %ld ub %ld %s",
+ ASN_DEBUG("lb %lld ub %lld %s",
ct->lower_bound, ct->upper_bound,
ct->flags & APC_EXTENSIBLE ? "ext" : "fix");
if(ct->flags & APC_EXTENSIBLE) {
@@ -206,3 +206,70 @@ SEQUENCE_OF_encode_uper(asn_TYPE_descriptor_t *td,
_ASN_ENCODED_OK(er);
}
+asn_enc_rval_t
+SEQUENCE_OF_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ asn_anonymous_sequence_ *list;
+ asn_per_constraint_t *ct;
+ asn_enc_rval_t er;
+ asn_TYPE_member_t *elm = td->elements;
+ int seq;
+
+ if(!sptr) _ASN_ENCODE_FAILED;
+ list = _A_SEQUENCE_FROM_VOID(sptr);
+
+ er.encoded = 0;
+
+ ASN_DEBUG("Encoding %s as SEQUENCE OF size (%d) using ALIGNED PER", td->name, list->count);
+
+ if(constraints) ct = &constraints->size;
+ else if(td->per_constraints) ct = &td->per_constraints->size;
+ else ct = 0;
+
+ /* If extensible constraint, check if size is in root */
+ if(ct) {
+ int not_in_root = (list->count < ct->lower_bound
+ || list->count > ct->upper_bound);
+ ASN_DEBUG("lb %lld ub %lld %s",
+ ct->lower_bound, ct->upper_bound,
+ ct->flags & APC_EXTENSIBLE ? "ext" : "fix");
+ if(ct->flags & APC_EXTENSIBLE) {
+ /* Declare whether size is in extension root */
+ if(per_put_few_bits(po, not_in_root, 1))
+ _ASN_ENCODE_FAILED;
+ if(not_in_root) ct = 0;
+ } else if(not_in_root && ct->effective_bits >= 0)
+ _ASN_ENCODE_FAILED;
+ }
+
+ if(ct && ct->effective_bits >= 0) {
+ /* X.691, #19.5: No length determinant */
+// if(per_put_few_bits(po, list->count - ct->lower_bound,
+// ct->effective_bits))
+// _ASN_ENCODE_FAILED;
+ if (aper_put_length(po, ct->upper_bound - ct->lower_bound + 1, list->count - ct->lower_bound) < 0)
+ _ASN_ENCODE_FAILED;
+ }
+
+ for(seq = -1; seq < list->count;) {
+ ssize_t mayEncode;
+ if(seq < 0) seq = 0;
+ if(ct && ct->effective_bits >= 0) {
+ mayEncode = list->count;
+ } else {
+ mayEncode = aper_put_length(po, -1, list->count - seq);
+ if(mayEncode < 0) _ASN_ENCODE_FAILED;
+ }
+
+ while(mayEncode--) {
+ void *memb_ptr = list->array[seq++];
+ if(!memb_ptr) _ASN_ENCODE_FAILED;
+ er = elm->type->aper_encoder(elm->type,
+ elm->per_constraints, memb_ptr, po);
+ if(er.encoded == -1)
+ _ASN_ENCODE_FAILED;
+ }
+ }
+
+ _ASN_ENCODED_OK(er);
+}
diff --git a/src/constr_SET.c b/src/constr_SET.c
index ecf5661..8a124c0 100644
--- a/src/constr_SET.c
+++ b/src/constr_SET.c
@@ -175,7 +175,7 @@ SET_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
* for optimization.
*/
for(;; ctx->step = 0) {
- asn_TYPE_tag2member_t *t2m;
+ const asn_TYPE_tag2member_t *t2m;
asn_TYPE_tag2member_t key;
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
@@ -225,7 +225,7 @@ SET_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
}
key.el_tag = tlv_tag;
- t2m = (asn_TYPE_tag2member_t *)bsearch(&key,
+ t2m = (const asn_TYPE_tag2member_t *)bsearch(&key,
specs->tag2el, specs->tag2el_count,
sizeof(specs->tag2el[0]), _t2e_cmp);
if(t2m) {
@@ -404,7 +404,7 @@ _SET_is_populated(asn_TYPE_descriptor_t *td, void *st) {
unsigned int midx, pres, must;
midx = edx/(8 * sizeof(specs->_mandatory_elements[0]));
- pres = ((unsigned int *)((char *)st+specs->pres_offset))[midx];
+ pres = ((unsigned int *)((char *)st + specs->pres_offset))[midx];
must = sys_ntohl(specs->_mandatory_elements[midx]);
if((pres & must) == must) {
@@ -439,7 +439,8 @@ SET_encode_der(asn_TYPE_descriptor_t *td,
size_t computed_size = 0;
asn_enc_rval_t er;
int t2m_build_own = (specs->tag2el_count != td->elements_count);
- asn_TYPE_tag2member_t *t2m;
+ const asn_TYPE_tag2member_t *t2m;
+ asn_TYPE_tag2member_t *t2m_build;
int t2m_count;
ssize_t ret;
int edx;
@@ -448,17 +449,16 @@ SET_encode_der(asn_TYPE_descriptor_t *td,
* Use existing, or build our own tags map.
*/
if(t2m_build_own) {
- t2m = (asn_TYPE_tag2member_t *)alloca(
- td->elements_count * sizeof(t2m[0]));
- if(!t2m) _ASN_ENCODE_FAILED; /* There are such platforms */
+ 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_count = 0;
} else {
+ t2m_build = NULL;
/*
* There is no untagged CHOICE in this SET.
* Employ existing table.
*/
- t2m = specs->tag2el;
- t2m_count = specs->tag2el_count;
}
/*
@@ -479,8 +479,8 @@ SET_encode_der(asn_TYPE_descriptor_t *td,
/* Mandatory elements missing */
_ASN_ENCODE_FAILED;
if(t2m_build_own) {
- t2m[t2m_count].el_no = edx;
- t2m[t2m_count].el_tag = 0;
+ t2m_build[t2m_count].el_no = edx;
+ t2m_build[t2m_count].el_tag = 0;
t2m_count++;
}
continue;
@@ -499,8 +499,8 @@ SET_encode_der(asn_TYPE_descriptor_t *td,
* Remember the outmost tag of this member.
*/
if(t2m_build_own) {
- t2m[t2m_count].el_no = edx;
- t2m[t2m_count].el_tag = asn_TYPE_outmost_tag(
+ t2m_build[t2m_count].el_no = edx;
+ t2m_build[t2m_count].el_tag = asn_TYPE_outmost_tag(
elm->type, memb_ptr, elm->tag_mode, elm->tag);
t2m_count++;
} else {
@@ -513,18 +513,21 @@ SET_encode_der(asn_TYPE_descriptor_t *td,
/*
* Finalize order of the components.
*/
- assert(t2m_count == td->elements_count);
if(t2m_build_own) {
/*
* Sort the underlying members according to their
* canonical tags order. DER encoding mandates it.
*/
- qsort(t2m, t2m_count, sizeof(specs->tag2el[0]), _t2e_cmp);
+ qsort(t2m_build, t2m_count, sizeof(specs->tag2el[0]), _t2e_cmp);
+ t2m = t2m_build;
} else {
/*
* Tags are already sorted by the compiler.
*/
+ t2m = specs->tag2el;
+ t2m_count = specs->tag2el_count;
}
+ assert(t2m_count == td->elements_count);
/*
* Encode the TLV for the sequence itself.
@@ -570,6 +573,186 @@ SET_encode_der(asn_TYPE_descriptor_t *td,
_ASN_ENCODED_OK(er);
}
+asn_enc_rval_t
+SET_encode_uper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints,
+ void *sptr,
+ asn_per_outp_t *po) {
+ _ASN_ENCODE_FAILED;
+}
+
+asn_dec_rval_t
+SET_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ _ASN_DECODE_FAILED;
+}
+
+asn_enc_rval_t
+SET_encode_aper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints,
+ void *sptr,
+ asn_per_outp_t *po) {
+ asn_SET_specifics_t *specs = (asn_SET_specifics_t *)td->specifics;
+ asn_enc_rval_t er;
+ int edx;
+ int t2m_build_own = (specs->tag2el_count != td->elements_count);
+ const asn_TYPE_tag2member_t *t2m;
+ asn_TYPE_tag2member_t *t2m_build;
+ int t2m_count;
+
+ (void)constraints;
+
+ if(!sptr)
+ _ASN_ENCODE_FAILED;
+
+ er.encoded = 0;
+
+ ASN_DEBUG("Encoding %s as SET (APER) map %d", td->name, specs->_mandatory_elements[0]);
+
+ /*
+ * Use existing, or build our own tags map.
+ */
+ if(t2m_build_own) {
+ t2m_build = (asn_TYPE_tag2member_t *)alloca(
+ td->elements_count * sizeof(t2m[0]));
+ if(!t2m_build) _ASN_ENCODE_FAILED; /* There are such platforms */
+ t2m_count = 0;
+ } else {
+ t2m_build = NULL;
+ /*
+ * There is no untagged CHOICE in this SET.
+ * Employ existing table.
+ */
+ }
+
+ /*
+ * Gather the length of the underlying members sequence.
+ */
+ for(edx = 0; edx < td->elements_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ void *memb_ptr;
+
+ /*
+ * Compute the length of the encoding of this member.
+ */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
+ if(!memb_ptr) {
+ if(!elm->optional)
+ /* Mandatory elements missing */
+ _ASN_ENCODE_FAILED;
+ if(t2m_build_own) {
+ t2m_build[t2m_count].el_no = edx;
+ t2m_build[t2m_count].el_tag = 0;
+ t2m_count++;
+ }
+ continue;
+ }
+ } else {
+ memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+ }
+
+ /*
+ * Remember the outmost tag of this member.
+ */
+ if(t2m_build_own) {
+ t2m_build[t2m_count].el_no = edx;
+ t2m_build[t2m_count].el_tag = asn_TYPE_outmost_tag(
+ elm->type, memb_ptr, elm->tag_mode, elm->tag);
+ t2m_count++;
+ } else {
+ /*
+ * No dynamic sorting is necessary.
+ */
+ }
+ }
+
+ /*
+ * Finalize order of the components.
+ */
+ assert(t2m_count == td->elements_count);
+ if(t2m_build_own) {
+ /*
+ * Sort the underlying members according to their
+ * canonical tags order. DER encoding mandates it.
+ */
+ qsort(t2m_build, t2m_count, sizeof(specs->tag2el[0]), _t2e_cmp);
+ t2m = t2m_build;
+ } else {
+ /*
+ * Tags are already sorted by the compiler.
+ */
+ t2m = specs->tag2el;
+ t2m_count = specs->tag2el_count;
+ }
+ assert(t2m_count == td->elements_count);
+
+ for(edx = 0; edx < td->elements_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[t2m[edx].el_no];
+// asn_enc_rval_t tmper;
+// void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+ int present;
+
+ /* Fetch the pointer to this member */
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
+ present = (*memb_ptr2 != 0);
+ } else {
+// memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+// memb_ptr2 = &memb_ptr;
+ present = 1;
+ continue;
+ }
+
+// /* Eliminate default values */
+// if(present && elm->default_value
+// && elm->default_value(0, memb_ptr2) == 1)
+// present = 0;
+
+ ASN_DEBUG("Element %s %s %s->%s is %s",
+ elm->flags & ATF_POINTER ? "ptr" : "inline",
+ elm->default_value ? "def" : "wtv",
+ td->name, elm->name, present ? "present" : "absent");
+ if(per_put_few_bits(po, present << 7, 8))
+ _ASN_ENCODE_FAILED;
+ }
+
+ /*
+ * Encode all members.
+ */
+ for(edx = 0; edx < td->elements_count; edx++) {
+ asn_TYPE_member_t *elm = &td->elements[edx];
+ asn_enc_rval_t tmper;
+ void *memb_ptr; /* Pointer to the member */
+ void **memb_ptr2; /* Pointer to that pointer */
+
+ /* Encode according to the tag order */
+// elm = &td->elements[t2m[edx].el_no];
+
+ if(elm->flags & ATF_POINTER) {
+ memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
+ if(!*memb_ptr2) {
+ ASN_DEBUG("Element %s %d not present",
+ elm->name, edx);
+ if(elm->optional)
+ continue;
+ /* Mandatory element is missing */
+ _ASN_ENCODE_FAILED;
+ }
+ } else {
+ memb_ptr = (void *)((char *)sptr + elm->memb_offset);
+ memb_ptr2 = &memb_ptr;
+ }
+ tmper = elm->type->aper_encoder(elm->type, elm->per_constraints,
+ *memb_ptr2, po);
+ if(tmper.encoded == -1)
+ return tmper;
+ }
+
+ _ASN_ENCODED_OK(er);
+}
+
#undef XER_ADVANCE
#define XER_ADVANCE(num_bytes) do { \
size_t num = num_bytes; \
@@ -648,8 +831,7 @@ SET_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
if(elm->flags & ATF_POINTER) {
/* Member is a pointer to another structure */
- memb_ptr2 = (void **)((char *)st
- + elm->memb_offset);
+ memb_ptr2 = (void **)((char *)st + elm->memb_offset);
} else {
memb_ptr = (char *)st + elm->memb_offset;
memb_ptr2 = &memb_ptr;
@@ -804,7 +986,7 @@ SET_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
asn_SET_specifics_t *specs = (asn_SET_specifics_t *)td->specifics;
asn_enc_rval_t er;
int xcan = (flags & XER_F_CANONICAL);
- asn_TYPE_tag2member_t *t2m = specs->tag2el_cxer;
+ const asn_TYPE_tag2member_t *t2m = specs->tag2el_cxer;
int t2m_count = specs->tag2el_cxer_count;
int edx;
diff --git a/src/constr_SET_OF.c b/src/constr_SET_OF.c
index 11eac57..2fd530e 100644
--- a/src/constr_SET_OF.c
+++ b/src/constr_SET_OF.c
@@ -884,7 +884,7 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
if(!st) {
st = *sptr = CALLOC(1, specs->struct_size);
if(!st) _ASN_DECODE_FAILED;
- }
+ }
list = _A_SET_FROM_VOID(st);
/* Figure out which constraints to use */
@@ -901,7 +901,7 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
if(ct && ct->effective_bits >= 0) {
/* X.691, #19.5: No length determinant */
nelems = per_get_few_bits(pd, ct->effective_bits);
- ASN_DEBUG("Preparing to fetch %ld+%ld elements from %s",
+ ASN_DEBUG("Preparing to fetch %ld+%lld elements from %s",
(long)nelems, ct->lower_bound, td->name);
if(nelems < 0) _ASN_DECODE_STARVED;
nelems += ct->lower_bound;
@@ -915,7 +915,7 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
nelems = uper_get_length(pd,
ct ? ct->effective_bits : -1, &repeat);
ASN_DEBUG("Got to decode %d elements (eff %d)",
- (int)nelems, (int)ct ? ct->effective_bits : -1);
+ (int)nelems, (int)(ct ? ct->effective_bits : -1));
if(nelems < 0) _ASN_DECODE_STARVED;
}
@@ -951,3 +951,91 @@ SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
return rv;
}
+asn_dec_rval_t
+SET_OF_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_dec_rval_t rv;
+ asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
+ asn_TYPE_member_t *elm = td->elements; /* Single one */
+ void *st = *sptr;
+ asn_anonymous_set_ *list;
+ asn_per_constraint_t *ct;
+ int repeat = 0;
+ ssize_t nelems;
+
+ if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
+ _ASN_DECODE_FAILED;
+
+ /*
+ * Create the target structure if it is not present already.
+ */
+ if(!st) {
+ st = *sptr = CALLOC(1, specs->struct_size);
+ if(!st) _ASN_DECODE_FAILED;
+ }
+ list = _A_SET_FROM_VOID(st);
+
+ /* Figure out which constraints to use */
+ if(constraints) ct = &constraints->size;
+ else if(td->per_constraints) ct = &td->per_constraints->size;
+ else ct = 0;
+
+ if(ct && ct->flags & APC_EXTENSIBLE) {
+ int value = per_get_few_bits(pd, 1);
+ if(value < 0) _ASN_DECODE_STARVED;
+ if(value) ct = 0; /* Not restricted! */
+ }
+
+ if(ct && ct->effective_bits >= 0) {
+ /* X.691, #19.5: No length determinant */
+// nelems = per_get_few_bits(pd, ct->effective_bits);
+ nelems = aper_get_nsnnwn(pd, ct->upper_bound - ct->lower_bound);
+ ASN_DEBUG("Preparing to fetch %ld+%lld elements from %s",
+ (long)nelems, ct->lower_bound, td->name);
+ if(nelems < 0) _ASN_DECODE_STARVED;
+ nelems += ct->lower_bound;
+ } else {
+ nelems = -1;
+ }
+
+ do {
+ int i;
+ if(nelems < 0) {
+ nelems = aper_get_length(pd, ct ? ct->upper_bound - ct->lower_bound + 1 : -1,
+ ct ? ct->effective_bits : -1, &repeat);
+ ASN_DEBUG("Got to decode %d elements (eff %d)",
+ (int)nelems, (int)(ct ? ct->effective_bits : -1));
+ if(nelems < 0) _ASN_DECODE_STARVED;
+ }
+
+ for(i = 0; i < nelems; i++) {
+ void *ptr = 0;
+ ASN_DEBUG("SET OF %s decoding", elm->type->name);
+ rv = elm->type->aper_decoder(opt_codec_ctx, elm->type,
+ elm->per_constraints, &ptr, pd);
+ ASN_DEBUG("%s SET OF %s decoded %d, %p",
+ td->name, elm->type->name, rv.code, ptr);
+ if(rv.code == RC_OK) {
+ if(ASN_SET_ADD(list, ptr) == 0)
+ continue;
+ ASN_DEBUG("Failed to add element into %s",
+ td->name);
+ /* Fall through */
+ rv.code = RC_FAIL;
+ } else {
+ ASN_DEBUG("Failed decoding %s of %s (SET OF)",
+ elm->type->name, td->name);
+ }
+ if(ptr) ASN_STRUCT_FREE(*elm->type, ptr);
+ return rv;
+ }
+
+ nelems = -1; /* Allow uper_get_length() */
+ } while(repeat);
+
+ ASN_DEBUG("Decoded %s as SET OF", td->name);
+
+ rv.code = RC_OK;
+ rv.consumed = 0;
+ return rv;
+}
diff --git a/src/constr_TYPE.c b/src/constr_TYPE.c
index 4bc88d4..322f68c 100644
--- a/src/constr_TYPE.c
+++ b/src/constr_TYPE.c
@@ -17,7 +17,7 @@ static asn_app_consume_bytes_f _print2fp;
* Return the outmost tag of the type.
*/
ber_tlv_tag_t
-asn_TYPE_outmost_tag(asn_TYPE_descriptor_t *type_descriptor,
+asn_TYPE_outmost_tag(const asn_TYPE_descriptor_t *type_descriptor,
const void *struct_ptr, int tag_mode, ber_tlv_tag_t tag) {
if(tag_mode)
diff --git a/src/der_encoder.c b/src/der_encoder.c
index 6c859e1..1c01480 100644
--- a/src/der_encoder.c
+++ b/src/der_encoder.c
@@ -80,8 +80,8 @@ der_write_tags(asn_TYPE_descriptor_t *sd,
ber_tlv_tag_t tag, /* EXPLICIT or IMPLICIT tag */
asn_app_consume_bytes_f *cb,
void *app_key) {
- ber_tlv_tag_t *tags; /* Copy of tags stream */
- int tags_count; /* Number of tags */
+ 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;
@@ -102,8 +102,9 @@ der_write_tags(asn_TYPE_descriptor_t *sd,
* and initialize it appropriately.
*/
int stag_offset;
- tags = (ber_tlv_tag_t *)alloca((sd->tags_count + 1) * sizeof(ber_tlv_tag_t));
- if(!tags) { /* Can fail on !x86 */
+ 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;
}
@@ -111,10 +112,11 @@ der_write_tags(asn_TYPE_descriptor_t *sd,
+ 1 /* EXPLICIT or IMPLICIT tag is given */
- ((tag_mode == -1) && sd->tags_count);
/* Copy tags over */
- tags[0] = tag;
+ tags_buf[0] = tag;
stag_offset = -1 + ((tag_mode == -1) && sd->tags_count);
for(i = 1; i < tags_count; i++)
- tags[i] = sd->tags[i + stag_offset];
+ tags_buf[i] = sd->tags[i + stag_offset];
+ tags = tags_buf;
} else {
tags = sd->tags;
tags_count = sd->tags_count;
diff --git a/src/per_decoder.c b/src/per_decoder.c
index 2b3d2e2..20fe1a1 100644
--- a/src/per_decoder.c
+++ b/src/per_decoder.c
@@ -21,6 +21,35 @@ uper_decode_complete(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
rval.consumed >>= 3;
} else if(rval.code == RC_OK) {
if(size) {
+ if(((const uint8_t *)buffer)[0] == 0) {
+ rval.consumed = 1; /* 1 byte */
+ } else {
+ ASN_DEBUG("Expecting single zeroed byte");
+ rval.code = RC_FAIL;
+ }
+ } else {
+ /* Must contain at least 8 bits. */
+ rval.code = RC_WMORE;
+ }
+ }
+
+ return rval;
+}
+
+asn_dec_rval_t
+aper_decode_complete(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size) {
+ asn_dec_rval_t rval;
+
+ rval = aper_decode(opt_codec_ctx, td, sptr, buffer, size, 0, 0);
+ if(rval.consumed) {
+ /*
+ * We've always given 8-aligned data,
+ * so convert bits to integral bytes.
+ */
+ rval.consumed += 7;
+ rval.consumed >>= 3;
+ } else if(rval.code == RC_OK) {
+ if(size) {
if(((uint8_t *)buffer)[0] == 0) {
rval.consumed = 1; /* 1 byte */
} else {
@@ -81,8 +110,8 @@ uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sp
/* Return the number of consumed bits */
rval.consumed = ((pd.buffer - (const uint8_t *)buffer) << 3)
+ pd.nboff - skip_bits;
- ASN_DEBUG("PER decoding consumed %d, counted %d",
- rval.consumed, pd.moved);
+ ASN_DEBUG("PER decoding consumed %ld, counted %ld",
+ (long)rval.consumed, (long)pd.moved);
assert(rval.consumed == pd.moved);
} else {
/* PER codec is not a restartable */
@@ -91,3 +120,57 @@ uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sp
return rval;
}
+asn_dec_rval_t
+aper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits, int unused_bits) {
+ asn_codec_ctx_t s_codec_ctx;
+ asn_dec_rval_t rval;
+ asn_per_data_t pd;
+
+ if(skip_bits < 0 || skip_bits > 7
+ || unused_bits < 0 || unused_bits > 7
+ || (unused_bits > 0 && !size))
+ _ASN_DECODE_FAILED;
+
+ /*
+ * Stack checker requires that the codec context
+ * must be allocated on the stack.
+ */
+ if(opt_codec_ctx) {
+ if(opt_codec_ctx->max_stack_size) {
+ s_codec_ctx = *opt_codec_ctx;
+ opt_codec_ctx = &s_codec_ctx;
+ }
+ } else {
+ /* If context is not given, be security-conscious anyway */
+ memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
+ s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX;
+ opt_codec_ctx = &s_codec_ctx;
+ }
+
+ /* Fill in the position indicator */
+ memset(&pd, 0, sizeof(pd));
+ pd.buffer = (const uint8_t *)buffer;
+ pd.nboff = skip_bits;
+ pd.nbits = 8 * size - unused_bits; /* 8 is CHAR_BIT from <limits.h> */
+ if(pd.nboff > pd.nbits)
+ _ASN_DECODE_FAILED;
+
+ /*
+ * Invoke type-specific decoder.
+ */
+ if(!td->aper_decoder)
+ _ASN_DECODE_FAILED; /* PER is not compiled in */
+ rval = td->aper_decoder(opt_codec_ctx, td, 0, sptr, &pd);
+ if(rval.code == RC_OK) {
+ /* Return the number of consumed bits */
+ rval.consumed = ((pd.buffer - (const uint8_t *)buffer) << 3)
+ + pd.nboff - skip_bits;
+ ASN_DEBUG("PER decoding consumed %d, counted %d",
+ rval.consumed, pd.moved);
+ assert(rval.consumed == pd.moved);
+ } else {
+ /* PER codec is not a restartable */
+ rval.consumed = 0;
+ }
+ return rval;
+}
diff --git a/src/per_encoder.c b/src/per_encoder.c
index f4bace0..02dc3a2 100644
--- a/src/per_encoder.c
+++ b/src/per_encoder.c
@@ -4,6 +4,7 @@
static asn_enc_rval_t uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *, void *sptr, asn_app_consume_bytes_f *cb, void *app_key);
+static asn_enc_rval_t aper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *, void *sptr, asn_app_consume_bytes_f *cb, void *app_key);
asn_enc_rval_t
uper_encode(asn_TYPE_descriptor_t *td, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
return uper_encode_internal(td, 0, sptr, cb, app_key);
@@ -41,6 +42,18 @@ uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_
return uper_encode_internal(td, 0, sptr, encode_to_buffer_cb, &key);
}
+asn_enc_rval_t
+aper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) {
+ enc_to_buf_arg key;
+
+ key.buffer = buffer;
+ key.left = buffer_size;
+
+ if(td) ASN_DEBUG("Encoding \"%s\" using ALIGNED PER", td->name);
+
+ return aper_encode_internal(td, 0, sptr, encode_to_buffer_cb, &key);
+}
+
typedef struct enc_dyn_arg {
void *buffer;
size_t length;
@@ -88,11 +101,40 @@ uper_encode_to_new_buffer(asn_TYPE_descriptor_t *td, asn_per_constraints_t *cons
}
default:
*buffer_r = key.buffer;
- ASN_DEBUG("Complete encoded in %d bits", er.encoded);
+ ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
return ((er.encoded + 7) >> 3);
}
}
+ssize_t
+aper_encode_to_new_buffer(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, void **buffer_r) {
+ asn_enc_rval_t er;
+ enc_dyn_arg key;
+
+ memset(&key, 0, sizeof(key));
+
+ er = aper_encode_internal(td, constraints, sptr, encode_dyn_cb, &key);
+ switch(er.encoded) {
+ case -1:
+ FREEMEM(key.buffer);
+ return -1;
+ case 0:
+ FREEMEM(key.buffer);
+ key.buffer = MALLOC(1);
+ if(key.buffer) {
+ *(char *)key.buffer = '\0';
+ *buffer_r = key.buffer;
+ return 1;
+ } else {
+ return -1;
+ }
+ default:
+ *buffer_r = key.buffer;
+ ASN_DEBUG("Complete encoded in %d bits", er.encoded);
+ return ((er.encoded + 7) >> 3);
+ }
+}
+
/*
* Internally useful functions.
*/
@@ -115,6 +157,23 @@ _uper_encode_flush_outp(asn_per_outp_t *po) {
return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key);
}
+static int
+_aper_encode_flush_outp(asn_per_outp_t *po) {
+ uint8_t *buf;
+
+ if(po->nboff == 0 && po->buffer == po->tmpspace)
+ return 0;
+
+ buf = po->buffer + (po->nboff >> 3);
+ /* Make sure we account for the last, partially filled */
+ if(po->nboff & 0x07) {
+ buf[0] &= 0xff << (8 - (po->nboff & 0x07));
+ buf++;
+ }
+
+ return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key);
+}
+
static asn_enc_rval_t
uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
asn_per_outp_t po;
@@ -149,3 +208,37 @@ uper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constrain
return er;
}
+static asn_enc_rval_t
+aper_encode_internal(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
+ asn_per_outp_t po;
+ asn_enc_rval_t er;
+
+ /*
+ * Invoke type-specific encoder.
+ */
+ if(!td || !td->aper_encoder)
+ _ASN_ENCODE_FAILED; /* PER is not compiled in */
+
+ po.buffer = po.tmpspace;
+ po.nboff = 0;
+ po.nbits = 8 * sizeof(po.tmpspace);
+ po.outper = cb;
+ po.op_key = app_key;
+ po.flushed_bytes = 0;
+
+ er = td->aper_encoder(td, constraints, sptr, &po);
+ if(er.encoded != -1) {
+ size_t bits_to_flush;
+
+ bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff;
+
+ /* Set number of bits encoded to a firm value */
+ er.encoded = (po.flushed_bytes << 3) + bits_to_flush;
+
+ if(_aper_encode_flush_outp(&po))
+ _ASN_ENCODE_FAILED;
+ }
+
+ return er;
+}
+
diff --git a/src/per_opentype.c b/src/per_opentype.c
index c749c8c..984a96d 100644
--- a/src/per_opentype.c
+++ b/src/per_opentype.c
@@ -18,8 +18,6 @@ static int uper_ugot_refill(asn_per_data_t *pd);
static int per_skip_bits(asn_per_data_t *pd, int skip_nbits);
static asn_dec_rval_t uper_sot_suck(asn_codec_ctx_t *, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd);
-int asn_debug_indent;
-
/*
* Encode an "open type field".
* #10.1, #10.2
@@ -38,6 +36,37 @@ uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints
for(bptr = buf, toGo = size; toGo;) {
ssize_t maySave = uper_put_length(po, toGo);
+ ASN_DEBUG("Prepending length %d to %s and allowing to save %d",
+ (int)size, td->name, (int)maySave);
+ if(maySave < 0) break;
+ if(per_put_many_bits(po, bptr, maySave * 8)) break;
+ bptr = (char *)bptr + maySave;
+ toGo -= maySave;
+ }
+
+ FREEMEM(buf);
+ if(toGo) return -1;
+
+ ASN_DEBUG("Open type put %s of length %ld + overhead (1byte?)",
+ td->name, (long)size);
+
+ return 0;
+}
+
+int
+aper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ void *buf;
+ void *bptr;
+ ssize_t size;
+ size_t toGo;
+
+ ASN_DEBUG("Open type put %s ...", td->name);
+
+ size = aper_encode_to_new_buffer(td, constraints, sptr, &buf);
+ if(size <= 0) return -1;
+
+ for(bptr = buf, toGo = size; toGo;) {
+ ssize_t maySave = aper_put_length(po, -1, toGo);
if(maySave < 0) break;
if(per_put_many_bits(po, bptr, maySave * 8)) break;
bptr = (char *)bptr + maySave;
@@ -48,7 +77,7 @@ uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints
if(toGo) return -1;
ASN_DEBUG("Open type put %s of length %d + overhead (1byte?)",
- td->name, size);
+ td->name, size);
return 0;
}
@@ -92,28 +121,31 @@ uper_open_type_get_simple(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
bufLen += chunk_bytes;
} while(repeat);
- ASN_DEBUG("Getting open type %s encoded in %d bytes", td->name,
- bufLen);
+ ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
+ (long)bufLen);
memset(&spd, 0, sizeof(spd));
spd.buffer = buf;
spd.nbits = bufLen << 3;
- asn_debug_indent += 4;
+ ASN_DEBUG_INDENT_ADD(+4);
rv = td->uper_decoder(ctx, td, constraints, sptr, &spd);
- asn_debug_indent -= 4;
+ ASN_DEBUG_INDENT_ADD(-4);
if(rv.code == RC_OK) {
/* Check padding validity */
padding = spd.nbits - spd.nboff;
- if(padding < 8 && per_get_few_bits(&spd, padding) == 0) {
+ if ((padding < 8 ||
+ /* X.691#10.1.3 */
+ (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
+ per_get_few_bits(&spd, padding) == 0) {
/* Everything is cool */
FREEMEM(buf);
return rv;
}
FREEMEM(buf);
if(padding >= 8) {
- ASN_DEBUG("Too large padding %d in open type", padding);
+ ASN_DEBUG("Too large padding %d in open type", (int)padding);
_ASN_DECODE_FAILED;
} else {
ASN_DEBUG("Non-zero padding");
@@ -148,9 +180,9 @@ uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */
pd->moved = 0; /* This now counts the open type size in bits */
- asn_debug_indent += 4;
+ ASN_DEBUG_INDENT_ADD(+4);
rv = td->uper_decoder(ctx, td, constraints, sptr, pd);
- asn_debug_indent -= 4;
+ ASN_DEBUG_INDENT_ADD(-4);
#define UPDRESTOREPD do { \
/* buffer and nboff are valid, preserve them. */ \
@@ -165,24 +197,23 @@ uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
return rv;
}
- ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d"
- , td->name,
+ ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name,
per_data_string(pd),
per_data_string(&arg.oldpd),
- arg.unclaimed, arg.repeat);
+ (int)arg.unclaimed, (int)arg.repeat);
padding = pd->moved % 8;
if(padding) {
int32_t pvalue;
if(padding > 7) {
ASN_DEBUG("Too large padding %d in open type",
- padding);
+ (int)padding);
rv.code = RC_FAIL;
UPDRESTOREPD;
return rv;
}
padding = 8 - padding;
- ASN_DEBUG("Getting padding of %d bits", padding);
+ ASN_DEBUG("Getting padding of %d bits", (int)padding);
pvalue = per_get_few_bits(pd, padding);
switch(pvalue) {
case -1:
@@ -192,7 +223,7 @@ uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
case 0: break;
default:
ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
- padding, (int)pvalue);
+ (int)padding, (int)pvalue);
UPDRESTOREPD;
_ASN_DECODE_FAILED;
}
@@ -212,14 +243,14 @@ uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
UPDRESTOREPD;
/* Skip data not consumed by the decoder */
- if(arg.unclaimed) ASN_DEBUG("Getting unclaimed %d", arg.unclaimed);
if(arg.unclaimed) {
+ ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed);
switch(per_skip_bits(pd, arg.unclaimed)) {
case -1:
- ASN_DEBUG("Claim of %d failed", arg.unclaimed);
+ ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed);
_ASN_DECODE_STARVED;
case 0:
- ASN_DEBUG("Got claim of %d", arg.unclaimed);
+ ASN_DEBUG("Got claim of %d", (int)arg.unclaimed);
break;
default:
/* Padding must be blank */
@@ -243,9 +274,7 @@ asn_dec_rval_t
uper_open_type_get(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
- return uper_open_type_get_simple(ctx, td, constraints,
- sptr, pd);
-
+ return uper_open_type_get_simple(ctx, td, constraints, sptr, pd);
}
int
@@ -293,8 +322,8 @@ uper_ugot_refill(asn_per_data_t *pd) {
asn_per_data_t *oldpd = &arg->oldpd;
- ASN_DEBUG("REFILLING pd->moved=%d, oldpd->moved=%d",
- pd->moved, oldpd->moved);
+ ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld",
+ (long)pd->moved, (long)oldpd->moved);
/* Advance our position to where pd is */
oldpd->buffer = pd->buffer;
@@ -314,7 +343,8 @@ uper_ugot_refill(asn_per_data_t *pd) {
pd->buffer = oldpd->buffer;
pd->nboff = oldpd->nboff - 1;
pd->nbits = oldpd->nbits;
- ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%d)", pd->moved);
+ ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)",
+ (long)pd->moved);
return 0;
}
@@ -324,8 +354,8 @@ uper_ugot_refill(asn_per_data_t *pd) {
}
next_chunk_bytes = uper_get_length(oldpd, -1, &arg->repeat);
- ASN_DEBUG("Open type LENGTH %d bytes at off %d, repeat %d",
- next_chunk_bytes, oldpd->moved, arg->repeat);
+ ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld",
+ (long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat);
if(next_chunk_bytes < 0) return -1;
if(next_chunk_bytes == 0) {
pd->refill = 0; /* No more refills, naturally */
@@ -336,14 +366,16 @@ uper_ugot_refill(asn_per_data_t *pd) {
if(avail >= next_chunk_bits) {
pd->nbits = oldpd->nboff + next_chunk_bits;
arg->unclaimed = 0;
- ASN_DEBUG("!+Parent frame %d bits, alloting %d [%d..%d] (%d)",
- next_chunk_bits, oldpd->moved,
- oldpd->nboff, oldpd->nbits,
- oldpd->nbits - oldpd->nboff);
+ ASN_DEBUG("!+Parent frame %ld bits, alloting %ld [%ld..%ld] (%ld)",
+ (long)next_chunk_bits, (long)oldpd->moved,
+ (long)oldpd->nboff, (long)oldpd->nbits,
+ (long)(oldpd->nbits - oldpd->nboff));
} else {
pd->nbits = oldpd->nbits;
arg->unclaimed = next_chunk_bits - avail;
- ASN_DEBUG("!-Parent frame %d, require %d, will claim %d", avail, next_chunk_bits, arg->unclaimed);
+ ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld",
+ (long)avail, (long)next_chunk_bits,
+ (long)arg->unclaimed);
}
pd->buffer = oldpd->buffer;
pd->nboff = oldpd->nboff;
@@ -357,7 +389,9 @@ per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
int hasNonZeroBits = 0;
while(skip_nbits > 0) {
int skip;
- if(skip_nbits < skip)
+
+ /* per_get_few_bits() is more efficient when nbits <= 24 */
+ if(skip_nbits < 24)
skip = skip_nbits;
else
skip = 24;
diff --git a/src/per_support.c b/src/per_support.c
index 173e696..d536bc0 100644
--- a/src/per_support.c
+++ b/src/per_support.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
+ * Copyright (c) 2005-2014 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
@@ -13,11 +13,11 @@ per_data_string(asn_per_data_t *pd) {
static int n;
n = (n+1) % 2;
snprintf(buf[n], sizeof(buf),
- "{m=%d span %+d[%d..%d] (%d)}",
- pd->moved,
- (((int)pd->buffer) & 0xf),
- pd->nboff, pd->nbits,
- pd->nbits - pd->nboff);
+ "{m=%ld span %+ld[%d..%d] (%d)}",
+ (long)pd->moved,
+ (((long)pd->buffer) & 0xf),
+ (int)pd->nboff, (int)pd->nbits,
+ (int)(pd->nbits - pd->nboff));
return buf[n];
}
@@ -31,6 +31,16 @@ per_get_undo(asn_per_data_t *pd, int nbits) {
}
}
+int32_t
+aper_get_align(asn_per_data_t *pd) {
+
+ if(pd->nboff & 0x7) {
+ ASN_DEBUG("Aligning %d bits", 8 - (pd->nboff & 0x7));
+ return per_get_few_bits(pd, 8 - (pd->nboff & 0x7));
+ }
+ return 0;
+}
+
/*
* Extract a small number of bits (<= 31) from the specified PER data pointer.
*/
@@ -49,7 +59,8 @@ per_get_few_bits(asn_per_data_t *pd, int nbits) {
int32_t tailv, vhead;
if(!pd->refill || nbits > 31) return -1;
/* Accumulate unused bytes before refill */
- ASN_DEBUG("Obtain the rest %d bits (want %d)", nleft, nbits);
+ ASN_DEBUG("Obtain the rest %d bits (want %d)",
+ (int)nleft, (int)nbits);
tailv = per_get_few_bits(pd, nleft);
if(tailv < 0) return -1;
/* Refill (replace pd contents with new data) */
@@ -103,13 +114,13 @@ per_get_few_bits(asn_per_data_t *pd, int nbits) {
accum &= (((uint32_t)1 << nbits) - 1);
- ASN_DEBUG(" [PER got %2d<=%2d bits => span %d %+d[%d..%d]:%02x (%d) => 0x%x]",
- nbits, nleft,
- pd->moved,
- (((int)pd->buffer) & 0xf),
- pd->nboff, pd->nbits,
+ ASN_DEBUG(" [PER got %2d<=%2d bits => span %d %+ld[%d..%d]:%02x (%d) => 0x%02x]",
+ (int)nbits, (int)nleft,
+ (int)pd->moved,
+ (((long)pd->buffer) & 0xf),
+ (int)pd->nboff, (int)pd->nbits,
pd->buffer[0],
- pd->nbits - pd->nboff,
+ (int)(pd->nbits - pd->nboff),
(int)accum);
return accum;
@@ -122,6 +133,8 @@ int
per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int alright, int nbits) {
int32_t value;
+ ASN_DEBUG("align: %s, nbits %d", alright ? "YES":"NO", nbits);
+
if(alright && (nbits & 7)) {
/* Perform right alignment of a first few bits */
value = per_get_few_bits(pd, nbits & 0x07);
@@ -186,6 +199,36 @@ uper_get_length(asn_per_data_t *pd, int ebits, int *repeat) {
return (16384 * value);
}
+ssize_t
+aper_get_length(asn_per_data_t *pd, int range, int ebits, int *repeat) {
+ ssize_t value;
+
+ *repeat = 0;
+
+ if (range <= 65536 && range >= 0)
+ return aper_get_nsnnwn(pd, range);
+
+ if (aper_get_align(pd) < 0)
+ return -1;
+
+ if(ebits >= 0) return per_get_few_bits(pd, ebits);
+
+ value = per_get_few_bits(pd, 8);
+ if(value < 0) return -1;
+ if((value & 128) == 0) /* #10.9.3.6 */
+ return (value & 0x7F);
+ if((value & 64) == 0) { /* #10.9.3.7 */
+ value = ((value & 63) << 8) | per_get_few_bits(pd, 8);
+ if(value < 0) return -1;
+ return value;
+ }
+ value &= 63; /* this is "m" from X.691, #10.9.3.8 */
+ if(value < 1 || value > 4)
+ return -1;
+ *repeat = 1;
+ return (16384 * value);
+}
+
/*
* Get the normally small length "n".
* This procedure used to decode length of extensions bit-maps
@@ -200,7 +243,7 @@ uper_get_nslength(asn_per_data_t *pd) {
if(per_get_few_bits(pd, 1) == 0) {
length = per_get_few_bits(pd, 6) + 1;
if(length <= 0) return -1;
- ASN_DEBUG("l=%d", length);
+ ASN_DEBUG("l=%d", (int)length);
return length;
} else {
int repeat;
@@ -210,6 +253,25 @@ uper_get_nslength(asn_per_data_t *pd) {
}
}
+ssize_t
+aper_get_nslength(asn_per_data_t *pd) {
+ ssize_t length;
+
+ ASN_DEBUG("Getting normally small length");
+
+ if(per_get_few_bits(pd, 1) == 0) {
+ length = per_get_few_bits(pd, 6) + 1;
+ if(length <= 0) return -1;
+ ASN_DEBUG("l=%d", length);
+ return length;
+ } else {
+ int repeat;
+ length = aper_get_length(pd, -1, -1, &repeat);
+ if(length >= 0 && !repeat) return length;
+ return -1; /* Error, or do not support >16K extensions */
+ }
+}
+
/*
* Get the normally small non-negative whole number.
* X.691, #10.6
@@ -236,14 +298,49 @@ uper_get_nsnnwn(asn_per_data_t *pd) {
return value;
}
+ssize_t
+aper_get_nsnnwn(asn_per_data_t *pd, int range) {
+ ssize_t value;
+ int bytes = 0;
+
+ ASN_DEBUG("getting nsnnwn with range %d", range);
+
+ if(range <= 255) {
+ if (range < 0) return -1;
+ /* 1 -> 8 bits */
+ int i;
+ for (i = 1; i <= 8; i++) {
+ int upper = 1 << i;
+ if (upper >= range)
+ break;
+ }
+ value = per_get_few_bits(pd, i);
+ return value;
+ } else if (range == 256){
+ /* 1 byte */
+ bytes = 1;
+ return -1;
+ } else if (range <= 65536) {
+ /* 2 bytes */
+ bytes = 2;
+ } else {
+ return -1;
+ }
+ if (aper_get_align(pd) < 0)
+ return -1;
+ value = per_get_few_bits(pd, 8 * bytes);
+ return value;
+}
+
/*
- * Put the normally small non-negative whole number.
- * X.691, #10.6
+ * X.691-11/2008, #11.6
+ * Encoding of a normally small non-negative whole number
*/
int
uper_put_nsnnwn(asn_per_outp_t *po, int n) {
int bytes;
+ ASN_DEBUG("uper put nsnnwn n %d", n);
if(n <= 63) {
if(n < 0) return -1;
return per_put_few_bits(po, n, 7);
@@ -263,6 +360,58 @@ uper_put_nsnnwn(asn_per_outp_t *po, int n) {
}
+/* X.691-2008/11, #11.5.6 -> #11.3 */
+int uper_get_constrained_whole_number(asn_per_data_t *pd, unsigned long *out_value, int nbits) {
+ unsigned long lhalf; /* Lower half of the number*/
+ long half;
+
+ if(nbits <= 31) {
+ half = per_get_few_bits(pd, nbits);
+ if(half < 0) return -1;
+ *out_value = half;
+ return 0;
+ }
+
+ if((size_t)nbits > 8 * sizeof(*out_value))
+ return -1; /* RANGE */
+
+ half = per_get_few_bits(pd, 31);
+ if(half < 0) return -1;
+
+ if(uper_get_constrained_whole_number(pd, &lhalf, nbits - 31))
+ return -1;
+
+ *out_value = ((unsigned long)half << (nbits - 31)) | lhalf;
+ return 0;
+}
+
+
+/* X.691-2008/11, #11.5.6 -> #11.3 */
+int uper_put_constrained_whole_number_s(asn_per_outp_t *po, long v, int nbits) {
+ /*
+ * Assume signed number can be safely coerced into
+ * unsigned of the same range.
+ * The following testing code will likely be optimized out
+ * by compiler if it is true.
+ */
+ unsigned long uvalue1 = ULONG_MAX;
+ long svalue = uvalue1;
+ unsigned long uvalue2 = svalue;
+ assert(uvalue1 == uvalue2);
+ return uper_put_constrained_whole_number_u(po, v, nbits);
+}
+
+int uper_put_constrained_whole_number_u(asn_per_outp_t *po, unsigned long v, int nbits) {
+ if(nbits <= 31) {
+ return per_put_few_bits(po, v, nbits);
+ } else {
+ /* Put higher portion first, followed by lower 31-bit */
+ if(uper_put_constrained_whole_number_u(po, v >> 31, nbits - 31))
+ return -1;
+ return per_put_few_bits(po, v, 31);
+ }
+}
+
/*
* Put a small number of bits (<= 31).
*/
@@ -275,7 +424,7 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) {
if(obits <= 0 || obits >= 32) return obits ? -1 : 0;
ASN_DEBUG("[PER put %d bits %x to %p+%d bits]",
- obits, (int)bits, po->buffer, po->nboff);
+ obits, (int)bits, po->buffer, (int)po->nboff);
/*
* Normalize position indicator.
@@ -291,8 +440,8 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) {
*/
if(po->nboff + obits > po->nbits) {
int complete_bytes = (po->buffer - po->tmpspace);
- ASN_DEBUG("[PER output %d complete + %d]",
- complete_bytes, po->flushed_bytes);
+ ASN_DEBUG("[PER output %ld complete + %ld]",
+ (long)complete_bytes, (long)po->flushed_bytes);
if(po->outper(po->tmpspace, complete_bytes, po->op_key) < 0)
return -1;
if(po->nboff)
@@ -307,47 +456,106 @@ per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) {
*/
buf = po->buffer;
omsk = ~((1 << (8 - po->nboff)) - 1);
- off = (po->nboff += obits);
+ off = (po->nboff + obits);
/* Clear data of debris before meaningful bits */
bits &= (((uint32_t)1 << obits) - 1);
ASN_DEBUG("[PER out %d %u/%x (t=%d,o=%d) %x&%x=%x]", obits,
(int)bits, (int)bits,
- po->nboff - obits, off, buf[0], omsk&0xff, buf[0] & omsk);
+ (int)po->nboff, (int)off,
+ buf[0], (int)(omsk&0xff),
+ (int)(buf[0] & omsk));
if(off <= 8) /* Completely within 1 byte */
+ po->nboff = off,
bits <<= (8 - off),
buf[0] = (buf[0] & omsk) | bits;
else if(off <= 16)
+ po->nboff = off,
bits <<= (16 - off),
buf[0] = (buf[0] & omsk) | (bits >> 8),
buf[1] = bits;
else if(off <= 24)
+ po->nboff = off,
bits <<= (24 - off),
buf[0] = (buf[0] & omsk) | (bits >> 16),
buf[1] = bits >> 8,
buf[2] = bits;
else if(off <= 31)
+ po->nboff = off,
bits <<= (32 - off),
buf[0] = (buf[0] & omsk) | (bits >> 24),
buf[1] = bits >> 16,
buf[2] = bits >> 8,
buf[3] = bits;
else {
- ASN_DEBUG("->[PER out split %d]", obits);
- po->nboff -= obits; /* undo incrementation from a few lines above */
- per_put_few_bits(po, bits >> (obits - 24), 24); /* shift according to the rest of the bits */
+ per_put_few_bits(po, bits >> (obits - 24), 24);
per_put_few_bits(po, bits, obits - 24);
- ASN_DEBUG("<-[PER out split %d]", obits);
}
- ASN_DEBUG("[PER out %u/%x => %02x buf+%d]",
- (int)bits, (int)bits, buf[0], po->buffer - po->tmpspace);
+ ASN_DEBUG("[PER out %u/%x => %02x buf+%ld]",
+ (int)bits, (int)bits, buf[0],
+ (long)(po->buffer - po->tmpspace));
return 0;
}
+int
+aper_put_nsnnwn(asn_per_outp_t *po, int range, int number) {
+ int bytes;
+
+ ASN_DEBUG("aper put nsnnwn %d with range %d", number, range);
+ /* 10.5.7.1 X.691 */
+ if(range < 0) {
+ int i;
+ for (i = 1; ; i++) {
+ int bits = 1 << (8 * i);
+ if (number <= bits)
+ break;
+ }
+ bytes = i;
+ assert(i <= 4);
+ }
+ if(range <= 255) {
+ int i;
+ for (i = 1; i <= 8; i++) {
+ int bits = 1 << i;
+ if (range <= bits)
+ break;
+ }
+ return per_put_few_bits(po, number, i);
+ } else if(range == 256) {
+ bytes = 1;
+ } else if(range <= 65536) {
+ bytes = 2;
+ } else { /* Ranges > 64K */
+ int i;
+ for (i = 1; ; i++) {
+ int bits = 1 << (8 * i);
+ if (range <= bits)
+ break;
+ }
+ assert(i <= 4);
+ bytes = i;
+ }
+ if(aper_put_align(po) < 0) /* Aligning on octet */
+ return -1;
+// if(per_put_few_bits(po, bytes, 8))
+// return -1;
+
+ return per_put_few_bits(po, number, 8 * bytes);
+}
+
+int aper_put_align(asn_per_outp_t *po) {
+
+ if(po->nboff & 0x7) {
+ ASN_DEBUG("Aligning %d bits", 8 - (po->nboff & 0x7));
+ if(per_put_few_bits(po, 0x00, (8 - (po->nboff & 0x7))))
+ return -1;
+ }
+ return 0;
+}
/*
* Output a large number of bits.
@@ -387,6 +595,8 @@ per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int nbits) {
ssize_t
uper_put_length(asn_per_outp_t *po, size_t length) {
+ ASN_DEBUG("UPER put length %d", length);
+
if(length <= 127) /* #10.9.3.6 */
return per_put_few_bits(po, length, 8)
? -1 : (ssize_t)length;
@@ -401,6 +611,33 @@ uper_put_length(asn_per_outp_t *po, size_t length) {
? -1 : (ssize_t)(length << 14);
}
+ssize_t
+aper_put_length(asn_per_outp_t *po, int range, size_t length) {
+
+ ASN_DEBUG("APER put length %d with range %d", length, range);
+
+ /* 10.9 X.691 Note 2 */
+ if (range <= 65536 && range >= 0)
+ return aper_put_nsnnwn(po, range, length);
+
+ if (aper_put_align(po) < 0)
+ return -1;
+
+ if(length <= 127) /* #10.9.3.6 */{
+ return per_put_few_bits(po, length, 8)
+ ? -1 : (ssize_t)length;
+ }
+ else if(length < 16384) /* #10.9.3.7 */
+ return per_put_few_bits(po, length|0x8000, 16)
+ ? -1 : (ssize_t)length;
+
+ length >>= 14;
+ if(length > 4) length = 4;
+
+ return per_put_few_bits(po, 0xC0 | length, 8)
+ ? -1 : (ssize_t)(length << 14);
+}
+
/*
* Put the normally small length "n" into the stream.
@@ -424,3 +661,19 @@ uper_put_nslength(asn_per_outp_t *po, size_t length) {
return 0;
}
+int
+aper_put_nslength(asn_per_outp_t *po, size_t length) {
+
+ if(length <= 64) {
+ /* #10.9.3.4 */
+ if(length == 0) return -1;
+ return per_put_few_bits(po, length-1, 7) ? -1 : 0;
+ } else {
+ if(aper_put_length(po, -1, length) != (ssize_t)length) {
+ /* This might happen in case of >16K extensions */
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/xer_decoder.c b/src/xer_decoder.c
index 161dc78..cb4b5f8 100644
--- a/src/xer_decoder.c
+++ b/src/xer_decoder.c
@@ -109,7 +109,8 @@ xer_check_tag(const void *buf_ptr, int size, const char *need_tag) {
if(size < 2 || buf[0] != LANGLE || buf[size-1] != RANGLE) {
if(size >= 2)
- ASN_DEBUG("Broken XML tag: \"%c...%c\"", buf[0], buf[size - 1]);
+ ASN_DEBUG("Broken XML tag: \"%c...%c\"",
+ buf[0], buf[size - 1]);
return XCT_BROKEN;
}
@@ -315,8 +316,8 @@ xer_decode_general(asn_codec_ctx_t *opt_codec_ctx,
}
-int
-xer_is_whitespace(const void *chunk_buf, size_t chunk_size) {
+size_t
+xer_whitespace_span(const void *chunk_buf, size_t chunk_size) {
const char *p = (const char *)chunk_buf;
const char *pend = p + chunk_size;
@@ -329,12 +330,13 @@ xer_is_whitespace(const void *chunk_buf, size_t chunk_size) {
* SPACE (32)
*/
case 0x09: case 0x0a: case 0x0d: case 0x20:
- break;
+ continue;
default:
- return 0;
+ break;
}
+ break;
}
- return 1; /* All whitespace */
+ return (p - (const char *)chunk_buf);
}
/*
diff --git a/src/xer_support.c b/src/xer_support.c
index 9e34e69..36b4bfb 100644
--- a/src/xer_support.c
+++ b/src/xer_support.c
@@ -22,16 +22,7 @@ typedef enum {
ST_COMMENT_CLO_RT /* "-->"[1] */
} pstate_e;
-static pxml_chunk_type_e final_chunk_type[] = {
- PXML_TEXT,
- PXML_TAG_END,
- PXML_COMMENT_END,
- PXML_TAG_END,
- PXML_COMMENT_END,
-};
-
-
-static int
+static const int
_charclass[256] = {
0,0,0,0,0,0,0,0, 0,1,1,0,1,1,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
@@ -79,8 +70,11 @@ _charclass[256] = {
#define TOKEN_CB(_type, _ns, _current_too) \
TOKEN_CB_CALL(_type, _ns, _current_too, 0)
+#define PXML_TAG_FINAL_CHUNK_TYPE PXML_TAG_END
+#define PXML_COMMENT_FINAL_CHUNK_TYPE PXML_COMMENT_END
+
#define TOKEN_CB_FINAL(_type, _ns, _current_too) \
- TOKEN_CB_CALL(final_chunk_type[_type], _ns, _current_too, 1)
+ TOKEN_CB_CALL( _type ## _FINAL_CHUNK_TYPE , _ns, _current_too, 1)
/*
* Parser itself