mirror of https://gerrit.osmocom.org/asn1c
NativeEnumerated for OER, and tests
This commit is contained in:
parent
049a2d7da7
commit
f9f3e06e21
|
@ -36,6 +36,7 @@ libasn1cskeletons_la_SOURCES = \
|
|||
ISO646String.c ISO646String.h \
|
||||
NULL.c NULL.h \
|
||||
NativeEnumerated.c NativeEnumerated.h \
|
||||
NativeEnumerated_oer.c \
|
||||
NativeInteger.c NativeInteger.h \
|
||||
NativeInteger_oer.c \
|
||||
NativeReal.c NativeReal.h \
|
||||
|
|
|
@ -31,8 +31,8 @@ asn_TYPE_operation_t asn_OP_NativeEnumerated = {
|
|||
0,
|
||||
0,
|
||||
#else
|
||||
0,
|
||||
0,
|
||||
NativeEnumerated_decode_oer,
|
||||
NativeEnumerated_encode_oer,
|
||||
#endif /* ASN_DISABLE_OER_SUPPORT */
|
||||
#ifdef ASN_DISABLE_PER_SUPPORT
|
||||
0,
|
||||
|
|
|
@ -23,6 +23,8 @@ extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated;
|
|||
extern asn_TYPE_operation_t asn_OP_NativeEnumerated;
|
||||
|
||||
xer_type_encoder_f NativeEnumerated_encode_xer;
|
||||
oer_type_decoder_f NativeEnumerated_decode_oer;
|
||||
oer_type_encoder_f NativeEnumerated_encode_oer;
|
||||
per_type_decoder_f NativeEnumerated_decode_uper;
|
||||
per_type_encoder_f NativeEnumerated_encode_uper;
|
||||
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_DISABLE_OER_SUPPORT
|
||||
|
||||
#include <asn_internal.h>
|
||||
#include <NativeEnumerated.h>
|
||||
#include <errno.h>
|
||||
|
||||
asn_dec_rval_t
|
||||
NativeEnumerated_decode_oer(asn_codec_ctx_t *opt_codec_ctx,
|
||||
asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints,
|
||||
void **nint_ptr, const void *ptr, size_t size) {
|
||||
asn_dec_rval_t rval = {RC_OK, 0};
|
||||
long *native = (long *)*nint_ptr;
|
||||
const uint8_t *b = ptr;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
(void)constraints;
|
||||
|
||||
if(size < 1) {
|
||||
ASN__DECODE_STARVED;
|
||||
}
|
||||
|
||||
if((*b & 0x80) == 0) {
|
||||
/*
|
||||
* X.696 (08/2015) #11.2 Short form for Enumerated.
|
||||
*/
|
||||
if(!native) {
|
||||
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
*native = *b;
|
||||
rval.consumed = 1;
|
||||
} else {
|
||||
/*
|
||||
* X.696 (08/2015) #11.4 Long form for Enumerated.
|
||||
*/
|
||||
size_t length = *b & 0x7f;
|
||||
const uint8_t *bend;
|
||||
long value;
|
||||
|
||||
if(length < 1 || length > sizeof(*native)) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
if((1 + length) > size) {
|
||||
ASN__DECODE_STARVED;
|
||||
}
|
||||
b++;
|
||||
bend = b + length;
|
||||
value = (*b & 0x80) ? -1 : 0; /* Determine sign */
|
||||
for(; b < bend; b++)
|
||||
value = (value << 8) | *b;
|
||||
|
||||
if(value < 0) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
if(specs && specs->field_unsigned) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if(!native) {
|
||||
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
*native = value;
|
||||
|
||||
rval.consumed = (1 + length);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode as Canonical OER.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
NativeEnumerated_encode_oer(asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints,
|
||||
void *sptr, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
asn_enc_rval_t er = {0, td, sptr};
|
||||
long native;
|
||||
|
||||
(void)constraints;
|
||||
|
||||
if(!sptr) ASN__ENCODE_FAILED;
|
||||
|
||||
native = *(const long *)sptr;
|
||||
|
||||
if(native >= 0 && native <= 127) {
|
||||
/* #11.2 Short form */
|
||||
uint8_t b = native;
|
||||
er.encoded = 1;
|
||||
if(cb(&b, er.encoded, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
ASN__ENCODED_OK(er);
|
||||
} else {
|
||||
/* #11.2 Long form */
|
||||
uint8_t buf[1 + sizeof(native)];
|
||||
uint8_t *b = &buf[sizeof(native)]; /* Last addressable */
|
||||
long final_pattern = -1 * (native < 0);
|
||||
|
||||
for(;;) {
|
||||
*b-- = native;
|
||||
native >>= 8;
|
||||
if(native == final_pattern) {
|
||||
if(final_pattern) {
|
||||
if((b[1] & 0x80)) break;
|
||||
} else {
|
||||
if(!(b[1] & 0x80)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*b = 0x80 | (&buf[sizeof(native)] - b);
|
||||
er.encoded = 1 + (&buf[sizeof(native)] - b);
|
||||
if(cb(b, er.encoded, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ASN_DISABLE_OER_SUPPORT */
|
|
@ -75,6 +75,7 @@ OPEN_TYPE.h OPEN_TYPE_oer.c
|
|||
INTEGER_oer.c
|
||||
OCTET_STRING_oer.c
|
||||
NativeInteger_oer.c
|
||||
NativeEnumerated_oer.c
|
||||
constr_SEQUENCE_oer.c
|
||||
|
||||
CODEC-PER: # THIS IS A SPECIAL SECTION
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
@CODE_COVERAGE_RULES@
|
||||
|
||||
check_PROGRAMS = \
|
||||
check-ber_tlv_tag \
|
||||
check-length \
|
||||
check-OIDs \
|
||||
check-GeneralizedTime \
|
||||
check-OCTET_STRING \
|
||||
check-UTF8String \
|
||||
check-UTCTime \
|
||||
check-INTEGER \
|
||||
check-REAL \
|
||||
check-XER \
|
||||
check-OER-INTEGER \
|
||||
check-PER \
|
||||
check-PER-INTEGER
|
||||
check_PROGRAMS = \
|
||||
check-ber_tlv_tag \
|
||||
check-length \
|
||||
check-OIDs \
|
||||
check-GeneralizedTime \
|
||||
check-OCTET_STRING \
|
||||
check-UTF8String \
|
||||
check-UTCTime \
|
||||
check-INTEGER \
|
||||
check-REAL \
|
||||
check-XER \
|
||||
check-OER-INTEGER \
|
||||
check-OER-NativeEnumerated \
|
||||
check-PER \
|
||||
check-PER-INTEGER
|
||||
|
||||
#Filter out the coverage options from CFLAGS as we don't need
|
||||
#code coverage data for the tests executables
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <asn_codecs.h>
|
||||
#include <NativeEnumerated.h>
|
||||
|
||||
#define CHECK_DECODE(code, a, b, c) check_decode(__LINE__, code, a, b, c)
|
||||
#define CHECK_ROUNDTRIP(a) check_roundtrip(__LINE__, a);
|
||||
|
||||
static void
|
||||
check_decode(int lineno, enum asn_dec_rval_code_e code, intmax_t control, const char *buf, size_t size) {
|
||||
static char *code_s[] = { "RC_OK", "RC_WMORE", "RC_FAIL", "<error>" };
|
||||
|
||||
fprintf(stderr, "\n%d: OER decode (control %" PRIdMAX ")\n", lineno, control);
|
||||
|
||||
long value;
|
||||
long *value_ptr = &value;
|
||||
asn_dec_rval_t ret;
|
||||
|
||||
fprintf(stderr, "%d: buf[%zu]={%d, %d, ...}\n", lineno, size,
|
||||
size <= 0 ? -1 : ((const uint8_t *)buf)[0],
|
||||
size <= 1 ? -1 : ((const uint8_t *)buf)[1]);
|
||||
|
||||
ret = NativeEnumerated_decode_oer(NULL, &asn_DEF_NativeEnumerated, NULL,
|
||||
(void **)&value_ptr, buf, size);
|
||||
if(ret.code != RC_OK) {
|
||||
/* Basic OER decode does not work */
|
||||
fprintf(stderr, "%d: Failed oer_decode(ctl=%" PRIdMAX ", size=%zu)\n",
|
||||
lineno, control, size);
|
||||
if(ret.code == code) {
|
||||
fprintf(stderr, " (That was expected)\n");
|
||||
return;
|
||||
} else {
|
||||
fprintf(
|
||||
stderr, " Unexpected return code %s (%d) expected %s\n",
|
||||
code_s[(unsigned)ret.code <= RC_FAIL ? RC_FAIL : (RC_FAIL + 1)],
|
||||
(int)ret.code, code_s[code]);
|
||||
assert(ret.code == code);
|
||||
}
|
||||
} else {
|
||||
intmax_t outcome = value;
|
||||
if(outcome != control) {
|
||||
/* Decoded value is wrong */
|
||||
fprintf(stderr,
|
||||
"%d: Decode result %" PRIdMAX " is not expected %" PRIdMAX
|
||||
"\n",
|
||||
lineno, outcome, control);
|
||||
assert(outcome == control);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "%d: Decode result %" PRIdMAX "\n", lineno, control);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_data(int lineno, const uint8_t *buf, size_t size) {
|
||||
const uint8_t *p = buf;
|
||||
const uint8_t *end = buf + size;
|
||||
|
||||
fprintf(stderr, "%d: Encoded: [", lineno);
|
||||
|
||||
for(; p < end; p++) {
|
||||
fprintf(stderr, "\\x%02x", *(const unsigned char *)p);
|
||||
}
|
||||
fprintf(stderr, "] (%zu bytes)\n", size);
|
||||
}
|
||||
|
||||
static void
|
||||
check_roundtrip(int lineno, intmax_t control) {
|
||||
uint8_t tmpbuf[32];
|
||||
size_t tmpbuf_size;
|
||||
|
||||
fprintf(stderr, "\n%d: OER round-trip value %" PRIdMAX "\n", lineno, control);
|
||||
|
||||
asn_enc_rval_t er;
|
||||
asn_dec_rval_t ret;
|
||||
|
||||
long value_out = control;
|
||||
long value_in = -42;
|
||||
long *value_in_ptr = &value_in;
|
||||
|
||||
er = oer_encode_to_buffer(&asn_DEF_NativeEnumerated, NULL,
|
||||
&value_out, tmpbuf, sizeof(tmpbuf));
|
||||
if(er.encoded == -1) {
|
||||
fprintf(stderr, "%d: OER encode failed for %s\n", lineno,
|
||||
er.failed_type ? er.failed_type->name : "<none>");
|
||||
assert(er.encoded != -1);
|
||||
}
|
||||
tmpbuf_size = er.encoded;
|
||||
|
||||
dump_data(lineno, tmpbuf, tmpbuf_size);
|
||||
|
||||
ret = asn_DEF_NativeEnumerated.op->oer_decoder(0, &asn_DEF_NativeEnumerated,
|
||||
NULL, (void **)&value_in_ptr,
|
||||
tmpbuf, tmpbuf_size);
|
||||
if(ret.code != RC_OK) {
|
||||
/* Basic OER decode does not work */
|
||||
fprintf(stderr, "%d: Failed oer_decode(value=%" PRIdMAX ", size=%zu)\n",
|
||||
lineno, control, tmpbuf_size);
|
||||
assert(ret.code == 0);
|
||||
} else {
|
||||
intmax_t outcome = value_in;
|
||||
if(outcome != control) {
|
||||
/* Decoded value is wrong */
|
||||
fprintf(stderr,
|
||||
"%d: Decode result %" PRIdMAX " is not expected %" PRIdMAX
|
||||
"\n",
|
||||
lineno, outcome, control);
|
||||
assert(outcome == control);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "%d: Decode result %" PRIdMAX "\n", lineno, control);
|
||||
}
|
||||
|
||||
int
|
||||
main() {
|
||||
CHECK_DECODE(RC_WMORE, 0, "", 0);
|
||||
CHECK_DECODE(RC_OK, 0, "\x00", 1);
|
||||
CHECK_DECODE(RC_FAIL, 0, "\x00", 1);
|
||||
CHECK_DECODE(RC_WMORE, 0, "", 0);
|
||||
CHECK_DECODE(RC_WMORE, 0, "", 0);
|
||||
CHECK_DECODE(RC_OK, 0, "\x00", 1);
|
||||
CHECK_DECODE(RC_OK, 0, "\x00", 1);
|
||||
|
||||
CHECK_DECODE(RC_OK, 0, "\x00", 1);
|
||||
CHECK_DECODE(RC_OK, 1, "\x01", 1);
|
||||
CHECK_DECODE(RC_FAIL, 0, "\xff", 1);
|
||||
CHECK_DECODE(RC_FAIL, 0, "\x89", 1);
|
||||
CHECK_DECODE(RC_WMORE, 0, "\x84", 1);
|
||||
CHECK_DECODE(RC_WMORE, 0, "\x84\x00", 3);
|
||||
CHECK_DECODE(RC_WMORE, 0, "\x84\x00\x00", 3);
|
||||
CHECK_DECODE(RC_WMORE, 0, "\x84\x00\x00\x00", 4);
|
||||
CHECK_DECODE(RC_OK, 0, "\x84\x00\x00\x00\x00", 5);
|
||||
CHECK_DECODE(RC_OK, 1, "\x84\x00\x00\x00\x01", 5);
|
||||
CHECK_DECODE(RC_OK, 127, "\x7f", 1);
|
||||
CHECK_DECODE(RC_OK, 127, "\x81\x7f", 2);
|
||||
CHECK_DECODE(RC_OK, 255, "\x82\x00\xff", 3);
|
||||
CHECK_DECODE(RC_OK, -1, "\x81\xff", 2);
|
||||
CHECK_DECODE(RC_OK, -1, "\x82\xff\xff", 3);
|
||||
|
||||
CHECK_DECODE(RC_OK, 1, "\x01\x00", 2);
|
||||
CHECK_DECODE(RC_OK, 1, "\x01\x01", 2);
|
||||
CHECK_DECODE(RC_OK, -1, "\x81\xff", 2);
|
||||
CHECK_DECODE(RC_WMORE, -1, "\x82\x00\xff", 2);
|
||||
|
||||
CHECK_ROUNDTRIP(0);
|
||||
CHECK_ROUNDTRIP(1);
|
||||
CHECK_ROUNDTRIP(-1);
|
||||
CHECK_ROUNDTRIP(-127);
|
||||
CHECK_ROUNDTRIP(-128);
|
||||
CHECK_ROUNDTRIP(-129);
|
||||
CHECK_ROUNDTRIP(126);
|
||||
CHECK_ROUNDTRIP(127);
|
||||
CHECK_ROUNDTRIP(128);
|
||||
CHECK_ROUNDTRIP(-65000);
|
||||
CHECK_ROUNDTRIP(65000);
|
||||
CHECK_ROUNDTRIP(65535);
|
||||
CHECK_ROUNDTRIP(-65535);
|
||||
CHECK_ROUNDTRIP(-65536);
|
||||
CHECK_ROUNDTRIP(65536);
|
||||
CHECK_ROUNDTRIP(32000);
|
||||
|
||||
for(size_t i = 0; i < 7 ; i++) {
|
||||
intmax_t value = (intmax_t)1 << i;
|
||||
CHECK_ROUNDTRIP(value);
|
||||
value = -value;
|
||||
CHECK_ROUNDTRIP(value);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < 16 ; i++) {
|
||||
intmax_t value = (intmax_t)1 << i;
|
||||
CHECK_ROUNDTRIP(value);
|
||||
value = -value;
|
||||
CHECK_ROUNDTRIP(value);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < 32 ; i++) {
|
||||
intmax_t value = (intmax_t)1 << i;
|
||||
CHECK_ROUNDTRIP(value);
|
||||
value = -value;
|
||||
CHECK_ROUNDTRIP(value);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < 8 * sizeof(intmax_t) ; i++) {
|
||||
intmax_t value = (intmax_t)1 << i;
|
||||
CHECK_ROUNDTRIP(value);
|
||||
value = -value;
|
||||
CHECK_ROUNDTRIP(value);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue